summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/rendering
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/rendering
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/rendering')
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/AbstractInlineTextBox.cpp6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.cpp21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/BidiRun.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ClipPathOperation.h22
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ClipRect.h15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ColumnInfo.h11
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.cpp2228
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/CompositingReasons.h105
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.cpp76
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.cpp1104
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h248
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FixedTableLayout.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.cpp191
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.cpp210
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.h51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.h15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/HitTestRequest.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/HitTestResult.cpp95
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/HitTestResult.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.h3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineBox.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineBox.h36
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.cpp345
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.h39
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineIterator.h130
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.cpp502
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.h32
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayerPaintingInfo.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.cpp42
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.h63
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.cpp76
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.h58
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.cpp16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutState.cpp233
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/LayoutState.h104
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/OrderIterator.cpp31
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/OrderIterator.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/Pagination.cpp67
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/Pagination.h64
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/PaintInfo.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/PartialLayoutState.h103
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderApplet.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderApplet.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBR.cpp14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBR.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBlock.cpp1820
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBlock.h323
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.cpp987
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.h162
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBlockLineLayout.cpp1282
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBox.cpp1502
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBox.h206
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.cpp415
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.h59
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderButton.cpp14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderButton.h27
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderCounter.cpp26
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderCounter.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp127
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.cpp12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.cpp106
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.h24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.cpp15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.cpp34
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.cpp323
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.h36
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.cpp678
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.h120
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFrame.cpp17
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFrame.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.cpp37
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.h24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.cpp40
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.cpp23
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.h11
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderGrid.cpp769
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderGrid.h51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.cpp33
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.cpp94
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp201
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImage.h25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.h22
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderInline.cpp156
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderInline.h27
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.cpp102
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.h55
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayer.cpp1991
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayer.h438
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.cpp114
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.h91
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.cpp244
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.h41
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.cpp2605
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.h372
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.cpp47
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.h18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.cpp78
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.h17
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.cpp174
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.h25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.cpp715
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.h43
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.cpp434
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.h102
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNodeIterator.h1
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.cpp43
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderListBox.cpp299
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderListBox.h69
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderListItem.cpp196
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderListItem.h25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.cpp64
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.h28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.cpp20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMedia.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMedia.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.cpp11
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.h3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.cpp15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.h1
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.cpp205
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.h29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMeter.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMeter.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.cpp200
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.h83
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.cpp294
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.h105
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.cpp351
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.h161
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.cpp108
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.h74
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.cpp730
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.h144
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderObject.cpp1497
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderObject.h492
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderObjectChildList.cpp27
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderOverflow.h10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderPart.cpp47
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderPart.h10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderProgress.cpp12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderProgress.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRegion.cpp495
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRegion.h130
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.cpp63
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.h68
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.cpp166
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.h32
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderReplica.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderReplica.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRuby.cpp30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRuby.h29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.cpp14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.cpp24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.h24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.cpp15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.h26
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.cpp33
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.h31
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.cpp1
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderSelectionInfo.h30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderSlider.cpp19
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderSlider.h9
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTable.cpp366
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTable.h66
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.cpp92
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.h75
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.h24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.cpp113
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.h67
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.cpp374
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.h41
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderText.cpp245
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderText.h37
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.h37
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.h10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.cpp149
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.h39
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTheme.cpp223
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTheme.h44
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.cpp23
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.cpp51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.h37
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.h77
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm175
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.h92
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.cpp660
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.h114
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.cpp149
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.cpp9
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.h1
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderVideo.cpp34
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderVideo.h30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderView.cpp590
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderView.h268
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderWidget.cpp223
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderWidget.h25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderWordBreak.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.cpp279
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ScrollAlignment.cpp (renamed from chromium/third_party/WebKit/Source/core/rendering/ScrollBehavior.cpp)44
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/ScrollAlignment.h (renamed from chromium/third_party/WebKit/Source/core/rendering/ScrollBehavior.h)34
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.cpp288
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.h48
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/TrailingFloatsRootInlineBox.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.cpp214
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.h76
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.cpp2246
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.h (renamed from chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.h)240
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMappingPtr.h (renamed from chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMappingPtr.h)0
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.cpp94
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.h49
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.cpp279
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.h93
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.cpp236
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.h47
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.cpp460
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.h70
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingState.h (renamed from chromium/third_party/WebKit/Source/core/rendering/CompositingState.h)0
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingTriggers.h (renamed from chromium/third_party/WebKit/Source/core/rendering/BidiRun.cpp)44
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.cpp124
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.h (renamed from chromium/third_party/WebKit/Source/core/rendering/RenderBoxRegionInfo.h)38
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.cpp117
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.h77
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.cpp1259
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.h280
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/BreakingContext.cpp69
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/BreakingContextInlineHeaders.h488
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.cpp114
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.h63
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/LineInfo.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/LineLayoutState.h130
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/LineWidth.cpp (renamed from chromium/third_party/WebKit/Source/core/rendering/LineWidth.cpp)159
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/LineWidth.h (renamed from chromium/third_party/WebKit/Source/core/rendering/LineWidth.h)18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/RenderTextInfo.h (renamed from chromium/third_party/WebKit/Source/core/rendering/RegionOversetState.h)30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.cpp73
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.h94
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/line/WordMeasurement.h53
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp60
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp58
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp506
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp244
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h71
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp133
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp161
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h179
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp121
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h122
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h177
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp297
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h83
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.cpp36
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.h34
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.cpp202
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.h256
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/BorderData.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/BorderValue.h29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/CachedUAStyle.h29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/CollapsedBorderValue.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/ContentData.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/CursorList.h62
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/DataEquivalency.h49
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/GridCoordinate.h85
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/GridLength.h18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/GridPosition.h27
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.cpp253
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.h125
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/GridTrackSize.h46
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.cpp21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.h11
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/NinePieceImage.cpp6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/OutlineValue.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.cpp9
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.cpp1005
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.h681
-rw-r--r--[-rwxr-xr-x]chromium/third_party/WebKit/Source/core/rendering/style/RenderStyleConstants.h93
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.cpp81
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.h103
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.cpp32
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.h44
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.cpp35
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/ShapeValue.h60
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.cpp5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleBoxData.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.cpp46
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.h193
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp86
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.h65
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleDifference.h80
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.h28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.h37
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.cpp53
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.h57
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.cpp6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.h27
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleImage.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.cpp3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.h1
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StylePendingImage.h26
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StylePendingShader.h60
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.cpp98
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.h53
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.cpp113
-rw-r--r--[-rwxr-xr-x]chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.h66
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleShader.h64
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleVariableData.h64
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.cpp24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.h42
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp43
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp41
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp19
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp42
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp48
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h17
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp59
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp137
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp28
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp68
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp71
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp61
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp218
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h22
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp30
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp33
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h16
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h15
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp239
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h66
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp136
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h11
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp19
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp114
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h46
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp45
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp69
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp79
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp350
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h45
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp93
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp111
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h23
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp116
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp72
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h2
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp180
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h5
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp154
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp81
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h12
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp14
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp53
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h3
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp50
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h4
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h13
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp29
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h24
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp238
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h38
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp25
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h8
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h12
468 files changed, 25079 insertions, 30452 deletions
diff --git a/chromium/third_party/WebKit/Source/core/rendering/AbstractInlineTextBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/AbstractInlineTextBox.cpp
index a14b4a0e876..82c182e1d9c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/AbstractInlineTextBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/AbstractInlineTextBox.cpp
@@ -41,7 +41,7 @@ AbstractInlineTextBox::InlineToAbstractInlineTextBoxHashMap* AbstractInlineTextB
PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::getOrCreate(RenderText* renderText, InlineTextBox* inlineTextBox)
{
if (!inlineTextBox)
- return 0;
+ return nullptr;
if (!gAbstractInlineTextBoxMap)
gAbstractInlineTextBoxMap = new InlineToAbstractInlineTextBoxHashMap();
@@ -76,7 +76,7 @@ void AbstractInlineTextBox::detach()
PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::nextInlineTextBox() const
{
if (!m_inlineTextBox)
- return 0;
+ return nullptr;
return getOrCreate(m_renderText, m_inlineTextBox->nextTextBox());
}
@@ -149,7 +149,7 @@ String AbstractInlineTextBox::text() const
unsigned start = m_inlineTextBox->start();
unsigned len = m_inlineTextBox->len();
if (Node* node = m_renderText->node()) {
- RefPtr<Range> range = Range::create(node->document());
+ RefPtrWillBeRawPtr<Range> range = Range::create(node->document());
range->setStart(node, start, IGNORE_EXCEPTION);
range->setEnd(node, start + len, IGNORE_EXCEPTION);
return plainText(range.get(), TextIteratorIgnoresStyleVisibility);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.cpp b/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.cpp
index 2c290c68fb1..eec5a0cd9f6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "core/rendering/AutoTableLayout.h"
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/RenderTable.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderTableCol.h"
@@ -65,7 +66,7 @@ void AutoTableLayout::recalcColumn(unsigned effCol)
if (current.inColSpan || !cell)
continue;
- bool cellHasContent = cell->children()->firstChild() || cell->style()->hasBorder() || cell->style()->hasPadding();
+ bool cellHasContent = cell->children()->firstChild() || cell->style()->hasBorder() || cell->style()->hasPadding() || cell->style()->hasBackground();
if (cellHasContent)
columnLayout.emptyCellsOnly = false;
@@ -207,6 +208,8 @@ static bool shouldScaleColumns(RenderTable* table)
void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth)
{
+ FastTextAutosizer::TableLayoutScope fastTextAutosizerTableLayoutScope(m_table);
+
fullRecalc();
int spanMaxLogicalWidth = calcEffectiveLogicalWidth();
@@ -247,8 +250,22 @@ void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, Layout
void AutoTableLayout::applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
{
Length tableLogicalWidth = m_table->style()->logicalWidth();
- if (tableLogicalWidth.isFixed() && tableLogicalWidth.isPositive())
+ if (tableLogicalWidth.isFixed() && tableLogicalWidth.isPositive()) {
+ // |minWidth| is the result of measuring the intrinsic content's size. Keep it to
+ // make sure we are *never* smaller than the actual content.
+ LayoutUnit minContentWidth = minWidth;
+ // FIXME: This line looks REALLY suspicious as it could allow the minimum
+ // preferred logical width to be smaller than the table content. This has
+ // to be cross-checked against other browsers.
minWidth = maxWidth = max<int>(minWidth, tableLogicalWidth.value());
+
+ const Length& styleMaxLogicalWidth = m_table->style()->logicalMaxWidth();
+ if (styleMaxLogicalWidth.isFixed() && !styleMaxLogicalWidth.isNegative()) {
+ minWidth = min<int>(minWidth, styleMaxLogicalWidth.value());
+ minWidth = max(minWidth, minContentWidth);
+ maxWidth = minWidth;
+ }
+ }
}
/*
diff --git a/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.h b/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.h
index dfdd985d842..9336d0f15a5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/AutoTableLayout.h
@@ -34,7 +34,7 @@ class RenderTableCell;
class AutoTableLayout FINAL : public TableLayout {
public:
AutoTableLayout(RenderTable*);
- ~AutoTableLayout();
+ virtual ~AutoTableLayout();
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) OVERRIDE;
virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/BidiRun.h b/chromium/third_party/WebKit/Source/core/rendering/BidiRun.h
index 85f8f4a1a1c..cd743385c06 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/BidiRun.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/BidiRun.h
@@ -41,13 +41,8 @@ struct BidiRun : BidiCharacterRun {
{
// Stored in base class to save space.
m_hasHyphen = false;
- m_startsSegment = false;
}
- // BidiRuns are allocated out of the rendering partition.
- void* operator new(size_t);
- void operator delete(void*);
-
BidiRun* next() { return static_cast<BidiRun*>(m_next); }
RenderObject* object() { return m_object; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ClipPathOperation.h b/chromium/third_party/WebKit/Source/core/rendering/ClipPathOperation.h
index 7d50a10e4fd..bf64113d848 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ClipPathOperation.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/ClipPathOperation.h
@@ -63,15 +63,15 @@ protected:
OperationType m_type;
};
-class ReferenceClipPathOperation : public ClipPathOperation {
+class ReferenceClipPathOperation FINAL : public ClipPathOperation {
public:
- static PassRefPtr<ReferenceClipPathOperation> create(const String& url, const String& fragment)
+ static PassRefPtr<ReferenceClipPathOperation> create(const String& url, const AtomicString& fragment)
{
return adoptRef(new ReferenceClipPathOperation(url, fragment));
}
const String& url() const { return m_url; }
- const String& fragment() const { return m_fragment; }
+ const AtomicString& fragment() const { return m_fragment; }
private:
virtual bool operator==(const ClipPathOperation& o) const OVERRIDE
@@ -79,7 +79,7 @@ private:
return isSameType(o) && m_url == static_cast<const ReferenceClipPathOperation&>(o).m_url;
}
- ReferenceClipPathOperation(const String& url, const String& fragment)
+ ReferenceClipPathOperation(const String& url, const AtomicString& fragment)
: ClipPathOperation(REFERENCE)
, m_url(url)
, m_fragment(fragment)
@@ -87,12 +87,12 @@ private:
}
String m_url;
- String m_fragment;
+ AtomicString m_fragment;
};
DEFINE_TYPE_CASTS(ReferenceClipPathOperation, ClipPathOperation, op, op->type() == ClipPathOperation::REFERENCE, op.type() == ClipPathOperation::REFERENCE);
-class ShapeClipPathOperation : public ClipPathOperation {
+class ShapeClipPathOperation FINAL : public ClipPathOperation {
public:
static PassRefPtr<ShapeClipPathOperation> create(PassRefPtr<BasicShape> shape)
{
@@ -111,10 +111,7 @@ public:
}
private:
- virtual bool operator==(const ClipPathOperation& o) const OVERRIDE
- {
- return isSameType(o) && m_shape == static_cast<const ShapeClipPathOperation&>(o).m_shape;
- }
+ virtual bool operator==(const ClipPathOperation&) const OVERRIDE;
ShapeClipPathOperation(PassRefPtr<BasicShape> shape)
: ClipPathOperation(SHAPE)
@@ -128,6 +125,11 @@ private:
DEFINE_TYPE_CASTS(ShapeClipPathOperation, ClipPathOperation, op, op->type() == ClipPathOperation::SHAPE, op.type() == ClipPathOperation::SHAPE);
+inline bool ShapeClipPathOperation::operator==(const ClipPathOperation& o) const
+{
+ return isSameType(o) && *m_shape == *toShapeClipPathOperation(o).m_shape;
+}
+
}
#endif // ClipPathOperation_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ClipRect.h b/chromium/third_party/WebKit/Source/core/rendering/ClipRect.h
index 8fbcebf90a6..b0bed95bb77 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ClipRect.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/ClipRect.h
@@ -179,6 +179,7 @@ private:
enum ClipRectsType {
PaintingClipRects, // Relative to painting ancestor. Used for painting.
RootRelativeClipRects, // Relative to the ancestor treated as the root (e.g. transformed layer). Used for hit testing.
+ CompositingClipRects, // Relative to the compositing ancestor. Used for updating graphics layer geometry.
AbsoluteClipRects, // Relative to the RenderView's layer. Used for compositing overlap testing.
NumCachedClipRectsTypes,
AllClipRectTypes,
@@ -195,19 +196,24 @@ struct ClipRectsCache {
public:
ClipRectsCache()
{
-#ifndef NDEBUG
for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
m_clipRectsRoot[i] = 0;
+#ifndef NDEBUG
m_scrollbarRelevancy[i] = IgnoreOverlayScrollbarSize;
- }
#endif
+ }
}
PassRefPtr<ClipRects> getClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow) { return m_clipRects[getIndex(clipRectsType, respectOverflow)]; }
- void setClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow, PassRefPtr<ClipRects> clipRects) { m_clipRects[getIndex(clipRectsType, respectOverflow)] = clipRects; }
+ void setClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow, PassRefPtr<ClipRects> clipRects, const RenderLayer* root)
+ {
+ m_clipRects[getIndex(clipRectsType, respectOverflow)] = clipRects;
+ m_clipRectsRoot[clipRectsType] = root;
+ }
+
+ const RenderLayer* clipRectsRoot(ClipRectsType clipRectsType) const { return m_clipRectsRoot[clipRectsType]; }
#ifndef NDEBUG
- const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
OverlayScrollbarSizeRelevancy m_scrollbarRelevancy[NumCachedClipRectsTypes];
#endif
@@ -220,6 +226,7 @@ private:
return index;
}
+ const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes * 2];
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ColumnInfo.h b/chromium/third_party/WebKit/Source/core/rendering/ColumnInfo.h
index 39722819249..ddad54e1593 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ColumnInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/ColumnInfo.h
@@ -38,14 +38,12 @@ public:
: m_desiredColumnWidth(0)
, m_desiredColumnCount(1)
, m_progressionAxis(InlineAxis)
- , m_progressionIsReversed(false)
, m_columnCount(1)
, m_columnHeight(0)
, m_minimumColumnHeight(0)
, m_forcedBreaks(0)
, m_maximumDistanceBetweenForcedBreaks(0)
, m_forcedBreakOffset(0)
- , m_paginationUnit(Column)
{
}
@@ -60,9 +58,6 @@ public:
Axis progressionAxis() const { return m_progressionAxis; }
void setProgressionAxis(Axis progressionAxis) { m_progressionAxis = progressionAxis; }
- bool progressionIsReversed() const { return m_progressionIsReversed; }
- void setProgressionIsReversed(bool reversed) { m_progressionIsReversed = reversed; }
-
unsigned columnCount() const { return m_columnCount; }
LayoutUnit columnHeight() const { return m_columnHeight; }
@@ -98,15 +93,10 @@ public:
m_forcedBreakOffset = offsetFromFirstPage;
}
- enum PaginationUnit { Column, Page };
- PaginationUnit paginationUnit() const { return m_paginationUnit; }
- void setPaginationUnit(PaginationUnit paginationUnit) { m_paginationUnit = paginationUnit; }
-
private:
LayoutUnit m_desiredColumnWidth;
unsigned m_desiredColumnCount;
Axis m_progressionAxis;
- bool m_progressionIsReversed;
unsigned m_columnCount;
LayoutUnit m_columnHeight;
@@ -114,7 +104,6 @@ private:
int m_forcedBreaks; // FIXME: We will ultimately need to cache more information to balance around forced breaks properly.
LayoutUnit m_maximumDistanceBetweenForcedBreaks;
LayoutUnit m_forcedBreakOffset;
- PaginationUnit m_paginationUnit;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.cpp b/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.cpp
deleted file mode 100644
index 3358f9b4ced..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.cpp
+++ /dev/null
@@ -1,2228 +0,0 @@
-/*
- * Copyright (C) 2009, 2010, 2011 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 "core/rendering/CompositedLayerMapping.h"
-
-#include "CSSPropertyNames.h"
-#include "HTMLNames.h"
-#include "RuntimeEnabledFeatures.h"
-#include "core/animation/ActiveAnimations.h"
-#include "core/fetch/ImageResource.h"
-#include "core/html/HTMLIFrameElement.h"
-#include "core/html/HTMLMediaElement.h"
-#include "core/html/canvas/CanvasRenderingContext.h"
-#include "core/inspector/InspectorInstrumentation.h"
-#include "core/page/Chrome.h"
-#include "core/frame/FrameView.h"
-#include "core/frame/Settings.h"
-#include "core/frame/animation/AnimationController.h"
-#include "core/page/scrolling/ScrollingCoordinator.h"
-#include "core/plugins/PluginView.h"
-#include "core/rendering/FilterEffectRenderer.h"
-#include "core/rendering/RenderApplet.h"
-#include "core/rendering/RenderEmbeddedObject.h"
-#include "core/rendering/RenderIFrame.h"
-#include "core/rendering/RenderImage.h"
-#include "core/rendering/RenderLayerCompositor.h"
-#include "core/rendering/RenderLayerStackingNodeIterator.h"
-#include "core/rendering/RenderVideo.h"
-#include "core/rendering/RenderView.h"
-#include "core/rendering/animation/WebAnimationProvider.h"
-#include "core/rendering/style/KeyframeList.h"
-#include "platform/LengthFunctions.h"
-#include "platform/fonts/FontCache.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/graphics/filters/custom/CustomFilterOperation.h"
-#include "wtf/CurrentTime.h"
-#include "wtf/text/StringBuilder.h"
-
-using namespace std;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-static IntRect clipBox(RenderBox* renderer);
-
-static IntRect contentsRect(const RenderObject* renderer)
-{
- if (!renderer->isBox())
- return IntRect();
-
- return renderer->isVideo() ?
- toRenderVideo(renderer)->videoBox() :
- pixelSnappedIntRect(toRenderBox(renderer)->contentBoxRect());
-}
-
-static IntRect backgroundRect(const RenderObject* renderer)
-{
- if (!renderer->isBox())
- return IntRect();
-
- LayoutRect rect;
- const RenderBox* box = toRenderBox(renderer);
- EFillBox clip = box->style()->backgroundClip();
- switch (clip) {
- case BorderFillBox:
- rect = box->borderBoxRect();
- break;
- case PaddingFillBox:
- rect = box->paddingBoxRect();
- break;
- case ContentFillBox:
- rect = box->contentBoxRect();
- break;
- case TextFillBox:
- break;
- }
-
- return pixelSnappedIntRect(rect);
-}
-
-static inline bool isAcceleratedCanvas(const RenderObject* renderer)
-{
- if (renderer->isCanvas()) {
- HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
- if (CanvasRenderingContext* context = canvas->renderingContext())
- return context->isAccelerated();
- }
- return false;
-}
-
-static bool hasBoxDecorations(const RenderStyle* style)
-{
- return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
-}
-
-static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
-{
- return hasBoxDecorations(style) || style->hasBackgroundImage();
-}
-
-static bool contentLayerSupportsDirectBackgroundComposition(const RenderObject* renderer)
-{
- // No support for decorations - border, border-radius or outline.
- // Only simple background - solid color or transparent.
- if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
- return false;
-
- // If there is no background, there is nothing to support.
- if (!renderer->style()->hasBackground())
- return true;
-
- // Simple background that is contained within the contents rect.
- return contentsRect(renderer).contains(backgroundRect(renderer));
-}
-
-static inline bool isAcceleratedContents(RenderObject* renderer)
-{
- return isAcceleratedCanvas(renderer)
- || (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing())
- || renderer->isVideo();
-}
-
-// Get the scrolling coordinator in a way that works inside CompositedLayerMapping's destructor.
-static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer* layer)
-{
- Page* page = layer->renderer()->frame()->page();
- if (!page)
- return 0;
-
- return page->scrollingCoordinator();
-}
-
-CompositedLayerMapping::CompositedLayerMapping(RenderLayer* layer)
- : m_owningLayer(layer)
- , m_animationProvider(adoptPtr(new WebAnimationProvider))
- , m_artificiallyInflatedBounds(false)
- , m_boundsConstrainedByClipping(false)
- , m_isMainFrameRenderViewLayer(false)
- , m_requiresOwnBackingStoreForIntrinsicReasons(true)
- , m_requiresOwnBackingStoreForAncestorReasons(true)
- , m_canCompositeFilters(false)
- , m_backgroundLayerPaintsFixedRootBackground(false)
-{
- if (layer->isRootLayer() && renderer()->frame()->isMainFrame())
- m_isMainFrameRenderViewLayer = true;
-
- createPrimaryGraphicsLayer();
-}
-
-CompositedLayerMapping::~CompositedLayerMapping()
-{
- // Do not leave the destroyed pointer dangling on any RenderLayers that painted to this mapping's squashing layer.
- for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
- if (m_squashedLayers[i].renderLayer->groupedMapping() == this)
- m_squashedLayers[i].renderLayer->setGroupedMapping(0);
- }
-
- updateClippingLayers(false, false);
- updateOverflowControlsLayers(false, false, false);
- updateForegroundLayer(false);
- updateBackgroundLayer(false);
- updateMaskLayer(false);
- updateClippingMaskLayers(false);
- updateScrollingLayers(false);
- updateSquashingLayers(false);
- destroyGraphicsLayers();
-}
-
-PassOwnPtr<GraphicsLayer> CompositedLayerMapping::createGraphicsLayer(CompositingReasons reasons)
-{
- GraphicsLayerFactory* graphicsLayerFactory = 0;
- if (Page* page = renderer()->frame()->page())
- graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
-
- OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
-
- graphicsLayer->setCompositingReasons(reasons);
-
- return graphicsLayer.release();
-}
-
-void CompositedLayerMapping::createPrimaryGraphicsLayer()
-{
- m_graphicsLayer = createGraphicsLayer(m_owningLayer->compositingReasons());
-
-#if !OS(ANDROID)
- if (m_isMainFrameRenderViewLayer)
- m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
-#endif
-
- updateOpacity(renderer()->style());
- updateTransform(renderer()->style());
- updateFilters(renderer()->style());
-
- if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
- updateLayerBlendMode(renderer()->style());
- updateIsRootForIsolatedGroup();
- }
-}
-
-void CompositedLayerMapping::destroyGraphicsLayers()
-{
- if (m_graphicsLayer)
- m_graphicsLayer->removeFromParent();
-
- m_ancestorClippingLayer = nullptr;
- m_graphicsLayer = nullptr;
- m_foregroundLayer = nullptr;
- m_backgroundLayer = nullptr;
- m_childContainmentLayer = nullptr;
- m_maskLayer = nullptr;
- m_childClippingMaskLayer = nullptr;
-
- m_scrollingLayer = nullptr;
- m_scrollingContentsLayer = nullptr;
-}
-
-void CompositedLayerMapping::updateOpacity(const RenderStyle* style)
-{
- m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
-}
-
-void CompositedLayerMapping::updateTransform(const RenderStyle* style)
-{
- // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
- // baked into it, and we don't want that.
- TransformationMatrix t;
- if (m_owningLayer->hasTransform()) {
- style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
- makeMatrixRenderable(t, compositor()->canRender3DTransforms());
- }
-
- m_graphicsLayer->setTransform(t);
-}
-
-void CompositedLayerMapping::updateFilters(const RenderStyle* style)
-{
- bool didCompositeFilters = m_canCompositeFilters;
- m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer()->computeFilterOperations(style));
- if (didCompositeFilters != m_canCompositeFilters) {
- //
- // If filters used to be painted in software and are now painted in the compositor, we need to:
- // (1) Remove the FilterEffectRenderer, which was used for painting filters in software.
- // (2) Repaint the layer contents to remove the software-applied filter because the compositor will apply it.
- //
- // Similarly, if filters used to be painted in the compositor and are now painted in software, we need to:
- // (1) Create a FilterEffectRenderer.
- // (2) Repaint the layer contents to apply a software filter because the compositor won't apply it.
- //
- m_owningLayer->updateOrRemoveFilterEffectRenderer();
- setContentsNeedDisplay();
- }
-}
-
-void CompositedLayerMapping::updateLayerBlendMode(const RenderStyle* style)
-{
- setBlendMode(style->blendMode());
-}
-
-void CompositedLayerMapping::updateIsRootForIsolatedGroup()
-{
- bool isolate = m_owningLayer->shouldIsolateCompositedDescendants();
-
- // non stacking context layers should never isolate
- ASSERT(m_owningLayer->stackingNode()->isStackingContext() || !isolate);
-
- m_graphicsLayer->setIsRootForIsolatedGroup(isolate);
-}
-
-void CompositedLayerMapping::updateContentsOpaque()
-{
- // For non-root layers, background is always painted by the primary graphics layer.
- ASSERT(m_isMainFrameRenderViewLayer || !m_backgroundLayer);
- if (m_backgroundLayer) {
- m_graphicsLayer->setContentsOpaque(false);
- m_backgroundLayer->setContentsOpaque(m_owningLayer->backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
- } else {
- m_graphicsLayer->setContentsOpaque(m_owningLayer->backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
- }
-}
-
-static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
-{
- RenderStyle* style = renderer->style();
- return (style->transformOriginX().type() == Fixed && style->transformOriginX().value())
- || (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
-}
-
-static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
-{
- for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
- if (curr->hasTransform() || curr->needsCompositedScrolling())
- return true;
- }
-
- return false;
-}
-
-bool CompositedLayerMapping::shouldClipCompositedBounds() const
-{
- // Scrollbar layers use this layer for relative positioning, so don't clip.
- if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
- return false;
-
- if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
- return false;
-
- // Scrolled composited layers are clipped by their ancestor clipping layer,
- // so don't clip these, either.
- bool hasAncestorClippingLayer = compositor()->clippedByAncestor(m_owningLayer);
- bool clippingAncestorIsScrollParent = m_owningLayer->renderer()->containingBlock()->enclosingLayer() == m_owningLayer->ancestorScrollingLayer();
- if (hasAncestorClippingLayer && clippingAncestorIsScrollParent)
- return false;
-
- return true;
-}
-
-void CompositedLayerMapping::updateCompositedBounds()
-{
- // We need to know if we draw content in order to update our bounds (this has an effect
- // on whether or not descendands will paint into our backing). Update this value now.
- updateDrawsContent(isSimpleContainerCompositingLayer());
-
- IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
-
- // Clip to the size of the document or enclosing overflow-scroll layer.
- // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
- // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
- if (shouldClipCompositedBounds()) {
- RenderView* view = m_owningLayer->renderer()->view();
- RenderLayer* rootLayer = view->layer();
-
- LayoutRect clippingBounds;
- if (renderer()->style()->position() == FixedPosition && renderer()->container() == view)
- clippingBounds = view->frameView()->viewportConstrainedVisibleContentRect();
- else
- clippingBounds = view->unscaledDocumentRect();
-
- if (m_owningLayer != rootLayer)
- clippingBounds.intersect(m_owningLayer->backgroundClipRect(ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
-
- LayoutPoint delta;
- m_owningLayer->convertToLayerCoords(rootLayer, delta);
- clippingBounds.move(-delta.x(), -delta.y());
-
- layerBounds.intersect(pixelSnappedIntRect(clippingBounds));
- m_boundsConstrainedByClipping = true;
- } else {
- m_boundsConstrainedByClipping = false;
- }
-
- // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
- // then we need to ensure that the compositing layer has non-zero size so that we can apply
- // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
- if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
- layerBounds.setWidth(1);
- layerBounds.setHeight(1);
- m_artificiallyInflatedBounds = true;
- } else {
- m_artificiallyInflatedBounds = false;
- }
-
- setCompositedBounds(layerBounds);
-}
-
-void CompositedLayerMapping::updateAfterWidgetResize()
-{
- if (renderer()->isRenderPart()) {
- if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
- innerCompositor->frameViewDidChangeSize();
- innerCompositor->frameViewDidChangeLocation(contentsBox().location());
- }
- }
-}
-
-void CompositedLayerMapping::updateCompositingReasons()
-{
- // All other layers owned by this mapping will have the same compositing reason
- // for their lifetime, so they are initialized only when created.
- m_graphicsLayer->setCompositingReasons(m_owningLayer->compositingReasons());
-}
-
-void CompositedLayerMapping::updateAfterLayout(UpdateAfterLayoutFlags flags)
-{
- RenderLayerCompositor* layerCompositor = compositor();
- if (!layerCompositor->compositingLayersNeedRebuild()) {
- // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
- // position of this layer's GraphicsLayer depends on the position of our compositing
- // ancestor's GraphicsLayer. That cannot be determined until all the descendant
- // RenderLayers of that ancestor have been processed via updateLayerPositions().
- //
- // The solution is to update compositing children of this layer here,
- // via updateCompositingChildrenGeometry().
- updateCompositedBounds();
- layerCompositor->updateCompositingDescendantGeometry(m_owningLayer->stackingNode(), m_owningLayer, flags & CompositingChildrenOnly);
-
- if (flags & IsUpdateRoot) {
- updateGraphicsLayerGeometry();
- layerCompositor->updateRootLayerPosition();
- RenderLayerStackingNode* stackingContainer = m_owningLayer->stackingNode()->enclosingStackingContainerNode();
- if (!layerCompositor->compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != m_owningLayer->stackingNode()))
- layerCompositor->updateCompositingDescendantGeometry(stackingContainer, stackingContainer->layer(), flags & CompositingChildrenOnly);
- }
- }
-
- if (flags & NeedsFullRepaint && !paintsIntoCompositedAncestor())
- setContentsNeedDisplay();
-}
-
-bool CompositedLayerMapping::updateGraphicsLayerConfiguration()
-{
- RenderLayerCompositor* compositor = this->compositor();
- RenderObject* renderer = this->renderer();
-
- m_owningLayer->updateDescendantDependentFlags();
- m_owningLayer->stackingNode()->updateZOrderLists();
-
- bool layerConfigChanged = false;
- setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(m_owningLayer));
-
- // The background layer is currently only used for fixed root backgrounds.
- if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
- layerConfigChanged = true;
-
- if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
- layerConfigChanged = true;
-
- bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
-
- // Our scrolling layer will clip.
- if (m_owningLayer->needsCompositedScrolling())
- needsDescendentsClippingLayer = false;
-
- RenderLayer* scrollParent = m_owningLayer->scrollParent();
- bool needsAncestorClip = compositor->clippedByAncestor(m_owningLayer);
- if (scrollParent) {
- // If our containing block is our ancestor scrolling layer, then we'll already be clipped
- // to it via our scroll parent and we don't need an ancestor clipping layer.
- if (m_owningLayer->renderer()->containingBlock()->enclosingLayer() == m_owningLayer->ancestorCompositedScrollingLayer())
- needsAncestorClip = false;
- }
- if (updateClippingLayers(needsAncestorClip, needsDescendentsClippingLayer))
- layerConfigChanged = true;
-
- if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
- layerConfigChanged = true;
-
- if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling()))
- layerConfigChanged = true;
-
- updateScrollParent(scrollParent);
- updateClipParent(m_owningLayer->clipParent());
-
- if (updateSquashingLayers(!m_squashedLayers.isEmpty()))
- layerConfigChanged = true;
-
- if (layerConfigChanged)
- updateInternalHierarchy();
-
- if (updateMaskLayer(renderer->hasMask()))
- m_graphicsLayer->setMaskLayer(m_maskLayer.get());
-
- bool hasChildClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer) && (hasClippingLayer() || hasScrollingLayer());
- bool needsChildClippingMask = (renderer->style()->clipPath() || renderer->style()->hasBorderRadius()) && (hasChildClippingLayer || isAcceleratedContents(renderer));
- if (updateClippingMaskLayers(needsChildClippingMask)) {
- if (hasClippingLayer())
- clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
- else if (hasScrollingLayer())
- scrollingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
- else if (isAcceleratedContents(renderer))
- m_graphicsLayer->setContentsClippingMaskLayer(m_childClippingMaskLayer.get());
- }
-
- if (m_owningLayer->reflectionInfo()) {
- if (m_owningLayer->reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
- GraphicsLayer* reflectionLayer = m_owningLayer->reflectionInfo()->reflectionLayer()->compositedLayerMapping()->mainGraphicsLayer();
- m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
- }
- } else {
- m_graphicsLayer->setReplicatedByLayer(0);
- }
-
- updateBackgroundColor(isSimpleContainerCompositingLayer());
-
- if (isDirectlyCompositedImage())
- updateImageContents();
-
- if (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) {
- PluginView* pluginView = toPluginView(toRenderWidget(renderer)->widget());
- m_graphicsLayer->setContentsToPlatformLayer(pluginView->platformLayer());
- } else if (renderer->node() && renderer->node()->isFrameOwnerElement() && toHTMLFrameOwnerElement(renderer->node())->contentFrame()) {
- blink::WebLayer* layer = toHTMLFrameOwnerElement(renderer->node())->contentFrame()->remotePlatformLayer();
- if (layer)
- m_graphicsLayer->setContentsToPlatformLayer(layer);
- } else if (renderer->isVideo()) {
- HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer->node());
- m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer());
- } else if (isAcceleratedCanvas(renderer)) {
- HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
- if (CanvasRenderingContext* context = canvas->renderingContext())
- m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer());
- layerConfigChanged = true;
- }
- if (renderer->isRenderPart())
- layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
-
- return layerConfigChanged;
-}
-
-static IntRect clipBox(RenderBox* renderer)
-{
- LayoutRect result = PaintInfo::infiniteRect();
- if (renderer->hasOverflowClip())
- result = renderer->overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
-
- if (renderer->hasClip())
- result.intersect(renderer->clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
-
- return pixelSnappedIntRect(result);
-}
-
-void CompositedLayerMapping::updateGraphicsLayerGeometry()
-{
- // If we haven't built z-order lists yet, wait until later.
- if (m_owningLayer->stackingNode()->isStackingContainer() && m_owningLayer->stackingNode()->zOrderListsDirty())
- return;
-
- // Set transform property, if it is not animating. We have to do this here because the transform
- // is affected by the layer dimensions.
- if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()
- ? !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitTransform)
- : !renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform))
- updateTransform(renderer()->style());
-
- // Set opacity, if it is not animating.
- if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()
- ? !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyOpacity)
- : !renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity))
- updateOpacity(renderer()->style());
-
- bool isSimpleContainer = isSimpleContainerCompositingLayer();
-
- m_owningLayer->updateDescendantDependentFlags();
-
- // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
- // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
- // non-compositing visible layers.
- bool contentsVisible = m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers();
- if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && renderer()->isVideo()) {
- HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer()->node());
- if (mediaElement->isFullscreen())
- contentsVisible = false;
- }
- m_graphicsLayer->setContentsVisible(contentsVisible);
-
- RenderStyle* style = renderer()->style();
- // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
- bool preserves3D = style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection();
- m_graphicsLayer->setPreserves3D(preserves3D);
- m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
-
- RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
-
- // We compute everything relative to the enclosing compositing layer.
- IntRect ancestorCompositingBounds;
- if (compAncestor) {
- ASSERT(compAncestor->hasCompositedLayerMapping());
- ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->compositedLayerMapping()->compositedBounds());
- }
-
- IntRect localCompositingBounds = pixelSnappedIntRect(compositedBounds());
-
- IntRect relativeCompositingBounds(localCompositingBounds);
- IntPoint delta;
- m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta);
- relativeCompositingBounds.moveBy(delta);
-
- IntPoint graphicsLayerParentLocation;
- if (compAncestor && compAncestor->compositedLayerMapping()->hasClippingLayer()) {
- // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
- // position relative to it.
- IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
- graphicsLayerParentLocation = clippingBox.location();
- } else if (compAncestor) {
- graphicsLayerParentLocation = ancestorCompositingBounds.location();
- } else {
- graphicsLayerParentLocation = renderer()->view()->documentRect().location();
- }
-
- if (compAncestor && compAncestor->needsCompositedScrolling()) {
- RenderBox* renderBox = toRenderBox(compAncestor->renderer());
- IntSize scrollOffset = renderBox->scrolledContentOffset();
- IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
- graphicsLayerParentLocation = scrollOrigin - scrollOffset;
- }
-
- if (compAncestor && m_ancestorClippingLayer) {
- // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
- // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
- // for a compositing layer, rootLayer is the layer itself.
- ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
- IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions.
- ASSERT(parentClipRect != PaintInfo::infiniteRect());
- m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
- m_ancestorClippingLayer->setSize(parentClipRect.size());
-
- // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
- m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta);
-
- // The primary layer is then parented in, and positioned relative to this clipping layer.
- graphicsLayerParentLocation = parentClipRect.location();
- }
-
- FloatSize contentsSize = relativeCompositingBounds.size();
-
- m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
- m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
-
- FloatSize oldSize = m_graphicsLayer->size();
- if (oldSize != contentsSize) {
- m_graphicsLayer->setSize(contentsSize);
- // Usually invalidation will happen via layout etc, but if we've affected the layer
- // size by constraining relative to a clipping ancestor or the viewport, we
- // have to invalidate to avoid showing stretched content.
- if (m_boundsConstrainedByClipping)
- m_graphicsLayer->setNeedsDisplay();
- }
-
- // If we have a layer that clips children, position it.
- IntRect clippingBox;
- if (GraphicsLayer* clipLayer = clippingLayer()) {
- clippingBox = clipBox(toRenderBox(renderer()));
- clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
- clipLayer->setSize(clippingBox.size());
- clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
- if (m_childClippingMaskLayer && !m_scrollingLayer) {
- m_childClippingMaskLayer->setPosition(clipLayer->position());
- m_childClippingMaskLayer->setSize(clipLayer->size());
- m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer());
- }
- }
-
- if (m_maskLayer) {
- if (m_maskLayer->size() != m_graphicsLayer->size()) {
- m_maskLayer->setSize(m_graphicsLayer->size());
- m_maskLayer->setNeedsDisplay();
- }
- m_maskLayer->setPosition(FloatPoint());
- m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
- }
-
- if (m_owningLayer->hasTransform()) {
- const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
-
- // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
- IntRect layerBounds = IntRect(delta, borderBox.size());
-
- // Update properties that depend on layer dimensions
- FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
- // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
- FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
- relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
- transformOrigin.z());
- m_graphicsLayer->setAnchorPoint(anchor);
-
- RenderStyle* style = renderer()->style();
- GraphicsLayer* clipLayer = clippingLayer();
- if (style->hasPerspective()) {
- TransformationMatrix t = owningLayer()->perspectiveTransform();
-
- if (clipLayer) {
- clipLayer->setChildrenTransform(t);
- m_graphicsLayer->setChildrenTransform(TransformationMatrix());
- } else {
- m_graphicsLayer->setChildrenTransform(t);
- }
- } else {
- if (clipLayer)
- clipLayer->setChildrenTransform(TransformationMatrix());
- else
- m_graphicsLayer->setChildrenTransform(TransformationMatrix());
- }
- } else {
- m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
- }
-
- if (m_foregroundLayer) {
- FloatPoint foregroundPosition;
- FloatSize foregroundSize = contentsSize;
- IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
- if (hasClippingLayer()) {
- // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
- // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
- foregroundSize = FloatSize(clippingBox.size());
- foregroundOffset = toIntSize(clippingBox.location());
- }
-
- m_foregroundLayer->setPosition(foregroundPosition);
- if (foregroundSize != m_foregroundLayer->size()) {
- m_foregroundLayer->setSize(foregroundSize);
- m_foregroundLayer->setNeedsDisplay();
- }
- m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
- }
-
- if (m_backgroundLayer) {
- FloatPoint backgroundPosition;
- FloatSize backgroundSize = contentsSize;
- if (backgroundLayerPaintsFixedRootBackground()) {
- FrameView* frameView = toRenderView(renderer())->frameView();
- backgroundSize = frameView->visibleContentRect().size();
- }
- m_backgroundLayer->setPosition(backgroundPosition);
- if (backgroundSize != m_backgroundLayer->size()) {
- m_backgroundLayer->setSize(backgroundSize);
- m_backgroundLayer->setNeedsDisplay();
- }
- m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
- }
-
- if (m_owningLayer->reflectionInfo() && m_owningLayer->reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
- CompositedLayerMappingPtr reflectionCompositedLayerMapping = m_owningLayer->reflectionInfo()->reflectionLayer()->compositedLayerMapping();
- reflectionCompositedLayerMapping->updateGraphicsLayerGeometry();
-
- // The reflection layer has the bounds of m_owningLayer->reflectionLayer(),
- // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
- FloatRect layerBounds = compositedBounds();
- FloatRect reflectionLayerBounds = reflectionCompositedLayerMapping->compositedBounds();
- reflectionCompositedLayerMapping->mainGraphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
- }
-
- if (m_scrollingLayer) {
- ASSERT(m_scrollingContentsLayer);
- RenderBox* renderBox = toRenderBox(renderer());
- IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
- // FIXME: We should make RenderBox::clientBoxRect consider scrollbar placement.
- if (style->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
- clientBox.move(renderBox->verticalScrollbarWidth(), 0);
-
- IntSize adjustedScrollOffset = m_owningLayer->scrollableArea()->adjustedScrollOffset();
- m_scrollingLayer->setPosition(FloatPoint(clientBox.location() - localCompositingBounds.location()));
- m_scrollingLayer->setSize(clientBox.size());
-
- IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
- m_scrollingLayer->setOffsetFromRenderer(-toIntSize(clientBox.location()));
-
- if (m_childClippingMaskLayer) {
- m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
- m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
- m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
- }
-
- bool clientBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
-
- IntSize scrollSize(renderBox->scrollWidth(), renderBox->scrollHeight());
- if (scrollSize != m_scrollingContentsLayer->size() || clientBoxOffsetChanged)
- m_scrollingContentsLayer->setNeedsDisplay();
-
- IntSize scrollingContentsOffset = toIntSize(clientBox.location() - adjustedScrollOffset);
- if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) {
- bool scrollingCoordinatorHandlesOffset = compositor()->scrollingLayerDidChange(m_owningLayer);
-
- if (scrollingCoordinatorHandlesOffset)
- m_scrollingContentsLayer->setPosition(-m_owningLayer->scrollableArea()->scrollOrigin());
- else
- m_scrollingContentsLayer->setPosition(FloatPoint(-adjustedScrollOffset));
- }
-
- m_scrollingContentsLayer->setSize(scrollSize);
- // FIXME: The paint offset and the scroll offset should really be separate concepts.
- m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
-
- if (m_foregroundLayer) {
- if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
- m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
- m_foregroundLayer->setNeedsDisplay();
- m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
- }
- }
-
- if (m_squashingLayer) {
- ASSERT(compositor()->layerSquashingEnabled());
-
- IntRect totalSquashBounds;
- for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
- IntRect squashedBounds = compositor()->calculateCompositedBounds(m_squashedLayers[i].renderLayer, m_squashedLayers[i].renderLayer);
-
- // Store the composited bounds before applying the offset.
- // FIXME: consider whether it is more efficient or clarifies the math to store the compositedBounds after applying the offset.
- m_squashedLayers[i].compositedBounds = squashedBounds;
-
- squashedBounds.move(m_squashedLayers[i].offsetFromBackingRoot);
- totalSquashBounds.unite(squashedBounds);
- }
-
- IntPoint squashLayerPosition;
- // FIXME: this logic needs to update depending on what "containment" layers are added to CompositedLayerMapping due to other changes
- if (m_ancestorClippingLayer) {
- squashLayerPosition = IntPoint(m_ancestorClippingLayer->position().x() + totalSquashBounds.location().x(),
- m_ancestorClippingLayer->position().y() + totalSquashBounds.location().y());
- } else {
- squashLayerPosition = IntPoint(m_graphicsLayer->position().x() + totalSquashBounds.location().x(),
- m_graphicsLayer->position().y() + totalSquashBounds.location().y());
- }
-
- m_squashingLayer->setPosition(squashLayerPosition);
- m_squashingLayer->setSize(totalSquashBounds.size());
-
- // Now that the position of the squashing layer is known, update the offsets for each squashed RenderLayer.
- for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
- m_squashedLayers[i].offsetFromRenderer = IntSize(-m_squashedLayers[i].offsetFromBackingRoot.width() - m_graphicsLayer->position().x() + m_squashingLayer->position().x(),
- -m_squashedLayers[i].offsetFromBackingRoot.height() - m_graphicsLayer->position().y() + m_squashingLayer->position().y());
-
- // FIXME: find a better design to avoid this redundant value - most likely it will make
- // sense to move the paint task info into RenderLayer's m_compositingProperties.
- m_squashedLayers[i].renderLayer->setOffsetFromSquashingLayerOrigin(m_squashedLayers[i].offsetFromRenderer);
- }
- }
-
- if (m_owningLayer->scrollableArea())
- m_owningLayer->scrollableArea()->positionOverflowControls();
-
- // We can't make this call in RenderLayerCompositor::allocateOrClearCompositedLayerMapping
- // since it depends on whether compAncestor draws content, which gets updated later.
- updateRequiresOwnBackingStoreForAncestorReasons(compAncestor);
-
- if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
- updateLayerBlendMode(style);
- updateIsRootForIsolatedGroup();
- }
-
- updateContentsRect(isSimpleContainer);
- updateBackgroundColor(isSimpleContainer);
- updateDrawsContent(isSimpleContainer);
- updateContentsOpaque();
- updateAfterWidgetResize();
- registerScrollingLayers();
-
- updateCompositingReasons();
-}
-
-void CompositedLayerMapping::registerScrollingLayers()
-{
- // Register fixed position layers and their containers with the scrolling coordinator.
- ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
- if (!scrollingCoordinator)
- return;
-
- compositor()->updateViewportConstraintStatus(m_owningLayer);
-
- scrollingCoordinator->updateLayerPositionConstraint(m_owningLayer);
-
- // Page scale is applied as a transform on the root render view layer. Because the scroll
- // layer is further up in the hierarchy, we need to avoid marking the root render view
- // layer as a container.
- bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer();
- // FIXME: we should make certain that childForSuperLayers will never be the m_squashingContainmentLayer here
- scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
-}
-
-void CompositedLayerMapping::updateInternalHierarchy()
-{
- // m_foregroundLayer has to be inserted in the correct order with child layers,
- // so it's not inserted here.
- if (m_ancestorClippingLayer)
- m_ancestorClippingLayer->removeAllChildren();
-
- m_graphicsLayer->removeFromParent();
-
- if (m_ancestorClippingLayer)
- m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
-
- if (m_childContainmentLayer) {
- m_childContainmentLayer->removeFromParent();
- m_graphicsLayer->addChild(m_childContainmentLayer.get());
- }
-
- if (m_scrollingLayer) {
- GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
- m_scrollingLayer->removeFromParent();
- superlayer->addChild(m_scrollingLayer.get());
- }
-
- // The clip for child layers does not include space for overflow controls, so they exist as
- // siblings of the clipping layer if we have one. Normal children of this layer are set as
- // children of the clipping layer.
- if (m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar->removeFromParent();
- m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
- }
- if (m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar->removeFromParent();
- m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
- }
- if (m_layerForScrollCorner) {
- m_layerForScrollCorner->removeFromParent();
- m_graphicsLayer->addChild(m_layerForScrollCorner.get());
- }
-
- // The squashing containment layer, if it exists, becomes a no-op parent.
- if (m_squashingLayer) {
- ASSERT(compositor()->layerSquashingEnabled());
- ASSERT(m_squashingContainmentLayer);
-
- m_squashingContainmentLayer->removeAllChildren();
-
- if (m_ancestorClippingLayer)
- m_squashingContainmentLayer->addChild(m_ancestorClippingLayer.get());
- else
- m_squashingContainmentLayer->addChild(m_graphicsLayer.get());
-
- m_squashingContainmentLayer->addChild(m_squashingLayer.get());
- }
-}
-
-void CompositedLayerMapping::updateContentsRect(bool isSimpleContainer)
-{
- IntRect contentsRect;
- if (isSimpleContainer && renderer()->hasBackground())
- contentsRect = backgroundBox();
- else
- contentsRect = contentsBox();
-
- m_graphicsLayer->setContentsRect(contentsRect);
-}
-
-void CompositedLayerMapping::updateDrawsContent(bool isSimpleContainer)
-{
- if (m_scrollingLayer) {
- // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
- // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
- // m_scrollingLayer never has backing store.
- // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
- bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground();
- m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
-
- bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
- m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
- return;
- }
-
- bool hasPaintedContent = containsPaintedContent(isSimpleContainer);
- if (hasPaintedContent && isAcceleratedCanvas(renderer())) {
- CanvasRenderingContext* context = toHTMLCanvasElement(renderer()->node())->renderingContext();
- // Content layer may be null if context is lost.
- if (blink::WebLayer* contentLayer = context->platformLayer()) {
- Color bgColor;
- if (contentLayerSupportsDirectBackgroundComposition(renderer())) {
- bgColor = rendererBackgroundColor();
- hasPaintedContent = false;
- }
- contentLayer->setBackgroundColor(bgColor.rgb());
- }
- }
-
- // FIXME: we could refine this to only allocate backings for one of these layers if possible.
- m_graphicsLayer->setDrawsContent(hasPaintedContent);
- if (m_foregroundLayer)
- m_foregroundLayer->setDrawsContent(hasPaintedContent);
-
- if (m_backgroundLayer)
- m_backgroundLayer->setDrawsContent(hasPaintedContent);
-}
-
-// Return true if the layers changed.
-bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
-{
- bool layersChanged = false;
-
- if (needsAncestorClip) {
- if (!m_ancestorClippingLayer) {
- m_ancestorClippingLayer = createGraphicsLayer(CompositingReasonLayerForClip);
- m_ancestorClippingLayer->setMasksToBounds(true);
- layersChanged = true;
- }
- } else if (m_ancestorClippingLayer) {
- m_ancestorClippingLayer->removeFromParent();
- m_ancestorClippingLayer = nullptr;
- layersChanged = true;
- }
-
- if (needsDescendantClip) {
- // We don't need a child containment layer if we're the main frame render view
- // layer. It's redundant as the frame clip above us will handle this clipping.
- if (!m_childContainmentLayer && !m_isMainFrameRenderViewLayer) {
- m_childContainmentLayer = createGraphicsLayer(CompositingReasonLayerForClip);
- m_childContainmentLayer->setMasksToBounds(true);
- layersChanged = true;
- }
- } else if (hasClippingLayer()) {
- m_childContainmentLayer->removeFromParent();
- m_childContainmentLayer = nullptr;
- layersChanged = true;
- }
-
- return layersChanged;
-}
-
-void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
-{
- m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
-}
-
-bool CompositedLayerMapping::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
-{
- bool horizontalScrollbarLayerChanged = false;
- if (needsHorizontalScrollbarLayer) {
- if (!m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar = createGraphicsLayer(CompositingReasonLayerForScrollbar);
- horizontalScrollbarLayerChanged = true;
- }
- } else if (m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar = nullptr;
- horizontalScrollbarLayerChanged = true;
- }
-
- bool verticalScrollbarLayerChanged = false;
- if (needsVerticalScrollbarLayer) {
- if (!m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar = createGraphicsLayer(CompositingReasonLayerForScrollbar);
- verticalScrollbarLayerChanged = true;
- }
- } else if (m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar = nullptr;
- verticalScrollbarLayerChanged = true;
- }
-
- bool scrollCornerLayerChanged = false;
- if (needsScrollCornerLayer) {
- if (!m_layerForScrollCorner) {
- m_layerForScrollCorner = createGraphicsLayer(CompositingReasonLayerForScrollbar);
- scrollCornerLayerChanged = true;
- }
- } else if (m_layerForScrollCorner) {
- m_layerForScrollCorner = nullptr;
- scrollCornerLayerChanged = true;
- }
-
- if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
- if (horizontalScrollbarLayerChanged)
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer->scrollableArea(), HorizontalScrollbar);
- if (verticalScrollbarLayerChanged)
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer->scrollableArea(), VerticalScrollbar);
- }
-
- return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
-}
-
-void CompositedLayerMapping::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
-{
- IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
- if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
- Scrollbar* hBar = m_owningLayer->scrollableArea()->horizontalScrollbar();
- if (hBar) {
- layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
- layer->setSize(hBar->frameRect().size());
- if (layer->hasContentsLayer())
- layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
- }
- layer->setDrawsContent(hBar && !layer->hasContentsLayer());
- }
-
- if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
- Scrollbar* vBar = m_owningLayer->scrollableArea()->verticalScrollbar();
- if (vBar) {
- layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
- layer->setSize(vBar->frameRect().size());
- if (layer->hasContentsLayer())
- layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
- }
- layer->setDrawsContent(vBar && !layer->hasContentsLayer());
- }
-
- if (GraphicsLayer* layer = layerForScrollCorner()) {
- const LayoutRect& scrollCornerAndResizer = m_owningLayer->scrollableArea()->scrollCornerAndResizerRect();
- layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
- layer->setSize(scrollCornerAndResizer.size());
- layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
- }
-}
-
-bool CompositedLayerMapping::hasUnpositionedOverflowControlsLayers() const
-{
- if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
- if (!layer->drawsContent())
- return true;
- }
-
- if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
- if (!layer->drawsContent())
- return true;
- }
-
- if (GraphicsLayer* layer = layerForScrollCorner()) {
- if (!layer->drawsContent())
- return true;
- }
-
- return false;
-}
-
-bool CompositedLayerMapping::updateForegroundLayer(bool needsForegroundLayer)
-{
- bool layerChanged = false;
- if (needsForegroundLayer) {
- if (!m_foregroundLayer) {
- m_foregroundLayer = createGraphicsLayer(CompositingReasonLayerForForeground);
- m_foregroundLayer->setDrawsContent(true);
- m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
- layerChanged = true;
- }
- } else if (m_foregroundLayer) {
- m_foregroundLayer->removeFromParent();
- m_foregroundLayer = nullptr;
- layerChanged = true;
- }
-
- if (layerChanged)
- m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
-
- return layerChanged;
-}
-
-bool CompositedLayerMapping::updateBackgroundLayer(bool needsBackgroundLayer)
-{
- bool layerChanged = false;
- if (needsBackgroundLayer) {
- if (!m_backgroundLayer) {
- m_backgroundLayer = createGraphicsLayer(CompositingReasonLayerForBackground);
- m_backgroundLayer->setDrawsContent(true);
- m_backgroundLayer->setAnchorPoint(FloatPoint3D());
- m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
-#if !OS(ANDROID)
- m_backgroundLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
- m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(false);
-#endif
- layerChanged = true;
- }
- } else {
- if (m_backgroundLayer) {
- m_backgroundLayer->removeFromParent();
- m_backgroundLayer = nullptr;
-#if !OS(ANDROID)
- m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
-#endif
- layerChanged = true;
- }
- }
-
- if (layerChanged && !m_owningLayer->renderer()->documentBeingDestroyed())
- compositor()->rootFixedBackgroundsChanged();
-
- return layerChanged;
-}
-
-bool CompositedLayerMapping::updateMaskLayer(bool needsMaskLayer)
-{
- bool layerChanged = false;
- if (needsMaskLayer) {
- if (!m_maskLayer) {
- m_maskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
- m_maskLayer->setDrawsContent(true);
- m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
- layerChanged = true;
- }
- } else if (m_maskLayer) {
- m_maskLayer = nullptr;
- layerChanged = true;
- }
-
- if (layerChanged)
- m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
-
- return layerChanged;
-}
-
-bool CompositedLayerMapping::updateClippingMaskLayers(bool needsChildClippingMaskLayer)
-{
- bool layerChanged = false;
- if (needsChildClippingMaskLayer) {
- if (!m_childClippingMaskLayer) {
- m_childClippingMaskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
- m_childClippingMaskLayer->setDrawsContent(true);
- m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
- layerChanged = true;
- }
- } else if (m_childClippingMaskLayer) {
- m_childClippingMaskLayer = nullptr;
- layerChanged = true;
- }
- return layerChanged;
-}
-
-bool CompositedLayerMapping::updateScrollingLayers(bool needsScrollingLayers)
-{
- ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
-
- bool layerChanged = false;
- if (needsScrollingLayers) {
- if (!m_scrollingLayer) {
- // Outer layer which corresponds with the scroll view.
- m_scrollingLayer = createGraphicsLayer(CompositingReasonLayerForClip);
- m_scrollingLayer->setDrawsContent(false);
- m_scrollingLayer->setMasksToBounds(true);
-
- // Inner layer which renders the content that scrolls.
- m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContainer);
- m_scrollingContentsLayer->setDrawsContent(true);
- GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
- if (!m_foregroundLayer)
- paintPhase |= GraphicsLayerPaintForeground;
- m_scrollingContentsLayer->setPaintingPhase(paintPhase);
- m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
-
- layerChanged = true;
- if (scrollingCoordinator)
- scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer->scrollableArea());
- }
- } else if (m_scrollingLayer) {
- m_scrollingLayer = nullptr;
- m_scrollingContentsLayer = nullptr;
- layerChanged = true;
- if (scrollingCoordinator)
- scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer->scrollableArea());
- }
-
- if (layerChanged) {
- updateInternalHierarchy();
- m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
- m_graphicsLayer->setNeedsDisplay();
- if (renderer()->view())
- compositor()->scrollingLayerDidChange(m_owningLayer);
- }
-
- return layerChanged;
-}
-
-static void updateScrollParentForGraphicsLayer(GraphicsLayer* layer, GraphicsLayer* topmostLayer, RenderLayer* scrollParent, ScrollingCoordinator* scrollingCoordinator)
-{
- if (!layer)
- return;
-
- // Only the topmost layer has a scroll parent. All other layers have a null scroll parent.
- if (layer != topmostLayer)
- scrollParent = 0;
-
- scrollingCoordinator->updateScrollParentForGraphicsLayer(layer, scrollParent);
-}
-
-void CompositedLayerMapping::updateScrollParent(RenderLayer* scrollParent)
-{
-
- if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
- GraphicsLayer* topmostLayer = childForSuperlayers();
- updateScrollParentForGraphicsLayer(m_squashingContainmentLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
- updateScrollParentForGraphicsLayer(m_ancestorClippingLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
- updateScrollParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
- }
-}
-
-void CompositedLayerMapping::updateClipParent(RenderLayer* clipParent)
-{
- if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer))
- scrollingCoordinator->updateClipParentForGraphicsLayer(m_graphicsLayer.get(), clipParent);
-}
-
-bool CompositedLayerMapping::updateSquashingLayers(bool needsSquashingLayers)
-{
- bool layersChanged = false;
-
- if (needsSquashingLayers) {
- ASSERT(compositor()->layerSquashingEnabled());
-
- if (!m_squashingLayer) {
- ASSERT(!m_squashingContainmentLayer);
-
- m_squashingLayer = createGraphicsLayer(CompositingReasonOverlap);
- m_squashingLayer->setDrawsContent(true);
- m_squashingLayer->setNeedsDisplay();
- layersChanged = true;
-
- // FIXME: containment layer needs a new CompositingReason, CompositingReasonOverlap is not appropriate.
- m_squashingContainmentLayer = createGraphicsLayer(CompositingReasonOverlap);
- // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
- bool preserves3D = renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection();
- m_squashingContainmentLayer->setPreserves3D(preserves3D);
- layersChanged = true;
- }
-
- ASSERT(m_squashingLayer && m_squashingContainmentLayer);
- } else {
- if (m_squashingLayer) {
- m_squashingLayer->removeFromParent();
- m_squashingLayer = nullptr;
- layersChanged = true;
- // FIXME: do we need to invalidate something here?
-
- ASSERT(m_squashingContainmentLayer);
- m_squashingContainmentLayer->removeFromParent();
- m_squashingContainmentLayer = nullptr;
- layersChanged = true;
- }
-
- ASSERT(!m_squashingLayer && !m_squashingContainmentLayer);
- }
-
- return layersChanged;
-}
-
-GraphicsLayerPaintingPhase CompositedLayerMapping::paintingPhaseForPrimaryLayer() const
-{
- unsigned phase = 0;
- if (!m_backgroundLayer)
- phase |= GraphicsLayerPaintBackground;
- if (!m_foregroundLayer)
- phase |= GraphicsLayerPaintForeground;
- if (!m_maskLayer)
- phase |= GraphicsLayerPaintMask;
-
- if (m_scrollingContentsLayer) {
- phase &= ~GraphicsLayerPaintForeground;
- phase |= GraphicsLayerPaintCompositedScroll;
- }
-
- if (m_owningLayer->compositingReasons() & CompositingReasonOverflowScrollingParent)
- phase |= GraphicsLayerPaintCompositedScroll;
-
- return static_cast<GraphicsLayerPaintingPhase>(phase);
-}
-
-float CompositedLayerMapping::compositingOpacity(float rendererOpacity) const
-{
- float finalOpacity = rendererOpacity;
-
- for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
- // We only care about parents that are stacking contexts.
- // Recall that opacity creates stacking context.
- if (!curr->stackingNode()->isStackingContainer())
- continue;
-
- // If we found a composited layer, regardless of whether it actually
- // paints into it, we want to compute opacity relative to it. So we can
- // break here.
- //
- // FIXME: with grouped backings, a composited descendant will have to
- // continue past the grouped (squashed) layers that its parents may
- // contribute to. This whole confusion can be avoided by specifying
- // explicitly the composited ancestor where we would stop accumulating
- // opacity.
- if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == HasOwnBackingButPaintsIntoAncestor)
- break;
-
- finalOpacity *= curr->renderer()->opacity();
- }
-
- return finalOpacity;
-}
-
-Color CompositedLayerMapping::rendererBackgroundColor() const
-{
- RenderObject* backgroundRenderer = renderer();
- if (backgroundRenderer->isRoot())
- backgroundRenderer = backgroundRenderer->rendererForRootBackground();
-
- return backgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
-}
-
-void CompositedLayerMapping::updateBackgroundColor(bool isSimpleContainer)
-{
- Color backgroundColor = rendererBackgroundColor();
- if (isSimpleContainer) {
- m_graphicsLayer->setContentsToSolidColor(backgroundColor);
- m_graphicsLayer->setBackgroundColor(Color());
- } else {
- // An unset (invalid) color will remove the solid color.
- m_graphicsLayer->setContentsToSolidColor(Color());
- m_graphicsLayer->setBackgroundColor(backgroundColor);
- }
-}
-
-static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer)
-{
- if (renderer->hasClip())
- return false;
-
- if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
- return false;
-
- // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
- if (renderer->style()->backgroundComposite() != CompositeSourceOver)
- return false;
-
- if (renderer->style()->backgroundClip() == TextFillBox)
- return false;
-
- return true;
-}
-
-bool CompositedLayerMapping::paintsBoxDecorations() const
-{
- if (!m_owningLayer->hasVisibleBoxDecorations())
- return false;
-
- if (!supportsDirectBoxDecorationsComposition(renderer()))
- return true;
-
- return false;
-}
-
-bool CompositedLayerMapping::paintsChildren() const
-{
- if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers())
- return true;
-
- if (hasVisibleNonCompositingDescendantLayers())
- return true;
-
- return false;
-}
-
-static bool isCompositedPlugin(RenderObject* renderer)
-{
- return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
-}
-
-// A "simple container layer" is a RenderLayer which has no visible content to render.
-// It may have no children, or all its children may be themselves composited.
-// This is a useful optimization, because it allows us to avoid allocating backing store.
-bool CompositedLayerMapping::isSimpleContainerCompositingLayer() const
-{
- RenderObject* renderObject = renderer();
- if (renderObject->hasMask()) // masks require special treatment
- return false;
-
- if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
- return false;
-
- if (paintsBoxDecorations() || paintsChildren())
- return false;
-
- if (renderObject->isRenderRegion())
- return false;
-
- if (renderObject->node() && renderObject->node()->isDocumentNode()) {
- // Look to see if the root object has a non-simple background
- RenderObject* rootObject = renderObject->document().documentElement() ? renderObject->document().documentElement()->renderer() : 0;
- if (!rootObject)
- return false;
-
- 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).
- if (hasBoxDecorationsOrBackgroundImage(style))
- return false;
-
- // Now look at the body's renderer.
- HTMLElement* body = renderObject->document().body();
- RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
- if (!bodyObject)
- return false;
-
- style = bodyObject->style();
-
- if (hasBoxDecorationsOrBackgroundImage(style))
- return false;
- }
-
- return true;
-}
-
-static bool hasVisibleNonCompositingDescendant(RenderLayer* parent)
-{
- // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
- parent->stackingNode()->updateLayerListsIfNeeded();
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(parent->stackingNode());
-#endif
-
- RenderLayerStackingNodeIterator normalFlowIterator(*parent->stackingNode(), NormalFlowChildren);
- while (RenderLayerStackingNode* curNode = normalFlowIterator.next()) {
- RenderLayer* curLayer = curNode->layer();
- if (!curLayer->hasCompositedLayerMapping()
- && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
- return true;
- }
-
- if (!parent->hasVisibleDescendant())
- return false;
-
- RenderLayerStackingNodeIterator zOrderIterator(*parent->stackingNode(), NegativeZOrderChildren | PositiveZOrderChildren);
- while (RenderLayerStackingNode* curNode = zOrderIterator.next()) {
- RenderLayer* curLayer = curNode->layer();
- if (!curLayer->hasCompositedLayerMapping()
- && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
- return true;
- }
-
- return false;
-}
-
-// FIXME: By name the implementation is correct. But the code that uses this function means something
-// very slightly different - the implementation needs to also include composited descendants that
-// don't paint into their own backing, and instead paint into this backing.
-bool CompositedLayerMapping::hasVisibleNonCompositingDescendantLayers() const
-{
- return hasVisibleNonCompositingDescendant(m_owningLayer);
-}
-
-bool CompositedLayerMapping::containsPaintedContent(bool isSimpleContainer) const
-{
- if (isSimpleContainer || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
- return false;
-
- if (isDirectlyCompositedImage())
- return false;
-
- // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
- // and set background color on the layer in that case, instead of allocating backing store and painting.
- if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
- return m_owningLayer->hasBoxDecorationsOrBackground();
-
- return true;
-}
-
-// An image can be directly compositing if it's the sole content of the layer, and has no box decorations
-// that require painting. Direct compositing saves backing store.
-bool CompositedLayerMapping::isDirectlyCompositedImage() const
-{
- RenderObject* renderObject = renderer();
-
- if (!renderObject->isImage() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip())
- return false;
-
- RenderImage* imageRenderer = toRenderImage(renderObject);
- if (ImageResource* cachedImage = imageRenderer->cachedImage()) {
- if (!cachedImage->hasImage())
- return false;
-
- Image* image = cachedImage->imageForRenderer(imageRenderer);
- return image->isBitmapImage();
- }
-
- return false;
-}
-
-void CompositedLayerMapping::contentChanged(ContentChangeType changeType)
-{
- if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
- updateImageContents();
- return;
- }
-
- if ((changeType == MaskImageChanged) && m_maskLayer) {
- // The composited layer bounds relies on box->maskClipRect(), which changes
- // when the mask image becomes available.
- updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot);
- }
-
- if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
- m_graphicsLayer->setContentsNeedsDisplay();
- return;
- }
-}
-
-void CompositedLayerMapping::updateImageContents()
-{
- ASSERT(renderer()->isImage());
- RenderImage* imageRenderer = toRenderImage(renderer());
-
- ImageResource* cachedImage = imageRenderer->cachedImage();
- if (!cachedImage)
- return;
-
- Image* image = cachedImage->imageForRenderer(imageRenderer);
- if (!image)
- return;
-
- // We have to wait until the image is fully loaded before setting it on the layer.
- if (!cachedImage->isLoaded())
- return;
-
- // This is a no-op if the layer doesn't have an inner layer for the image.
- m_graphicsLayer->setContentsToImage(image);
- bool isSimpleContainer = false;
- updateDrawsContent(isSimpleContainer);
-
- // Image animation is "lazy", in that it automatically stops unless someone is drawing
- // the image. So we have to kick the animation each time; this has the downside that the
- // image will keep animating, even if its layer is not visible.
- image->startAnimation();
-}
-
-FloatPoint3D CompositedLayerMapping::computeTransformOrigin(const IntRect& borderBox) const
-{
- RenderStyle* style = renderer()->style();
-
- FloatPoint3D origin;
- origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
- origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
- origin.setZ(style->transformOriginZ());
-
- return origin;
-}
-
-FloatPoint CompositedLayerMapping::computePerspectiveOrigin(const IntRect& borderBox) const
-{
- RenderStyle* style = renderer()->style();
-
- float boxWidth = borderBox.width();
- float boxHeight = borderBox.height();
-
- FloatPoint origin;
- origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth));
- origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight));
-
- return origin;
-}
-
-// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
-IntSize CompositedLayerMapping::contentOffsetInCompostingLayer() const
-{
- return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
-}
-
-IntRect CompositedLayerMapping::contentsBox() const
-{
- IntRect contentsBox = contentsRect(renderer());
- contentsBox.move(contentOffsetInCompostingLayer());
- return contentsBox;
-}
-
-IntRect CompositedLayerMapping::backgroundBox() const
-{
- IntRect backgroundBox = backgroundRect(renderer());
- backgroundBox.move(contentOffsetInCompostingLayer());
- return backgroundBox;
-}
-
-GraphicsLayer* CompositedLayerMapping::parentForSublayers() const
-{
- if (m_scrollingContentsLayer)
- return m_scrollingContentsLayer.get();
-
- return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
-}
-
-GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const
-{
- if (m_squashingContainmentLayer)
- return m_squashingContainmentLayer.get();
-
- if (m_ancestorClippingLayer)
- return m_ancestorClippingLayer.get();
-
- return m_graphicsLayer.get();
-}
-
-bool CompositedLayerMapping::updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer* compositingAncestorLayer)
-{
- bool previousRequiresOwnBackingStoreForAncestorReasons = m_requiresOwnBackingStoreForAncestorReasons;
- bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
- bool canPaintIntoAncestor = compositingAncestorLayer
- && (compositingAncestorLayer->compositedLayerMapping()->mainGraphicsLayer()->drawsContent()
- || compositingAncestorLayer->compositedLayerMapping()->paintsIntoCompositedAncestor());
- m_requiresOwnBackingStoreForAncestorReasons = !canPaintIntoAncestor;
-
- if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
- paintsIntoCompositedAncestorChanged();
- return m_requiresOwnBackingStoreForAncestorReasons != previousRequiresOwnBackingStoreForAncestorReasons;
-}
-
-bool CompositedLayerMapping::updateRequiresOwnBackingStoreForIntrinsicReasons()
-{
- bool previousRequiresOwnBackingStoreForIntrinsicReasons = m_requiresOwnBackingStoreForIntrinsicReasons;
- bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
- RenderObject* renderer = m_owningLayer->renderer();
- m_requiresOwnBackingStoreForIntrinsicReasons = m_owningLayer->isRootLayer()
- || (m_owningLayer->compositingReasons() & CompositingReasonComboReasonsThatRequireOwnBacking)
- || m_owningLayer->transform()
- || m_owningLayer->clipsCompositingDescendantsWithBorderRadius() // FIXME: Revisit this if the paintsIntoCompositedAncestor state is removed.
- || renderer->isTransparent()
- || renderer->hasMask()
- || renderer->hasReflection()
- || renderer->hasFilter();
-
- if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
- paintsIntoCompositedAncestorChanged();
- return m_requiresOwnBackingStoreForIntrinsicReasons != previousRequiresOwnBackingStoreForIntrinsicReasons;
-}
-
-void CompositedLayerMapping::paintsIntoCompositedAncestorChanged()
-{
- // The answer to paintsIntoCompositedAncestor() affects cached clip rects, so when
- // it changes we have to clear clip rects on descendants.
- m_owningLayer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
- m_owningLayer->repainter().computeRepaintRectsIncludingDescendants();
-
- compositor()->repaintInCompositedAncestor(m_owningLayer, compositedBounds());
-}
-
-void CompositedLayerMapping::setBlendMode(blink::WebBlendMode blendMode)
-{
- if (m_ancestorClippingLayer) {
- m_ancestorClippingLayer->setBlendMode(blendMode);
- m_graphicsLayer->setBlendMode(blink::WebBlendModeNormal);
- } else {
- m_graphicsLayer->setBlendMode(blendMode);
- }
-}
-
-void CompositedLayerMapping::setContentsNeedDisplay()
-{
- ASSERT(!paintsIntoCompositedAncestor());
-
- if (m_graphicsLayer && m_graphicsLayer->drawsContent())
- m_graphicsLayer->setNeedsDisplay();
-
- if (m_foregroundLayer && m_foregroundLayer->drawsContent())
- m_foregroundLayer->setNeedsDisplay();
-
- if (m_backgroundLayer && m_backgroundLayer->drawsContent())
- m_backgroundLayer->setNeedsDisplay();
-
- if (m_maskLayer && m_maskLayer->drawsContent())
- m_maskLayer->setNeedsDisplay();
-
- if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent())
- m_childClippingMaskLayer->setNeedsDisplay();
-
- if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
- m_scrollingContentsLayer->setNeedsDisplay();
-}
-
-// r is in the coordinate space of the layer's render object
-void CompositedLayerMapping::setContentsNeedDisplayInRect(const IntRect& r)
-{
- ASSERT(!paintsIntoCompositedAncestor());
-
- if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
- IntRect layerDirtyRect = r;
- layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
- m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect);
- }
-
- if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
- IntRect layerDirtyRect = r;
- layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
- m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
- }
-
- // FIXME: need to split out repaints for the background.
- if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
- IntRect layerDirtyRect = r;
- layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer());
- m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect);
- }
-
- if (m_maskLayer && m_maskLayer->drawsContent()) {
- IntRect layerDirtyRect = r;
- layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
- m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
- }
-
- if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) {
- IntRect layerDirtyRect = r;
- layerDirtyRect.move(-m_childClippingMaskLayer->offsetFromRenderer());
- m_childClippingMaskLayer->setNeedsDisplayInRect(layerDirtyRect);
- }
-
- if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
- IntRect layerDirtyRect = r;
- layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
- m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
- }
-}
-
-void CompositedLayerMapping::doPaintTask(GraphicsLayerPaintInfo& paintInfo, GraphicsContext* context,
- const IntRect& clip) // In the coords of rootLayer.
-{
- if (paintsIntoCompositedAncestor()) {
- ASSERT_NOT_REACHED();
- return;
- }
-
- FontCachePurgePreventer fontCachePurgePreventer;
-
- PaintLayerFlags paintFlags = 0;
- if (paintInfo.paintingPhase & GraphicsLayerPaintBackground)
- paintFlags |= PaintLayerPaintingCompositingBackgroundPhase;
- if (paintInfo.paintingPhase & GraphicsLayerPaintForeground)
- paintFlags |= PaintLayerPaintingCompositingForegroundPhase;
- if (paintInfo.paintingPhase & GraphicsLayerPaintMask)
- paintFlags |= PaintLayerPaintingCompositingMaskPhase;
- if (paintInfo.paintingPhase & GraphicsLayerPaintChildClippingMask)
- paintFlags |= PaintLayerPaintingChildClippingMaskPhase;
- if (paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)
- paintFlags |= PaintLayerPaintingOverflowContents;
- if (paintInfo.paintingPhase & GraphicsLayerPaintCompositedScroll)
- paintFlags |= PaintLayerPaintingCompositingScrollingPhase;
-
- if (paintInfo.isBackgroundLayer)
- paintFlags |= (PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
- else if (compositor()->fixedRootBackgroundLayer())
- paintFlags |= PaintLayerPaintingSkipRootBackground;
-
- // Note carefully: in theory it is appropriate to invoke context->save() here
- // and restore the context after painting. For efficiency, we are assuming that
- // it is equivalent to manually undo this offset translation, which means we are
- // assuming that the context's space was not affected by the RenderLayer
- // painting code.
-
- LayoutSize offset = paintInfo.offsetFromRenderer;
- context->translate(-offset);
- LayoutRect relativeClip(clip);
- relativeClip.move(offset);
-
- // The dirtyRect is in the coords of the painting root.
- IntRect dirtyRect = pixelSnappedIntRect(relativeClip);
- if (!(paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents))
- dirtyRect.intersect(paintInfo.compositedBounds);
-
-#ifndef NDEBUG
- paintInfo.renderLayer->renderer()->assertSubtreeIsLaidOut();
-#endif
-
- if (paintInfo.renderLayer->compositingState() != PaintsIntoGroupedBacking) {
- // FIXME: GraphicsLayers need a way to split for RenderRegions.
- LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, LayoutSize());
- paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags);
-
- ASSERT(!paintInfo.isBackgroundLayer || paintFlags & PaintLayerPaintingRootBackgroundOnly);
-
- if (paintInfo.renderLayer->containsDirtyOverlayScrollbars())
- paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags | PaintLayerPaintingOverlayScrollbars);
- } else {
- ASSERT(compositor()->layerSquashingEnabled());
- LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, LayoutSize());
- paintInfo.renderLayer->paintLayer(context, paintingInfo, paintFlags);
- }
-
- ASSERT(!paintInfo.renderLayer->m_usedTransparency);
-
- // Manually restore the context to its original state by applying the opposite translation.
- context->translate(offset);
-}
-
-static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
-{
- if (!scrollbar)
- return;
-
- context.save();
- const IntRect& scrollbarRect = scrollbar->frameRect();
- context.translate(-scrollbarRect.x(), -scrollbarRect.y());
- IntRect transformedClip = clip;
- transformedClip.moveBy(scrollbarRect.location());
- scrollbar->paint(&context, transformedClip);
- context.restore();
-}
-
-// Up-call from compositing layer drawing callback.
-void CompositedLayerMapping::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
-{
-#ifndef NDEBUG
- if (Page* page = renderer()->frame()->page())
- page->setIsPainting(true);
-#endif
- InspectorInstrumentation::willPaint(m_owningLayer->renderer(), graphicsLayer);
-
- if (graphicsLayer == m_graphicsLayer.get()
- || graphicsLayer == m_foregroundLayer.get()
- || graphicsLayer == m_backgroundLayer.get()
- || graphicsLayer == m_maskLayer.get()
- || graphicsLayer == m_childClippingMaskLayer.get()
- || graphicsLayer == m_scrollingContentsLayer.get()) {
-
- GraphicsLayerPaintInfo paintInfo;
- paintInfo.renderLayer = m_owningLayer;
- paintInfo.compositedBounds = compositedBounds();
- paintInfo.offsetFromRenderer = graphicsLayer->offsetFromRenderer();
- paintInfo.paintingPhase = paintingPhase;
- paintInfo.isBackgroundLayer = (graphicsLayer == m_backgroundLayer);
-
- // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
- doPaintTask(paintInfo, &context, clip);
- } else if (graphicsLayer == m_squashingLayer.get()) {
- ASSERT(compositor()->layerSquashingEnabled());
- for (size_t i = 0; i < m_squashedLayers.size(); ++i)
- doPaintTask(m_squashedLayers[i], &context, clip);
- } else if (graphicsLayer == layerForHorizontalScrollbar()) {
- paintScrollbar(m_owningLayer->scrollableArea()->horizontalScrollbar(), context, clip);
- } else if (graphicsLayer == layerForVerticalScrollbar()) {
- paintScrollbar(m_owningLayer->scrollableArea()->verticalScrollbar(), context, clip);
- } else if (graphicsLayer == layerForScrollCorner()) {
- const IntRect& scrollCornerAndResizer = m_owningLayer->scrollableArea()->scrollCornerAndResizerRect();
- context.save();
- context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
- IntRect transformedClip = clip;
- transformedClip.moveBy(scrollCornerAndResizer.location());
- m_owningLayer->scrollableArea()->paintScrollCorner(&context, IntPoint(), transformedClip);
- m_owningLayer->scrollableArea()->paintResizer(&context, IntPoint(), transformedClip);
- context.restore();
- }
- InspectorInstrumentation::didPaint(m_owningLayer->renderer(), graphicsLayer, &context, clip);
-#ifndef NDEBUG
- if (Page* page = renderer()->frame()->page())
- page->setIsPainting(false);
-#endif
-}
-
-void CompositedLayerMapping::didCommitChangesForLayer(const GraphicsLayer* layer) const
-{
-}
-
-bool CompositedLayerMapping::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
-{
- if (graphicsLayer != m_graphicsLayer.get())
- return false;
-
- if (m_owningLayer->hasTransform()) {
- transform = m_owningLayer->currentTransform(RenderStyle::ExcludeTransformOrigin);
- return true;
- }
- return false;
-}
-
-bool CompositedLayerMapping::isTrackingRepaints() const
-{
- GraphicsLayerClient* client = compositor();
- return client ? client->isTrackingRepaints() : false;
-}
-
-static void collectTrackedRepaintRectsForGraphicsLayer(GraphicsLayer* graphicsLayer, Vector<FloatRect>& rects)
-{
- if (graphicsLayer)
- graphicsLayer->collectTrackedRepaintRects(rects);
-}
-
-PassOwnPtr<Vector<FloatRect> > CompositedLayerMapping::collectTrackedRepaintRects() const
-{
- OwnPtr<Vector<FloatRect> > rects = adoptPtr(new Vector<FloatRect>);
- collectTrackedRepaintRectsForGraphicsLayer(m_ancestorClippingLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_graphicsLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_childContainmentLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_scrollingLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_scrollingContentsLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_maskLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_childClippingMaskLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_foregroundLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_backgroundLayer.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_layerForHorizontalScrollbar.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_layerForVerticalScrollbar.get(), *rects);
- collectTrackedRepaintRectsForGraphicsLayer(m_layerForScrollCorner.get(), *rects);
- return rects.release();
-}
-
-#ifndef NDEBUG
-void CompositedLayerMapping::verifyNotPainting()
-{
- ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
-}
-#endif
-
-bool CompositedLayerMapping::startAnimation(double timeOffset, const CSSAnimationData* anim, const KeyframeList& keyframes)
-{
- bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
- IntSize boxSize;
- if (hasTransform)
- boxSize = toRenderBox(renderer())->pixelSnappedBorderBoxRect().size();
- WebAnimations animations(m_animationProvider->startAnimation(timeOffset, anim, keyframes, hasTransform, boxSize));
- if (animations.isEmpty())
- return false;
-
- bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
- bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
- int animationId = m_animationProvider->getWebAnimationId(keyframes.animationName());
-
- // Animating only some properties of the animation is not supported. So if the
- // GraphicsLayer rejects any property of the animation, we have to remove the
- // animation and return false to indicate un-accelerated animation is required.
- if (hasTransform) {
- if (!animations.m_transformAnimation || !m_graphicsLayer->addAnimation(animations.m_transformAnimation.release()))
- return false;
- }
- if (hasOpacity) {
- if (!animations.m_opacityAnimation || !m_graphicsLayer->addAnimation(animations.m_opacityAnimation.release())) {
- if (hasTransform)
- m_graphicsLayer->removeAnimation(animationId);
- return false;
- }
- }
- if (hasFilter) {
- if (!animations.m_filterAnimation || !m_graphicsLayer->addAnimation(animations.m_filterAnimation.release())) {
- if (hasTransform || hasOpacity)
- m_graphicsLayer->removeAnimation(animationId);
- return false;
- }
- }
- return true;
-}
-
-void CompositedLayerMapping::animationPaused(double timeOffset, const String& animationName)
-{
- int animationId = m_animationProvider->getWebAnimationId(animationName);
- ASSERT(animationId);
- m_graphicsLayer->pauseAnimation(animationId, timeOffset);
-}
-
-void CompositedLayerMapping::animationFinished(const String& animationName)
-{
- int animationId = m_animationProvider->getWebAnimationId(animationName);
- ASSERT(animationId);
- m_graphicsLayer->removeAnimation(animationId);
-}
-
-bool CompositedLayerMapping::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
-{
- ASSERT(property != CSSPropertyInvalid);
- IntSize boxSize;
- if (property == CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
- ASSERT(renderer()->isBox());
- boxSize = toRenderBox(renderer())->pixelSnappedBorderBoxRect().size();
- }
- float fromOpacity = 0;
- float toOpacity = 0;
- if (property == CSSPropertyOpacity) {
- fromOpacity = compositingOpacity(fromStyle->opacity());
- toOpacity = compositingOpacity(toStyle->opacity());
- }
-
- // Although KeyframeAnimation can have multiple properties of the animation, ImplicitAnimation (= Transition) has only one animation property.
- WebAnimations animations(m_animationProvider->startTransition(timeOffset, property, fromStyle,
- toStyle, m_owningLayer->hasTransform(), m_owningLayer->hasFilter(), boxSize, fromOpacity, toOpacity));
- if (animations.m_transformAnimation && m_graphicsLayer->addAnimation(animations.m_transformAnimation.release())) {
- // To ensure that the correct transform is visible when the animation ends, also set the final transform.
- updateTransform(toStyle);
- return true;
- }
- if (animations.m_opacityAnimation && m_graphicsLayer->addAnimation(animations.m_opacityAnimation.release())) {
- // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
- updateOpacity(toStyle);
- return true;
- }
- if (animations.m_filterAnimation && m_graphicsLayer->addAnimation(animations.m_filterAnimation.release())) {
- // To ensure that the correct filter is visible when the animation ends, also set the final filter.
- updateFilters(toStyle);
- return true;
- }
-
- return false;
-}
-
-void CompositedLayerMapping::transitionPaused(double timeOffset, CSSPropertyID property)
-{
- int animationId = m_animationProvider->getWebAnimationId(property);
- ASSERT(animationId);
- m_graphicsLayer->pauseAnimation(animationId, timeOffset);
-}
-
-void CompositedLayerMapping::transitionFinished(CSSPropertyID property)
-{
- int animationId = m_animationProvider->getWebAnimationId(property);
- ASSERT(animationId);
- m_graphicsLayer->removeAnimation(animationId);
-}
-
-void CompositedLayerMapping::notifyAnimationStarted(const GraphicsLayer*, double wallClockTime, double monotonicTime)
-{
- if (RuntimeEnabledFeatures::webAnimationsCSSEnabled())
- renderer()->node()->document().cssPendingAnimations().notifyCompositorAnimationStarted(monotonicTime);
- else
- renderer()->animation().notifyAnimationStarted(renderer(), wallClockTime);
-}
-
-IntRect CompositedLayerMapping::compositedBounds() const
-{
- return m_compositedBounds;
-}
-
-void CompositedLayerMapping::setCompositedBounds(const IntRect& bounds)
-{
- m_compositedBounds = bounds;
-}
-
-void CompositedLayerMapping::addRenderLayerToSquashingGraphicsLayer(RenderLayer* layer, IntSize offsetFromTargetBacking, size_t nextSquashedLayerIndex)
-{
- ASSERT(compositor()->layerSquashingEnabled());
-
- GraphicsLayerPaintInfo paintInfo;
- paintInfo.renderLayer = layer;
- // NOTE: composited bounds are updated elsewhere
- // NOTE: offsetFromRenderer is updated elsewhere
- paintInfo.offsetFromBackingRoot = offsetFromTargetBacking;
- paintInfo.paintingPhase = GraphicsLayerPaintAllWithOverflowClip;
- paintInfo.isBackgroundLayer = false;
-
- // Change tracking on squashing layers: at the first sign of something changed, just invalidate the layer.
- // FIXME: Perhaps we can find a tighter more clever mechanism later.
- if (nextSquashedLayerIndex < m_squashedLayers.size()) {
- if (m_squashedLayers[nextSquashedLayerIndex].renderLayer != layer) {
- m_squashedLayers[nextSquashedLayerIndex] = paintInfo;
- if (m_squashingLayer)
- m_squashingLayer->setNeedsDisplay();
- }
- } else {
- m_squashedLayers.append(paintInfo);
- if (m_squashingLayer)
- m_squashingLayer->setNeedsDisplay();
- }
- layer->setGroupedMapping(this);
-}
-
-void CompositedLayerMapping::finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex)
-{
- ASSERT(compositor()->layerSquashingEnabled());
-
- // Any additional squashed RenderLayers in the array no longer exist, and removing invalidates the squashingLayer contents.
- if (nextSquashedLayerIndex < m_squashedLayers.size()) {
- m_squashedLayers.remove(nextSquashedLayerIndex, m_squashedLayers.size() - nextSquashedLayerIndex);
- if (m_squashingLayer)
- m_squashingLayer->setNeedsDisplay();
- }
-}
-
-CompositingLayerType CompositedLayerMapping::compositingLayerType() const
-{
- if (m_graphicsLayer->hasContentsLayer())
- return MediaCompositingLayer;
-
- if (m_graphicsLayer->drawsContent())
- return NormalCompositingLayer;
-
- return ContainerCompositingLayer;
-}
-
-double CompositedLayerMapping::backingStoreMemoryEstimate() const
-{
- double backingMemory;
-
- // m_ancestorClippingLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
- backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
- if (m_foregroundLayer)
- backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
- if (m_backgroundLayer)
- backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
- if (m_maskLayer)
- backingMemory += m_maskLayer->backingStoreMemoryEstimate();
- if (m_childClippingMaskLayer)
- backingMemory += m_childClippingMaskLayer->backingStoreMemoryEstimate();
-
- if (m_scrollingContentsLayer)
- backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
-
- if (m_layerForHorizontalScrollbar)
- backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
-
- if (m_layerForVerticalScrollbar)
- backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
-
- if (m_layerForScrollCorner)
- backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
-
- return backingMemory;
-}
-
-String CompositedLayerMapping::debugName(const GraphicsLayer* graphicsLayer)
-{
- String name;
- if (graphicsLayer == m_graphicsLayer.get()) {
- name = m_owningLayer->debugName();
- } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
- name = "Ancestor Clipping Layer";
- } else if (graphicsLayer == m_foregroundLayer.get()) {
- name = m_owningLayer->debugName() + " (foreground) Layer";
- } else if (graphicsLayer == m_backgroundLayer.get()) {
- name = m_owningLayer->debugName() + " (background) Layer";
- } else if (graphicsLayer == m_childContainmentLayer.get()) {
- name = "Child Containment Layer";
- } else if (graphicsLayer == m_maskLayer.get()) {
- name = "Mask Layer";
- } else if (graphicsLayer == m_childClippingMaskLayer.get()) {
- name = "Child Clipping Mask Layer";
- } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
- name = "Horizontal Scrollbar Layer";
- } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
- name = "Vertical Scrollbar Layer";
- } else if (graphicsLayer == m_layerForScrollCorner.get()) {
- name = "Scroll Corner Layer";
- } else if (graphicsLayer == m_scrollingLayer.get()) {
- name = "Scrolling Layer";
- } else if (graphicsLayer == m_scrollingContentsLayer.get()) {
- name = "Scrolling Contents Layer";
- } else {
- ASSERT_NOT_REACHED();
- }
-
- return name;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/CompositingReasons.h b/chromium/third_party/WebKit/Source/core/rendering/CompositingReasons.h
deleted file mode 100644
index 8b023a724f8..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/CompositingReasons.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CompositingReasons_h
-#define CompositingReasons_h
-
-#include "wtf/MathExtras.h"
-#include <stdint.h>
-
-namespace WebCore {
-
-const uint64_t CompositingReasonNone = 0;
-
-// Intrinsic reasons that can be known right away by the layer
-const uint64_t CompositingReason3DTransform = UINT64_C(1) << 0;
-const uint64_t CompositingReasonVideo = UINT64_C(1) << 1;
-const uint64_t CompositingReasonCanvas = UINT64_C(1) << 2;
-const uint64_t CompositingReasonPlugin = UINT64_C(1) << 3;
-const uint64_t CompositingReasonIFrame = UINT64_C(1) << 4;
-const uint64_t CompositingReasonBackfaceVisibilityHidden = UINT64_C(1) << 5;
-const uint64_t CompositingReasonAnimation = UINT64_C(1) << 6;
-const uint64_t CompositingReasonFilters = UINT64_C(1) << 7;
-const uint64_t CompositingReasonPositionFixed = UINT64_C(1) << 8;
-const uint64_t CompositingReasonPositionSticky = UINT64_C(1) << 9;
-const uint64_t CompositingReasonOverflowScrollingTouch = UINT64_C(1) << 10;
-
-// Overlap reasons that require knowing what's behind you in paint-order before knowing the answer
-const uint64_t CompositingReasonAssumedOverlap = UINT64_C(1) << 12;
-const uint64_t CompositingReasonOverlap = UINT64_C(1) << 13;
-const uint64_t CompositingReasonNegativeZIndexChildren = UINT64_C(1) << 14;
-
-// Subtree reasons that require knowing what the status of your subtree is before knowing the answer
-const uint64_t CompositingReasonTransformWithCompositedDescendants = UINT64_C(1) << 15;
-const uint64_t CompositingReasonOpacityWithCompositedDescendants = UINT64_C(1) << 16;
-const uint64_t CompositingReasonMaskWithCompositedDescendants = UINT64_C(1) << 17;
-const uint64_t CompositingReasonReflectionWithCompositedDescendants = UINT64_C(1) << 18;
-const uint64_t CompositingReasonFilterWithCompositedDescendants = UINT64_C(1) << 19;
-const uint64_t CompositingReasonBlendingWithCompositedDescendants = UINT64_C(1) << 20;
-const uint64_t CompositingReasonClipsCompositingDescendants = UINT64_C(1) << 21;
-const uint64_t CompositingReasonPerspective = UINT64_C(1) << 22;
-const uint64_t CompositingReasonPreserve3D = UINT64_C(1) << 23;
-const uint64_t CompositingReasonReflectionOfCompositedParent = UINT64_C(1) << 24;
-
-// The root layer is a special case that may be forced to be a layer, but also it needs to be
-// a layer if anything else in the subtree is composited.
-const uint64_t CompositingReasonRoot = UINT64_C(1) << 25;
-
-// CompositedLayerMapping internal hierarchy reasons
-const uint64_t CompositingReasonLayerForClip = UINT64_C(1) << 26;
-const uint64_t CompositingReasonLayerForScrollbar = UINT64_C(1) << 27;
-const uint64_t CompositingReasonLayerForScrollingContainer = UINT64_C(1) << 28;
-const uint64_t CompositingReasonLayerForForeground = UINT64_C(1) << 29;
-const uint64_t CompositingReasonLayerForBackground = UINT64_C(1) << 30;
-const uint64_t CompositingReasonLayerForMask = UINT64_C(1) << 31;
-
-// FIXME: the following compositing reasons need to be re-organized to fit with categories
-// used in all the other reasons above.
-const uint64_t CompositingReasonOverflowScrollingParent = UINT64_C(1) << 32;
-const uint64_t CompositingReasonOutOfFlowClipping = UINT64_C(1) << 33;
-
-const uint64_t CompositingReasonLayerForVideoOverlay = UINT64_C(1) << 34;
-const uint64_t CompositingReasonIsolateCompositedDescendants = UINT64_C(1) << 35;
-
-// Note: if you add more reasons here, you will need to update WebCompositingReasons as well.
-
-// Various combinations of compositing reasons are defined here also, for more intutive and faster bitwise logic.
-const uint64_t CompositingReasonComboAllDirectReasons =
- CompositingReason3DTransform
- | CompositingReasonVideo
- | CompositingReasonCanvas
- | CompositingReasonPlugin
- | CompositingReasonIFrame
- | CompositingReasonBackfaceVisibilityHidden
- | CompositingReasonAnimation
- | CompositingReasonFilters
- | CompositingReasonPositionFixed
- | CompositingReasonPositionSticky
- | CompositingReasonOverflowScrollingTouch
- | CompositingReasonOverflowScrollingParent
- | CompositingReasonOutOfFlowClipping;
-
-const uint64_t CompositingReasonComboReasonsThatRequireOwnBacking =
- CompositingReasonComboAllDirectReasons
- | CompositingReasonOverlap
- | CompositingReasonAssumedOverlap
- | CompositingReasonNegativeZIndexChildren
- | CompositingReasonTransformWithCompositedDescendants
- | CompositingReasonOpacityWithCompositedDescendants
- | CompositingReasonMaskWithCompositedDescendants
- | CompositingReasonFilterWithCompositedDescendants
- | CompositingReasonBlendingWithCompositedDescendants
- | CompositingReasonIsolateCompositedDescendants
- | CompositingReasonPreserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect.
-
-const uint64_t CompositingReasonComboAllOverlapReasons =
- CompositingReasonOverlap
- | CompositingReasonAssumedOverlap;
-
-typedef uint64_t CompositingReasons;
-
-
-} // namespace WebCore
-
-#endif // CompositingReasons_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.cpp
index 9051eb20342..9f3e0262827 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.cpp
@@ -27,7 +27,7 @@
#include "core/rendering/RootInlineBox.h"
#include "core/rendering/style/ShadowList.h"
#include "platform/fonts/Font.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/text/TextRun.h"
@@ -36,21 +36,20 @@ namespace WebCore {
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
GraphicsContext* context = paintInfo.context;
- RenderStyle* style = m_renderer->style(isFirstLineStyle());
+ RenderStyle* style = renderer().style(isFirstLineStyle());
const Font& font = style->font();
FloatPoint boxOrigin = locationIncludingFlipping();
- LayoutPoint adjustedPaintOffset = paintOffset;
+ boxOrigin.moveBy(FloatPoint(paintOffset));
if (!isHorizontal())
- adjustedPaintOffset.move(0, -virtualLogicalHeight());
- boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y());
+ boxOrigin.move(0, -virtualLogicalHeight());
FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), virtualLogicalHeight()));
GraphicsContextStateSaver stateSaver(*context);
if (!isHorizontal())
context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clockwise));
FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent());
- Color styleTextColor = m_renderer->resolveColor(style, CSSPropertyWebkitTextFillColor);
+ Color styleTextColor = renderer().resolveColor(style, CSSPropertyWebkitTextFillColor);
if (styleTextColor != context->fillColor())
context->setFillColor(styleTextColor);
@@ -58,8 +57,8 @@ void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, La
paintSelection(context, boxOrigin, style, font);
// Select the correct color for painting the text.
- Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
- if (foreground.isValid() && foreground != styleTextColor)
+ Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor();
+ if (foreground != styleTextColor)
context->setFillColor(foreground);
}
@@ -67,21 +66,20 @@ void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, La
const ShadowList* shadowList = context->printing() ? 0 : style->textShadow();
bool hasShadow = shadowList;
if (hasShadow) {
- DrawLooper drawLooper;
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
for (size_t i = shadowList->shadows().size(); i--; ) {
const ShadowData& shadow = shadowList->shadows()[i];
- int shadowX = isHorizontal() ? shadow.x() : shadow.y();
- int shadowY = isHorizontal() ? shadow.y() : -shadow.x();
+ float shadowX = isHorizontal() ? shadow.x() : shadow.y();
+ float shadowY = isHorizontal() ? shadow.y() : -shadow.x();
FloatSize offset(shadowX, shadowY);
- drawLooper.addShadow(offset, shadow.blur(), m_renderer->resolveColor(shadow.color()),
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
+ drawLooperBuilder->addShadow(offset, shadow.blur(), shadow.color(),
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha);
}
- drawLooper.addUnmodifiedContent();
- context->setDrawLooper(drawLooper);
+ drawLooperBuilder->addUnmodifiedContent();
+ context->setDrawLooper(drawLooperBuilder.release());
}
- // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
- TextRun textRun = RenderBlockFlow::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion);
+ TextRun textRun = RenderBlockFlow::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion);
TextRunPaintInfo textRunPaintInfo(textRun);
textRunPaintInfo.bounds = boxRect;
context->drawText(font, textRunPaintInfo, textOrigin);
@@ -98,18 +96,18 @@ void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, La
InlineBox* EllipsisBox::markupBox() const
{
- if (!m_shouldPaintMarkupBox || !m_renderer->isRenderBlock())
+ if (!m_shouldPaintMarkupBox || !renderer().isRenderBlock())
return 0;
- RenderBlock* block = toRenderBlock(m_renderer);
- RootInlineBox* lastLine = block->lineAtIndex(block->lineCount() - 1);
+ RenderBlock& block = toRenderBlock(renderer());
+ RootInlineBox* lastLine = block.lineAtIndex(block.lineCount() - 1);
if (!lastLine)
return 0;
// If the last line-box on the last line of a block is a link, -webkit-line-clamp paints that box after the ellipsis.
// It does not actually move the link.
InlineBox* anchorBox = lastLine->lastChild();
- if (!anchorBox || !anchorBox->renderer()->style()->isLink())
+ if (!anchorBox || !anchorBox->renderer().style()->isLink())
return 0;
return anchorBox;
@@ -123,23 +121,22 @@ void EllipsisBox::paintMarkupBox(PaintInfo& paintInfo, const LayoutPoint& paintO
LayoutPoint adjustedPaintOffset = paintOffset;
adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(),
- y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent()));
+ y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent()));
markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom);
}
IntRect EllipsisBox::selectionRect()
{
- RenderStyle* style = m_renderer->style(isFirstLineStyle());
+ RenderStyle* style = 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(RenderBlockFlow::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(logicalLeft(), logicalTop() + root()->selectionTopAdjustedForPrecedingBlock()), root()->selectionHeightAdjustedForPrecedingBlock()));
+ return enclosingIntRect(font.selectionRectForText(RenderBlockFlow::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(logicalLeft(), logicalTop() + root().selectionTopAdjustedForPrecedingBlock()), root().selectionHeightAdjustedForPrecedingBlock()));
}
void EllipsisBox::paintSelection(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font)
{
- Color textColor = m_renderer->resolveColor(style, CSSPropertyColor);
- Color c = m_renderer->selectionBackgroundColor();
- if (!c.isValid() || !c.alpha())
+ Color textColor = renderer().resolveColor(style, CSSPropertyColor);
+ Color c = renderer().selectionBackgroundColor();
+ if (!c.alpha())
return;
// If the text color ends up being the same as the selection background, invert the selection
@@ -148,16 +145,15 @@ void EllipsisBox::paintSelection(GraphicsContext* context, const FloatPoint& box
c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
GraphicsContextStateSaver stateSaver(*context);
- LayoutUnit selectionBottom = root()->selectionBottom();
- LayoutUnit top = root()->selectionTop();
- LayoutUnit h = root()->selectionHeight();
- const int deltaY = roundToInt(renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - top);
+ LayoutUnit selectionBottom = root().selectionBottom();
+ LayoutUnit top = root().selectionTop();
+ LayoutUnit h = root().selectionHeight();
+ const int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - top);
const FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
- FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, h));
+ FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, h.toFloat()));
alignSelectionRectToDevicePixels(clipRect);
context->clip(clipRect);
- // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
- context->drawHighlightForText(font, RenderBlockFlow::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), localOrigin, h, c);
+ context->drawHighlightForText(font, RenderBlockFlow::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), localOrigin, h, c);
}
bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
@@ -166,11 +162,11 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Hit test the markup box.
if (InlineBox* markupBox = this->markupBox()) {
- RenderStyle* style = m_renderer->style(isFirstLineStyle());
+ RenderStyle* style = renderer().style(isFirstLineStyle());
LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x();
- LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent());
+ LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent());
if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) {
- renderer()->updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
+ renderer().updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
return true;
}
}
@@ -179,8 +175,8 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
boxOrigin.moveBy(accumulatedOffset);
FloatRect boundsRect(boxOrigin, size());
if (visibleToHitTestRequest(request) && boundsRect.intersects(HitTestLocation::rectForPoint(locationInContainer.point(), 0, 0, 0, 0))) {
- renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, boundsRect))
+ renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+ if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, boundsRect))
return true;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.h b/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.h
index ad8e61291f5..c97d375c54a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/EllipsisBox.h
@@ -29,7 +29,7 @@ class HitTestResult;
class EllipsisBox FINAL : public InlineBox {
public:
- EllipsisBox(RenderObject* obj, const AtomicString& ellipsisStr, InlineFlowBox* parent,
+ EllipsisBox(RenderObject& obj, const AtomicString& ellipsisStr, InlineFlowBox* parent,
int width, int height, int x, int y, bool firstLine, bool isVertical, InlineBox* markupBox)
: InlineBox(obj, FloatPoint(x, y), width, firstLine, true, false, false, isVertical, 0, 0, parent)
, m_shouldPaintMarkupBox(markupBox)
@@ -40,7 +40,7 @@ public:
setHasVirtualLogicalHeight();
}
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
void setSelectionState(RenderObject::SelectionState s) { m_selectionState = s; }
IntRect selectionRect();
@@ -48,8 +48,8 @@ public:
virtual float virtualLogicalHeight() const OVERRIDE { return m_height; }
private:
void paintMarkupBox(PaintInfo&, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, RenderStyle*);
- virtual int height() const { return m_height; }
- virtual RenderObject::SelectionState selectionState() { return m_selectionState; }
+ int height() const { return m_height; }
+ virtual RenderObject::SelectionState selectionState() OVERRIDE { return m_selectionState; }
void paintSelection(GraphicsContext*, const FloatPoint&, RenderStyle*, const Font&);
InlineBox* markupBox() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.cpp b/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.cpp
index cbdcafc68f0..43ec0362bf6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.cpp
@@ -32,108 +32,1100 @@
#include "core/rendering/FastTextAutosizer.h"
#include "core/dom/Document.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
+#include "core/html/HTMLTextAreaElement.h"
+#include "core/page/Page.h"
#include "core/rendering/InlineIterator.h"
#include "core/rendering/RenderBlock.h"
-#include "core/rendering/TextAutosizer.h"
+#include "core/rendering/RenderListItem.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderView.h"
+
+#ifdef AUTOSIZING_DOM_DEBUG_INFO
+#include "core/dom/ExecutionContextTask.h"
+#endif
+
+using namespace std;
namespace WebCore {
-FastTextAutosizer::FastTextAutosizer(Document* document)
+#ifdef AUTOSIZING_DOM_DEBUG_INFO
+class WriteDebugInfoTask : public ExecutionContextTask {
+public:
+ WriteDebugInfoTask(PassRefPtrWillBeRawPtr<Element> element, AtomicString value)
+ : m_element(element)
+ , m_value(value)
+ {
+ }
+
+ virtual void performTask(ExecutionContext*)
+ {
+ m_element->setAttribute("data-autosizing", m_value, ASSERT_NO_EXCEPTION);
+ }
+
+private:
+ RefPtrWillBePersistent<Element> m_element;
+ AtomicString m_value;
+};
+
+static void writeDebugInfo(RenderObject* renderer, const AtomicString& output)
+{
+ Node* node = renderer->node();
+ if (!node)
+ return;
+ if (node->isDocumentNode())
+ node = toDocument(node)->documentElement();
+ if (!node->isElementNode())
+ return;
+ node->document().postTask(adoptPtr(new WriteDebugInfoTask(toElement(node), output)));
+}
+
+void FastTextAutosizer::writeClusterDebugInfo(Cluster* cluster)
+{
+ String explanation = "";
+ if (cluster->m_flags & SUPPRESSING) {
+ explanation = "[suppressed]";
+ } else if (!(cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER))) {
+ explanation = "[inherited]";
+ } else if (cluster->m_supercluster) {
+ explanation = "[supercluster]";
+ } else if (!clusterHasEnoughTextToAutosize(cluster)) {
+ explanation = "[insufficient-text]";
+ } else {
+ const RenderBlock* widthProvider = clusterWidthProvider(cluster->m_root);
+ if (cluster->m_hasTableAncestor && cluster->m_multiplier < multiplierFromBlock(widthProvider)) {
+ explanation = "[table-ancestor-limited]";
+ } else {
+ explanation = String::format("[from width %d of %s]",
+ static_cast<int>(widthFromBlock(widthProvider)), widthProvider->debugName().utf8().data());
+ }
+ }
+ String pageInfo = "";
+ if (cluster->m_root->isRenderView()) {
+ pageInfo = String::format("; pageinfo: bm %f * (lw %d / fw %d)",
+ m_pageInfo.m_baseMultiplier, m_pageInfo.m_layoutWidth, m_pageInfo.m_frameWidth);
+ }
+ float multiplier = cluster->m_flags & SUPPRESSING ? 1.0 : cluster->m_multiplier;
+ writeDebugInfo(const_cast<RenderBlock*>(cluster->m_root),
+ AtomicString(String::format("cluster: %f %s%s", multiplier,
+ explanation.utf8().data(), pageInfo.utf8().data())));
+}
+#endif
+
+static const RenderObject* parentElementRenderer(const RenderObject* renderer)
+{
+ // At style recalc, the renderer's parent may not be attached,
+ // so we need to obtain this from the DOM tree.
+ const Node* node = renderer->node();
+ if (!node)
+ return 0;
+
+ while ((node = node->parentNode())) {
+ if (node->isElementNode())
+ return node->renderer();
+ }
+ return 0;
+}
+
+static bool isNonTextAreaFormControl(const RenderObject* renderer)
+{
+ const Node* node = renderer ? renderer->node() : 0;
+ if (!node || !node->isElementNode())
+ return false;
+ const Element* element = toElement(node);
+
+ return (element->isFormControlElement() && !isHTMLTextAreaElement(element));
+}
+
+static bool isPotentialClusterRoot(const RenderObject* renderer)
+{
+ // "Potential cluster roots" are the smallest unit for which we can
+ // enable/disable text autosizing.
+ // - Must not be inline, as different multipliers on one line looks terrible.
+ // Exceptions are inline-block and alike elements (inline-table, -webkit-inline-*),
+ // as they often contain entire multi-line columns of text.
+ // - Must not be normal list items, as items in the same list should look
+ // consistent, unless they are floating or position:absolute/fixed.
+ Node* node = renderer->generatingNode();
+ if (node && !node->hasChildren())
+ return false;
+ if (!renderer->isRenderBlock())
+ return false;
+ if (renderer->isInline() && !renderer->style()->isDisplayReplacedType())
+ return false;
+ if (renderer->isListItem())
+ return (renderer->isFloating() || renderer->isOutOfFlowPositioned());
+
+ return true;
+}
+
+static bool isIndependentDescendant(const RenderBlock* renderer)
+{
+ ASSERT(isPotentialClusterRoot(renderer));
+
+ RenderBlock* containingBlock = renderer->containingBlock();
+ return renderer->isRenderView()
+ || renderer->isFloating()
+ || renderer->isOutOfFlowPositioned()
+ || renderer->isTableCell()
+ || renderer->isTableCaption()
+ || renderer->isFlexibleBoxIncludingDeprecated()
+ || renderer->hasColumns()
+ || (containingBlock && containingBlock->isHorizontalWritingMode() != renderer->isHorizontalWritingMode())
+ || renderer->style()->isDisplayReplacedType()
+ || renderer->isTextArea()
+ || renderer->style()->userModify() != READ_ONLY;
+}
+
+static bool blockIsRowOfLinks(const RenderBlock* block)
+{
+ // A "row of links" is a block for which:
+ // 1. It does not contain non-link text elements longer than 3 characters
+ // 2. It contains a minimum of 3 inline links and all links should
+ // have the same specified font size.
+ // 3. It should not contain <br> elements.
+ // 4. It should contain only inline elements unless they are containers,
+ // children of link elements or children of sub-containers.
+ int linkCount = 0;
+ RenderObject* renderer = block->firstChild();
+ float matchingFontSize = -1;
+
+ while (renderer) {
+ if (!isPotentialClusterRoot(renderer)) {
+ if (renderer->isText() && toRenderText(renderer)->text().impl()->stripWhiteSpace()->length() > 3)
+ return false;
+ if (!renderer->isInline() || renderer->isBR())
+ return false;
+ }
+ if (renderer->style()->isLink()) {
+ linkCount++;
+ if (matchingFontSize < 0)
+ matchingFontSize = renderer->style()->specifiedFontSize();
+ else if (matchingFontSize != renderer->style()->specifiedFontSize())
+ return false;
+
+ // Skip traversing descendants of the link.
+ renderer = renderer->nextInPreOrderAfterChildren(block);
+ continue;
+ }
+ renderer = renderer->nextInPreOrder(block);
+ }
+
+ return (linkCount >= 3);
+}
+
+static bool blockHeightConstrained(const RenderBlock* block)
+{
+ // FIXME: Propagate constrainedness down the tree, to avoid inefficiently walking back up from each box.
+ // FIXME: This code needs to take into account vertical writing modes.
+ // FIXME: Consider additional heuristics, such as ignoring fixed heights if the content is already overflowing before autosizing kicks in.
+ for (; block; block = block->containingBlock()) {
+ RenderStyle* style = block->style();
+ if (style->overflowY() >= OSCROLL)
+ return false;
+ if (style->height().isSpecified() || style->maxHeight().isSpecified() || block->isOutOfFlowPositioned()) {
+ // Some sites (e.g. wikipedia) set their html and/or body elements to height:100%,
+ // without intending to constrain the height of the content within them.
+ return !block->isDocumentElement() && !block->isBody();
+ }
+ if (block->isFloating())
+ return false;
+ }
+ return false;
+}
+
+static bool blockOrImmediateChildrenAreFormControls(const RenderBlock* block)
+{
+ if (isNonTextAreaFormControl(block))
+ return true;
+ const RenderObject* renderer = block->firstChild();
+ while (renderer) {
+ if (isNonTextAreaFormControl(renderer))
+ return true;
+ renderer = renderer->nextSibling();
+ }
+
+ return false;
+}
+
+// Some blocks are not autosized even if their parent cluster wants them to.
+static bool blockSuppressesAutosizing(const RenderBlock* block)
+{
+ if (blockOrImmediateChildrenAreFormControls(block))
+ return true;
+
+ if (blockIsRowOfLinks(block))
+ return true;
+
+ // Don't autosize block-level text that can't wrap (as it's likely to
+ // expand sideways and break the page's layout).
+ if (!block->style()->autoWrap())
+ return true;
+
+ if (blockHeightConstrained(block))
+ return true;
+
+ return false;
+}
+
+static bool hasExplicitWidth(const RenderBlock* block)
+{
+ // FIXME: This heuristic may need to be expanded to other ways a block can be wider or narrower
+ // than its parent containing block.
+ return block->style() && block->style()->width().isSpecified();
+}
+
+FastTextAutosizer::FastTextAutosizer(const Document* document)
: m_document(document)
+ , m_firstBlockToBeginLayout(0)
+#ifndef NDEBUG
+ , m_blocksThatHaveBegunLayout()
+#endif
+ , m_superclusters()
+ , m_clusterStack()
+ , m_fingerprintMapper()
+ , m_pageInfo()
+ , m_updatePageInfoDeferred(false)
{
}
void FastTextAutosizer::record(const RenderBlock* block)
{
- if (!m_document->settings()
- || !m_document->settings()->textAutosizingEnabled()
- || m_document->printing()
- || !m_document->page())
+ if (!m_pageInfo.m_settingEnabled)
return;
- if (!TextAutosizer::isAutosizingContainer(block))
+ ASSERT(!m_blocksThatHaveBegunLayout.contains(block));
+
+ if (!classifyBlock(block, INDEPENDENT | EXPLICIT_WIDTH))
return;
- AtomicString blockFingerprint = fingerprint(block);
- HashMap<AtomicString, OwnPtr<Cluster> >::AddResult result =
- m_clusterForFingerprint.add(blockFingerprint, PassOwnPtr<Cluster>());
+ if (Fingerprint fingerprint = computeFingerprint(block))
+ m_fingerprintMapper.addTentativeClusterRoot(block, fingerprint);
+}
- if (result.isNewEntry)
- result.iterator->value = adoptPtr(new Cluster(blockFingerprint));
+void FastTextAutosizer::destroy(const RenderBlock* block)
+{
+ if (!m_pageInfo.m_settingEnabled)
+ return;
- Cluster* cluster = result.iterator->value.get();
- cluster->m_blocks.add(block);
+ ASSERT(!m_blocksThatHaveBegunLayout.contains(block));
- m_clusterForBlock.set(block, cluster);
+ if (m_fingerprintMapper.remove(block) && m_firstBlockToBeginLayout) {
+ // RenderBlock with a fingerprint was destroyed during layout.
+ // Clear the cluster stack and the supercluster map to avoid stale pointers.
+ // Speculative fix for http://crbug.com/369485.
+ m_firstBlockToBeginLayout = 0;
+ m_clusterStack.clear();
+ m_superclusters.clear();
+ }
}
-void FastTextAutosizer::destroy(const RenderBlock* block)
+FastTextAutosizer::BeginLayoutBehavior FastTextAutosizer::prepareForLayout(const RenderBlock* block)
{
- Cluster* cluster = m_clusterForBlock.take(block);
- if (!cluster)
+#ifndef NDEBUG
+ m_blocksThatHaveBegunLayout.add(block);
+#endif
+
+ if (!m_firstBlockToBeginLayout) {
+ m_firstBlockToBeginLayout = block;
+ prepareClusterStack(block->parent());
+ } else if (block == currentCluster()->m_root) {
+ // Ignore beginLayout on the same block twice.
+ // This can happen with paginated overflow.
+ return StopLayout;
+ }
+
+ return ContinueLayout;
+}
+
+void FastTextAutosizer::prepareClusterStack(const RenderObject* renderer)
+{
+ if (!renderer)
return;
- cluster->m_blocks.remove(block);
- if (cluster->m_blocks.isEmpty()) {
- // This deletes the Cluster.
- m_clusterForFingerprint.remove(cluster->m_fingerprint);
+ prepareClusterStack(renderer->parent());
+
+ if (renderer->isRenderBlock()) {
+ const RenderBlock* block = toRenderBlock(renderer);
+#ifndef NDEBUG
+ m_blocksThatHaveBegunLayout.add(block);
+#endif
+ if (Cluster* cluster = maybeCreateCluster(block))
+ m_clusterStack.append(adoptPtr(cluster));
+ }
+}
+
+void FastTextAutosizer::beginLayout(RenderBlock* block)
+{
+ ASSERT(shouldHandleLayout());
+
+ if (prepareForLayout(block) == StopLayout)
+ return;
+
+ if (Cluster* cluster = maybeCreateCluster(block))
+ m_clusterStack.append(adoptPtr(cluster));
+
+ // Cells in auto-layout tables are handled separately by inflateAutoTable.
+ bool isAutoTableCell = block->isTableCell() && !toRenderTableCell(block)->table()->style()->isFixedTableLayout();
+ if (!isAutoTableCell && !m_clusterStack.isEmpty())
+ inflate(block);
+}
+
+void FastTextAutosizer::inflateListItem(RenderListItem* listItem, RenderListMarker* listItemMarker)
+{
+ if (!shouldHandleLayout())
return;
+ ASSERT(listItem && listItemMarker);
+
+ if (prepareForLayout(listItem) == StopLayout)
+ return;
+
+ // Force the LI to be inside the DBCAT when computing the multiplier.
+ // This guarantees that the DBCAT has entered layout, so we can ask for its width.
+ // It also makes sense because the list marker is autosized like a text node.
+ float multiplier = clusterMultiplier(currentCluster());
+
+ applyMultiplier(listItem, multiplier);
+ applyMultiplier(listItemMarker, multiplier);
+}
+
+void FastTextAutosizer::inflateAutoTable(RenderTable* table)
+{
+ ASSERT(table);
+ ASSERT(!table->style()->isFixedTableLayout());
+ ASSERT(table->containingBlock());
+
+ Cluster* cluster = currentCluster();
+ if (cluster->m_root != table)
+ return;
+
+ // Pre-inflate cells that have enough text so that their inflated preferred widths will be used
+ // for column sizing.
+ for (RenderObject* section = table->firstChild(); section; section = section->nextSibling()) {
+ if (!section->isTableSection())
+ continue;
+ for (RenderTableRow* row = toRenderTableSection(section)->firstRow(); row; row = row->nextRow()) {
+ for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
+ if (!cell->needsLayout())
+ continue;
+
+ beginLayout(cell);
+ inflate(cell, DescendToInnerBlocks);
+ endLayout(cell);
+ }
+ }
}
- cluster->m_multiplier = 0;
}
-static void applyMultiplier(RenderObject* renderer, float multiplier)
+void FastTextAutosizer::endLayout(RenderBlock* block)
{
- // We need to clone the render style to avoid breaking style sharing.
- RefPtr<RenderStyle> style = RenderStyle::clone(renderer->style());
- style->setTextAutosizingMultiplier(multiplier);
- style->setUnique();
- renderer->setStyleInternal(style.release());
+ ASSERT(shouldHandleLayout());
+
+ if (block == m_firstBlockToBeginLayout) {
+ m_firstBlockToBeginLayout = 0;
+ m_clusterStack.clear();
+ m_superclusters.clear();
+ m_stylesRetainedDuringLayout.clear();
+#ifndef NDEBUG
+ m_blocksThatHaveBegunLayout.clear();
+#endif
+ // Tables can create two layout scopes for the same block so the isEmpty
+ // check below is needed to guard against endLayout being called twice.
+ } else if (!m_clusterStack.isEmpty() && currentCluster()->m_root == block) {
+ m_clusterStack.removeLast();
+ }
}
-void FastTextAutosizer::inflate(RenderBlock* block)
+float FastTextAutosizer::inflate(RenderObject* parent, InflateBehavior behavior, float multiplier)
{
- Cluster* cluster = 0;
- for (const RenderObject* clusterBlock = block; clusterBlock && !cluster; clusterBlock = clusterBlock->parent()) {
- if (clusterBlock->isRenderBlock())
- cluster = m_clusterForBlock.get(toRenderBlock(clusterBlock));
+ Cluster* cluster = currentCluster();
+ bool hasTextChild = false;
+
+ RenderObject* child = 0;
+ if (parent->isRenderBlock() && (parent->childrenInline() || behavior == DescendToInnerBlocks))
+ child = toRenderBlock(parent)->firstChild();
+ else if (parent->isRenderInline())
+ child = toRenderInline(parent)->firstChild();
+
+ while (child) {
+ if (child->isText()) {
+ hasTextChild = true;
+ // We only calculate this multiplier on-demand to ensure the parent block of this text
+ // has entered layout.
+ if (!multiplier)
+ multiplier = cluster->m_flags & SUPPRESSING ? 1.0f : clusterMultiplier(cluster);
+ applyMultiplier(child, multiplier);
+ // FIXME: Investigate why MarkOnlyThis is sufficient.
+ if (parent->isRenderInline())
+ child->setPreferredLogicalWidthsDirty(MarkOnlyThis);
+ } else if (child->isRenderInline()) {
+ multiplier = inflate(child, behavior, multiplier);
+ } else if (child->isRenderBlock() && behavior == DescendToInnerBlocks
+ && !classifyBlock(child, INDEPENDENT | EXPLICIT_WIDTH | SUPPRESSING)) {
+ multiplier = inflate(child, behavior, multiplier);
+ }
+ child = child->nextSibling();
}
- if (!cluster)
- return;
- if (!cluster->m_multiplier)
- cluster->m_multiplier = computeMultiplier(cluster);
- if (cluster->m_multiplier == 1)
+
+ if (hasTextChild) {
+ applyMultiplier(parent, multiplier); // Parent handles line spacing.
+ } else if (!parent->isListItem()) {
+ // For consistency, a block with no immediate text child should always have a
+ // multiplier of 1 (except for list items which are handled in inflateListItem).
+ applyMultiplier(parent, 1);
+ }
+ return multiplier;
+}
+
+bool FastTextAutosizer::shouldHandleLayout() const
+{
+ return m_pageInfo.m_settingEnabled && m_pageInfo.m_pageNeedsAutosizing && !m_updatePageInfoDeferred;
+}
+
+void FastTextAutosizer::updatePageInfoInAllFrames()
+{
+ ASSERT(!m_document->frame() || m_document->frame()->isMainFrame());
+
+ for (Frame* frame = m_document->frame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->isLocalFrame())
+ continue;
+ if (FastTextAutosizer* textAutosizer = toLocalFrame(frame)->document()->fastTextAutosizer())
+ textAutosizer->updatePageInfo();
+ }
+}
+
+void FastTextAutosizer::updatePageInfo()
+{
+ if (m_updatePageInfoDeferred || !m_document->page() || !m_document->settings())
return;
- applyMultiplier(block, cluster->m_multiplier);
- for (InlineWalker walker(block); !walker.atEnd(); walker.advance()) {
- RenderObject* inlineObj = walker.current();
- if (inlineObj->isRenderBlock() && m_clusterForBlock.contains(toRenderBlock(inlineObj)))
+ PageInfo previousPageInfo(m_pageInfo);
+ m_pageInfo.m_settingEnabled = m_document->settings()->textAutosizingEnabled();
+
+ if (!m_pageInfo.m_settingEnabled || m_document->printing()) {
+ m_pageInfo.m_pageNeedsAutosizing = false;
+ } else {
+ RenderView* renderView = m_document->renderView();
+ bool horizontalWritingMode = isHorizontalWritingMode(renderView->style()->writingMode());
+
+ LocalFrame* mainFrame = m_document->page()->deprecatedLocalMainFrame();
+ IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride();
+ if (frameSize.isEmpty())
+ frameSize = mainFrame->view()->unscaledVisibleContentSize(IncludeScrollbars);
+ m_pageInfo.m_frameWidth = horizontalWritingMode ? frameSize.width() : frameSize.height();
+
+ IntSize layoutSize = mainFrame->view()->layoutSize();
+ m_pageInfo.m_layoutWidth = horizontalWritingMode ? layoutSize.width() : layoutSize.height();
+
+ // Compute the base font scale multiplier based on device and accessibility settings.
+ m_pageInfo.m_baseMultiplier = m_document->settings()->accessibilityFontScaleFactor();
+ // If the page has a meta viewport or @viewport, don't apply the device scale adjustment.
+ const ViewportDescription& viewportDescription = mainFrame->document()->viewportDescription();
+ if (!viewportDescription.isSpecifiedByAuthor()) {
+ float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustment();
+ m_pageInfo.m_baseMultiplier *= deviceScaleAdjustment;
+ }
+
+ m_pageInfo.m_pageNeedsAutosizing = !!m_pageInfo.m_frameWidth
+ && (m_pageInfo.m_baseMultiplier * (static_cast<float>(m_pageInfo.m_layoutWidth) / m_pageInfo.m_frameWidth) > 1.0f);
+ }
+
+ if (m_pageInfo.m_pageNeedsAutosizing) {
+ // If page info has changed, multipliers may have changed. Force a layout to recompute them.
+ if (m_pageInfo.m_frameWidth != previousPageInfo.m_frameWidth
+ || m_pageInfo.m_layoutWidth != previousPageInfo.m_layoutWidth
+ || m_pageInfo.m_baseMultiplier != previousPageInfo.m_baseMultiplier
+ || m_pageInfo.m_settingEnabled != previousPageInfo.m_settingEnabled)
+ setAllTextNeedsLayout();
+ } else if (previousPageInfo.m_hasAutosized) {
+ // If we are no longer autosizing the page, we won't do anything during the next layout.
+ // Set all the multipliers back to 1 now.
+ resetMultipliers();
+ m_pageInfo.m_hasAutosized = false;
+ }
+}
+
+void FastTextAutosizer::resetMultipliers()
+{
+ RenderObject* renderer = m_document->renderView();
+ while (renderer) {
+ if (RenderStyle* style = renderer->style()) {
+ if (style->textAutosizingMultiplier() != 1)
+ applyMultiplier(renderer, 1, LayoutNeeded);
+ }
+ renderer = renderer->nextInPreOrder();
+ }
+}
+
+void FastTextAutosizer::setAllTextNeedsLayout()
+{
+ RenderObject* renderer = m_document->renderView();
+ while (renderer) {
+ if (renderer->isText())
+ renderer->setNeedsLayoutAndFullPaintInvalidation();
+ renderer = renderer->nextInPreOrder();
+ }
+}
+
+FastTextAutosizer::BlockFlags FastTextAutosizer::classifyBlock(const RenderObject* renderer, BlockFlags mask)
+{
+ if (!renderer->isRenderBlock())
+ return 0;
+
+ const RenderBlock* block = toRenderBlock(renderer);
+ BlockFlags flags = 0;
+
+ if (isPotentialClusterRoot(block)) {
+ if (mask & POTENTIAL_ROOT)
+ flags |= POTENTIAL_ROOT;
+
+ if ((mask & INDEPENDENT) && (isIndependentDescendant(block) || block->isTable()))
+ flags |= INDEPENDENT;
+
+ if ((mask & EXPLICIT_WIDTH) && hasExplicitWidth(block))
+ flags |= EXPLICIT_WIDTH;
+
+ if ((mask & SUPPRESSING) && blockSuppressesAutosizing(block))
+ flags |= SUPPRESSING;
+ }
+ return flags;
+}
+
+bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock* root, const RenderBlock* widthProvider)
+{
+ Cluster hypotheticalCluster(root, classifyBlock(root), 0);
+ return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider);
+}
+
+bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const RenderBlock* widthProvider)
+{
+ if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText)
+ return cluster->m_hasEnoughTextToAutosize == HasEnoughText;
+
+ const RenderBlock* root = cluster->m_root;
+ if (!widthProvider)
+ widthProvider = clusterWidthProvider(root);
+
+ // TextAreas and user-modifiable areas get a free pass to autosize regardless of text content.
+ if (root->isTextArea() || (root->style() && root->style()->userModify() != READ_ONLY)) {
+ cluster->m_hasEnoughTextToAutosize = HasEnoughText;
+ return true;
+ }
+
+ if (cluster->m_flags & SUPPRESSING) {
+ cluster->m_hasEnoughTextToAutosize = NotEnoughText;
+ return false;
+ }
+
+ // 4 lines of text is considered enough to autosize.
+ float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4;
+
+ float length = 0;
+ RenderObject* descendant = root->firstChild();
+ while (descendant) {
+ if (descendant->isRenderBlock()) {
+ if (classifyBlock(descendant, INDEPENDENT | SUPPRESSING)) {
+ descendant = descendant->nextInPreOrderAfterChildren(root);
+ continue;
+ }
+ } else if (descendant->isText()) {
+ // Note: Using text().stripWhiteSpace().length() instead of renderedTextLength() because
+ // the lineboxes will not be built until layout. These values can be different.
+ // Note: This is an approximation assuming each character is 1em wide.
+ length += toRenderText(descendant)->text().stripWhiteSpace().length() * descendant->style()->specifiedFontSize();
+
+ if (length >= minimumTextLengthToAutosize) {
+ cluster->m_hasEnoughTextToAutosize = HasEnoughText;
+ return true;
+ }
+ }
+ descendant = descendant->nextInPreOrder(root);
+ }
+
+ cluster->m_hasEnoughTextToAutosize = NotEnoughText;
+ return false;
+}
+
+FastTextAutosizer::Fingerprint FastTextAutosizer::getFingerprint(const RenderObject* renderer)
+{
+ Fingerprint result = m_fingerprintMapper.get(renderer);
+ if (!result) {
+ result = computeFingerprint(renderer);
+ m_fingerprintMapper.add(renderer, result);
+ }
+ return result;
+}
+
+FastTextAutosizer::Fingerprint FastTextAutosizer::computeFingerprint(const RenderObject* renderer)
+{
+ Node* node = renderer->generatingNode();
+ if (!node || !node->isElementNode())
+ return 0;
+
+ FingerprintSourceData data;
+ if (const RenderObject* parent = parentElementRenderer(renderer))
+ data.m_parentHash = getFingerprint(parent);
+
+ data.m_qualifiedNameHash = QualifiedNameHash::hash(toElement(node)->tagQName());
+
+ if (RenderStyle* style = renderer->style()) {
+ data.m_packedStyleProperties = style->direction();
+ data.m_packedStyleProperties |= (style->position() << 1);
+ data.m_packedStyleProperties |= (style->floating() << 4);
+ data.m_packedStyleProperties |= (style->display() << 6);
+ data.m_packedStyleProperties |= (style->width().type() << 11);
+ // packedStyleProperties effectively using 15 bits now.
+
+ // consider for adding: writing mode, padding.
+
+ data.m_width = style->width().getFloatValue();
+ }
+
+ // Use nodeIndex as a rough approximation of column number
+ // (it's too early to call RenderTableCell::col).
+ // FIXME: account for colspan
+ if (renderer->isTableCell())
+ data.m_column = renderer->node()->nodeIndex();
+
+ return StringHasher::computeHash<UChar>(
+ static_cast<const UChar*>(static_cast<const void*>(&data)),
+ sizeof data / sizeof(UChar));
+}
+
+FastTextAutosizer::Cluster* FastTextAutosizer::maybeCreateCluster(const RenderBlock* block)
+{
+ BlockFlags flags = classifyBlock(block);
+ if (!(flags & POTENTIAL_ROOT))
+ return 0;
+
+ Cluster* parentCluster = m_clusterStack.isEmpty() ? 0 : currentCluster();
+ ASSERT(parentCluster || block->isRenderView());
+
+ // If a non-independent block would not alter the SUPPRESSING flag, it doesn't need to be a cluster.
+ bool parentSuppresses = parentCluster && (parentCluster->m_flags & SUPPRESSING);
+ if (!(flags & INDEPENDENT) && !(flags & EXPLICIT_WIDTH) && !!(flags & SUPPRESSING) == parentSuppresses)
+ return 0;
+
+ Cluster* cluster = new Cluster(block, flags, parentCluster, getSupercluster(block));
+#ifdef AUTOSIZING_DOM_DEBUG_INFO
+ // Non-SUPPRESSING clusters are annotated in clusterMultiplier.
+ if (flags & SUPPRESSING)
+ writeClusterDebugInfo(cluster);
+#endif
+ return cluster;
+}
+
+FastTextAutosizer::Supercluster* FastTextAutosizer::getSupercluster(const RenderBlock* block)
+{
+ Fingerprint fingerprint = m_fingerprintMapper.get(block);
+ if (!fingerprint)
+ return 0;
+
+ BlockSet* roots = &m_fingerprintMapper.getTentativeClusterRoots(fingerprint);
+ if (!roots || roots->size() < 2 || !roots->contains(block))
+ return 0;
+
+ SuperclusterMap::AddResult addResult = m_superclusters.add(fingerprint, PassOwnPtr<Supercluster>());
+ if (!addResult.isNewEntry)
+ return addResult.storedValue->value.get();
+
+ Supercluster* supercluster = new Supercluster(roots);
+ addResult.storedValue->value = adoptPtr(supercluster);
+ return supercluster;
+}
+
+float FastTextAutosizer::clusterMultiplier(Cluster* cluster)
+{
+ if (cluster->m_multiplier)
+ return cluster->m_multiplier;
+
+ // FIXME: why does isWiderOrNarrowerDescendant crash on independent clusters?
+ if (!(cluster->m_flags & INDEPENDENT) && isWiderOrNarrowerDescendant(cluster))
+ cluster->m_flags |= WIDER_OR_NARROWER;
+
+ if (cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER)) {
+ if (cluster->m_supercluster)
+ cluster->m_multiplier = superclusterMultiplier(cluster);
+ else if (clusterHasEnoughTextToAutosize(cluster))
+ cluster->m_multiplier = multiplierFromBlock(clusterWidthProvider(cluster->m_root));
+ else
+ cluster->m_multiplier = 1.0f;
+ } else {
+ cluster->m_multiplier = cluster->m_parent ? clusterMultiplier(cluster->m_parent) : 1.0f;
+ }
+
+#ifdef AUTOSIZING_DOM_DEBUG_INFO
+ writeClusterDebugInfo(cluster);
+#endif
+
+ ASSERT(cluster->m_multiplier);
+ return cluster->m_multiplier;
+}
+
+bool FastTextAutosizer::superclusterHasEnoughTextToAutosize(Supercluster* supercluster, const RenderBlock* widthProvider)
+{
+ if (supercluster->m_hasEnoughTextToAutosize != UnknownAmountOfText)
+ return supercluster->m_hasEnoughTextToAutosize == HasEnoughText;
+
+ BlockSet::iterator end = supercluster->m_roots->end();
+ for (BlockSet::iterator it = supercluster->m_roots->begin(); it != end; ++it) {
+ if (clusterWouldHaveEnoughTextToAutosize(*it, widthProvider)) {
+ supercluster->m_hasEnoughTextToAutosize = HasEnoughText;
+ return true;
+ }
+ }
+ supercluster->m_hasEnoughTextToAutosize = NotEnoughText;
+ return false;
+}
+
+float FastTextAutosizer::superclusterMultiplier(Cluster* cluster)
+{
+ Supercluster* supercluster = cluster->m_supercluster;
+ if (!supercluster->m_multiplier) {
+ const RenderBlock* widthProvider = maxClusterWidthProvider(cluster->m_supercluster, cluster->m_root);
+ supercluster->m_multiplier = superclusterHasEnoughTextToAutosize(supercluster, widthProvider)
+ ? multiplierFromBlock(widthProvider) : 1.0f;
+ }
+ ASSERT(supercluster->m_multiplier);
+ return supercluster->m_multiplier;
+}
+
+const RenderBlock* FastTextAutosizer::clusterWidthProvider(const RenderBlock* root)
+{
+ if (root->isTable() || root->isTableCell())
+ return root;
+
+ return deepestBlockContainingAllText(root);
+}
+
+const RenderBlock* FastTextAutosizer::maxClusterWidthProvider(const Supercluster* supercluster, const RenderBlock* currentRoot)
+{
+ const RenderBlock* result = clusterWidthProvider(currentRoot);
+ float maxWidth = widthFromBlock(result);
+
+ const BlockSet* roots = supercluster->m_roots;
+ for (BlockSet::iterator it = roots->begin(); it != roots->end(); ++it) {
+ const RenderBlock* widthProvider = clusterWidthProvider(*it);
+ if (widthProvider->needsLayout())
continue;
+ float width = widthFromBlock(widthProvider);
+ if (width > maxWidth) {
+ maxWidth = width;
+ result = widthProvider;
+ }
+ }
+ RELEASE_ASSERT(result);
+ return result;
+}
+
+float FastTextAutosizer::widthFromBlock(const RenderBlock* block)
+{
+ RELEASE_ASSERT(block);
+ RELEASE_ASSERT(block->style());
+
+ if (!(block->isTable() || block->isTableCell() || block->isListItem()))
+ return block->contentLogicalWidth().toFloat();
+
+ if (!block->containingBlock())
+ return 0;
+
+ // Tables may be inflated before computing their preferred widths. Try several methods to
+ // obtain a width, and fall back on a containing block's width.
+ do {
+ float width;
+ Length specifiedWidth = block->isTableCell()
+ ? toRenderTableCell(block)->styleOrColLogicalWidth() : block->style()->logicalWidth();
+ if (specifiedWidth.isFixed()) {
+ if ((width = specifiedWidth.value()) > 0)
+ return width;
+ }
+ if (specifiedWidth.isPercent()) {
+ if (float containerWidth = block->containingBlock()->contentLogicalWidth().toFloat()) {
+ if ((width = floatValueForLength(specifiedWidth, containerWidth)) > 0)
+ return width;
+ }
+ }
+ if ((width = block->contentLogicalWidth().toFloat()) > 0)
+ return width;
+ } while ((block = block->containingBlock()));
+ return 0;
+}
+
+float FastTextAutosizer::multiplierFromBlock(const RenderBlock* block)
+{
+ // If block->needsLayout() is false, it does not need to be in m_blocksThatHaveBegunLayout.
+ // This can happen during layout of a positioned object if the cluster's DBCAT is deeper
+ // than the positioned object's containing block, and wasn't marked as needing layout.
+ ASSERT(m_blocksThatHaveBegunLayout.contains(block) || !block->needsLayout());
+
+ // Block width, in CSS pixels.
+ float blockWidth = widthFromBlock(block);
+ float multiplier = m_pageInfo.m_frameWidth ? min(blockWidth, static_cast<float>(m_pageInfo.m_layoutWidth)) / m_pageInfo.m_frameWidth : 1.0f;
+
+ return max(m_pageInfo.m_baseMultiplier * multiplier, 1.0f);
+}
+
+const RenderBlock* FastTextAutosizer::deepestBlockContainingAllText(Cluster* cluster)
+{
+ if (!cluster->m_deepestBlockContainingAllText)
+ cluster->m_deepestBlockContainingAllText = deepestBlockContainingAllText(cluster->m_root);
+
+ return cluster->m_deepestBlockContainingAllText;
+}
+
+// FIXME: Refactor this to look more like FastTextAutosizer::deepestCommonAncestor. This is copied
+// from TextAutosizer::findDeepestBlockContainingAllText.
+const RenderBlock* FastTextAutosizer::deepestBlockContainingAllText(const RenderBlock* root)
+{
+ size_t firstDepth = 0;
+ const RenderObject* firstTextLeaf = findTextLeaf(root, firstDepth, First);
+ if (!firstTextLeaf)
+ return root;
+
+ size_t lastDepth = 0;
+ const RenderObject* lastTextLeaf = findTextLeaf(root, lastDepth, Last);
+ ASSERT(lastTextLeaf);
+
+ // Equalize the depths if necessary. Only one of the while loops below will get executed.
+ const RenderObject* firstNode = firstTextLeaf;
+ const RenderObject* lastNode = lastTextLeaf;
+ while (firstDepth > lastDepth) {
+ firstNode = firstNode->parent();
+ --firstDepth;
+ }
+ while (lastDepth > firstDepth) {
+ lastNode = lastNode->parent();
+ --lastDepth;
+ }
+
+ // Go up from both nodes until the parent is the same. Both pointers will point to the LCA then.
+ while (firstNode != lastNode) {
+ firstNode = firstNode->parent();
+ lastNode = lastNode->parent();
+ }
+
+ if (firstNode->isRenderBlock())
+ return toRenderBlock(firstNode);
+
+ // containingBlock() should never leave the cluster, since it only skips ancestors when finding
+ // the container of position:absolute/fixed blocks, and those cannot exist between a cluster and
+ // its text node's lowest common ancestor as isAutosizingCluster would have made them into their
+ // own independent cluster.
+ const RenderBlock* containingBlock = firstNode->containingBlock();
+ if (!containingBlock)
+ return root;
+
+ ASSERT(containingBlock->isDescendantOf(root));
+ return containingBlock;
+}
+
+const RenderObject* FastTextAutosizer::findTextLeaf(const RenderObject* parent, size_t& depth, TextLeafSearch firstOrLast)
+{
+ // List items are treated as text due to the marker.
+ // The actual renderer for the marker (RenderListMarker) may not be in the tree yet since it is added during layout.
+ if (parent->isListItem())
+ return parent;
+
+ if (parent->isText())
+ return parent;
+
+ ++depth;
+ const RenderObject* child = (firstOrLast == First) ? parent->slowFirstChild() : parent->slowLastChild();
+ while (child) {
+ // Note: At this point clusters may not have been created for these blocks so we cannot rely
+ // on m_clusters. Instead, we use a best-guess about whether the block will become a cluster.
+ if (!classifyBlock(child, INDEPENDENT)) {
+ if (const RenderObject* leaf = findTextLeaf(child, depth, firstOrLast))
+ return leaf;
+ }
+ child = (firstOrLast == First) ? child->nextSibling() : child->previousSibling();
+ }
+ --depth;
+
+ return 0;
+}
+
+void FastTextAutosizer::applyMultiplier(RenderObject* renderer, float multiplier, RelayoutBehavior relayoutBehavior)
+{
+ ASSERT(renderer && renderer->style());
+ RenderStyle* currentStyle = renderer->style();
+ if (currentStyle->textAutosizingMultiplier() == multiplier)
+ return;
+
+ // We need to clone the render style to avoid breaking style sharing.
+ RefPtr<RenderStyle> style = RenderStyle::clone(currentStyle);
+ style->setTextAutosizingMultiplier(multiplier);
+ style->setUnique();
+
+ switch (relayoutBehavior) {
+ case AlreadyInLayout:
+ // Don't free currentStyle until the end of the layout pass. This allows other parts of the system
+ // to safely hold raw RenderStyle* pointers during layout, e.g. BreakingContext::m_currentStyle.
+ m_stylesRetainedDuringLayout.append(currentStyle);
+
+ renderer->setStyleInternal(style.release());
+ renderer->setNeedsLayoutAndFullPaintInvalidation();
+ break;
+
+ case LayoutNeeded:
+ renderer->setStyle(style.release());
+ break;
+ }
+
+ if (multiplier != 1)
+ m_pageInfo.m_hasAutosized = true;
+}
+
+bool FastTextAutosizer::isWiderOrNarrowerDescendant(Cluster* cluster)
+{
+ // FIXME: Why do we return true when hasExplicitWidth returns false??
+ if (!cluster->m_parent || !hasExplicitWidth(cluster->m_root))
+ return true;
+
+ const RenderBlock* parentDeepestBlockContainingAllText = deepestBlockContainingAllText(cluster->m_parent);
+ ASSERT(m_blocksThatHaveBegunLayout.contains(cluster->m_root));
+ ASSERT(m_blocksThatHaveBegunLayout.contains(parentDeepestBlockContainingAllText));
+
+ float contentWidth = cluster->m_root->contentLogicalWidth().toFloat();
+ float clusterTextWidth = parentDeepestBlockContainingAllText->contentLogicalWidth().toFloat();
+
+ // Clusters with a root that is wider than the deepestBlockContainingAllText of their parent
+ // autosize independently of their parent.
+ if (contentWidth > clusterTextWidth)
+ return true;
- applyMultiplier(inlineObj, cluster->m_multiplier);
+ // Clusters with a root that is significantly narrower than the deepestBlockContainingAllText of
+ // their parent autosize independently of their parent.
+ static float narrowWidthDifference = 200;
+ if (clusterTextWidth - contentWidth > narrowWidthDifference)
+ return true;
+
+ return false;
+}
+
+FastTextAutosizer::Cluster* FastTextAutosizer::currentCluster() const
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!m_clusterStack.isEmpty());
+ return m_clusterStack.last().get();
+}
+
+#ifndef NDEBUG
+void FastTextAutosizer::FingerprintMapper::assertMapsAreConsistent()
+{
+ // For each fingerprint -> block mapping in m_blocksForFingerprint we should have an associated
+ // map from block -> fingerprint in m_fingerprints.
+ ReverseFingerprintMap::iterator end = m_blocksForFingerprint.end();
+ for (ReverseFingerprintMap::iterator fingerprintIt = m_blocksForFingerprint.begin(); fingerprintIt != end; ++fingerprintIt) {
+ Fingerprint fingerprint = fingerprintIt->key;
+ BlockSet* blocks = fingerprintIt->value.get();
+ for (BlockSet::iterator blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt) {
+ const RenderBlock* block = (*blockIt);
+ ASSERT(m_fingerprints.get(block) == fingerprint);
+ }
}
}
+#endif
+
+void FastTextAutosizer::FingerprintMapper::add(const RenderObject* renderer, Fingerprint fingerprint)
+{
+ remove(renderer);
+
+ m_fingerprints.set(renderer, fingerprint);
+#ifndef NDEBUG
+ assertMapsAreConsistent();
+#endif
+}
+
+void FastTextAutosizer::FingerprintMapper::addTentativeClusterRoot(const RenderBlock* block, Fingerprint fingerprint)
+{
+ add(block, fingerprint);
+
+ ReverseFingerprintMap::AddResult addResult = m_blocksForFingerprint.add(fingerprint, PassOwnPtr<BlockSet>());
+ if (addResult.isNewEntry)
+ addResult.storedValue->value = adoptPtr(new BlockSet);
+ addResult.storedValue->value->add(block);
+#ifndef NDEBUG
+ assertMapsAreConsistent();
+#endif
+}
+
+bool FastTextAutosizer::FingerprintMapper::remove(const RenderObject* renderer)
+{
+ Fingerprint fingerprint = m_fingerprints.take(renderer);
+ if (!fingerprint || !renderer->isRenderBlock())
+ return false;
+
+ ReverseFingerprintMap::iterator blocksIter = m_blocksForFingerprint.find(fingerprint);
+ if (blocksIter == m_blocksForFingerprint.end())
+ return false;
+
+ BlockSet& blocks = *blocksIter->value;
+ blocks.remove(toRenderBlock(renderer));
+ if (blocks.isEmpty())
+ m_blocksForFingerprint.remove(blocksIter);
+#ifndef NDEBUG
+ assertMapsAreConsistent();
+#endif
+ return true;
+}
-AtomicString FastTextAutosizer::fingerprint(const RenderBlock* block)
+FastTextAutosizer::Fingerprint FastTextAutosizer::FingerprintMapper::get(const RenderObject* renderer)
{
- // FIXME(crbug.com/322340): Implement a better fingerprinting algorithm.
- return String::number((unsigned long long) block);
+ return m_fingerprints.get(renderer);
}
-float FastTextAutosizer::computeMultiplier(const FastTextAutosizer::Cluster* cluster)
+FastTextAutosizer::BlockSet& FastTextAutosizer::FingerprintMapper::getTentativeClusterRoots(Fingerprint fingerprint)
{
- const WTF::HashSet<const RenderBlock*>& blocks = cluster->m_blocks;
+ return *m_blocksForFingerprint.get(fingerprint);
+}
+
+FastTextAutosizer::LayoutScope::LayoutScope(RenderBlock* block)
+ : m_textAutosizer(block->document().fastTextAutosizer())
+ , m_block(block)
+{
+ if (!m_textAutosizer)
+ return;
- bool shouldAutosize = false;
- for (WTF::HashSet<const RenderBlock*>::iterator it = blocks.begin(); it != blocks.end(); ++it)
- shouldAutosize |= TextAutosizer::containerShouldBeAutosized(*it);
+ if (m_textAutosizer->shouldHandleLayout())
+ m_textAutosizer->beginLayout(m_block);
+ else
+ m_textAutosizer = 0;
+}
- if (!shouldAutosize)
- return 1.0f;
+FastTextAutosizer::LayoutScope::~LayoutScope()
+{
+ if (m_textAutosizer)
+ m_textAutosizer->endLayout(m_block);
+}
- // FIXME(crbug.com/322344): Implement multiplier computation.
- return 1.5f;
+
+FastTextAutosizer::TableLayoutScope::TableLayoutScope(RenderTable* table)
+ : LayoutScope(table)
+{
+ if (m_textAutosizer) {
+ ASSERT(m_textAutosizer->shouldHandleLayout());
+ m_textAutosizer->inflateAutoTable(table);
+ }
+}
+
+FastTextAutosizer::DeferUpdatePageInfo::DeferUpdatePageInfo(Page* page)
+ : m_mainFrame(page->deprecatedLocalMainFrame())
+{
+ if (FastTextAutosizer* textAutosizer = m_mainFrame->document()->fastTextAutosizer()) {
+ ASSERT(!textAutosizer->m_updatePageInfoDeferred);
+ textAutosizer->m_updatePageInfoDeferred = true;
+ }
+}
+
+FastTextAutosizer::DeferUpdatePageInfo::~DeferUpdatePageInfo()
+{
+ if (FastTextAutosizer* textAutosizer = m_mainFrame->document()->fastTextAutosizer()) {
+ ASSERT(textAutosizer->m_updatePageInfoDeferred);
+ textAutosizer->m_updatePageInfoDeferred = false;
+ textAutosizer->updatePageInfoInAllFrames();
+ }
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h b/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h
index 16265fd899a..f3f5efb2eab 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h
@@ -31,17 +31,20 @@
#ifndef FastTextAutosizer_h
#define FastTextAutosizer_h
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderTable.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
-#include "wtf/text/AtomicStringHash.h"
namespace WebCore {
class Document;
class RenderBlock;
+class RenderListItem;
+class RenderListMarker;
// Single-pass text autosizer (work in progress). Works in two stages:
// (1) record information about page elements during style recalc
@@ -52,38 +55,255 @@ class FastTextAutosizer FINAL {
WTF_MAKE_NONCOPYABLE(FastTextAutosizer);
public:
- static PassOwnPtr<FastTextAutosizer> create(Document* document)
+ static PassOwnPtr<FastTextAutosizer> create(const Document* document)
{
return adoptPtr(new FastTextAutosizer(document));
}
+ void updatePageInfoInAllFrames();
+ void updatePageInfo();
void record(const RenderBlock*);
void destroy(const RenderBlock*);
- void inflate(RenderBlock*);
+ void inflateListItem(RenderListItem*, RenderListMarker*);
+
+ class LayoutScope {
+ public:
+ explicit LayoutScope(RenderBlock*);
+ ~LayoutScope();
+ protected:
+ FastTextAutosizer* m_textAutosizer;
+ RenderBlock* m_block;
+ };
+
+ class TableLayoutScope : LayoutScope {
+ public:
+ explicit TableLayoutScope(RenderTable*);
+ };
+
+ class DeferUpdatePageInfo {
+ public:
+ explicit DeferUpdatePageInfo(Page*);
+ ~DeferUpdatePageInfo();
+ private:
+ RefPtr<LocalFrame> m_mainFrame;
+ };
private:
- // TODO: make a proper API for this class?
+ typedef HashSet<const RenderBlock*> BlockSet;
+
+ enum HasEnoughTextToAutosize {
+ UnknownAmountOfText,
+ HasEnoughText,
+ NotEnoughText
+ };
+
+ enum RelayoutBehavior {
+ AlreadyInLayout, // The default; appropriate if we are already in layout.
+ LayoutNeeded // Use this if changing a multiplier outside of layout.
+ };
+
+ enum BeginLayoutBehavior {
+ StopLayout,
+ ContinueLayout
+ };
+
+ enum InflateBehavior {
+ ThisBlockOnly,
+ DescendToInnerBlocks
+ };
+
+ enum BlockFlag {
+ // A block that is evaluated for becoming a cluster root.
+ POTENTIAL_ROOT = 1 << 0,
+ // A cluster root that establishes an independent multiplier.
+ INDEPENDENT = 1 << 1,
+ // A cluster root with an explicit width. These are likely to be independent.
+ EXPLICIT_WIDTH = 1 << 2,
+ // A cluster that is wider or narrower than its parent. These also create an
+ // independent multiplier, but this state cannot be determined until layout.
+ WIDER_OR_NARROWER = 1 << 3,
+ // A cluster that suppresses autosizing.
+ SUPPRESSING = 1 << 4
+ };
+
+ typedef unsigned BlockFlags;
+
+ // A supercluster represents autosizing information about a set of two or
+ // more blocks that all have the same fingerprint. Clusters whose roots
+ // belong to a supercluster will share a common multiplier and
+ // text-length-based autosizing status.
+ struct Supercluster {
+ explicit Supercluster(const BlockSet* roots)
+ : m_roots(roots)
+ , m_hasEnoughTextToAutosize(UnknownAmountOfText)
+ , m_multiplier(0)
+ {
+ }
+
+ const BlockSet* const m_roots;
+ HasEnoughTextToAutosize m_hasEnoughTextToAutosize;
+ float m_multiplier;
+ };
+
struct Cluster {
- explicit Cluster(AtomicString fingerprint)
- : m_fingerprint(fingerprint)
+ explicit Cluster(const RenderBlock* root, BlockFlags flags, Cluster* parent, Supercluster* supercluster = 0)
+ : m_root(root)
+ , m_flags(flags)
+ , m_deepestBlockContainingAllText(0)
+ , m_parent(parent)
, m_multiplier(0)
+ , m_hasEnoughTextToAutosize(UnknownAmountOfText)
+ , m_supercluster(supercluster)
+ , m_hasTableAncestor(root->isTableCell() || (m_parent && m_parent->m_hasTableAncestor))
{
}
- AtomicString m_fingerprint;
- WTF::HashSet<const RenderBlock*> m_blocks;
+ const RenderBlock* const m_root;
+ BlockFlags m_flags;
+ // The deepest block containing all text is computed lazily (see:
+ // deepestBlockContainingAllText). A value of 0 indicates the value has not been computed yet.
+ const RenderBlock* m_deepestBlockContainingAllText;
+ Cluster* m_parent;
+ // The multiplier is computed lazily (see: clusterMultiplier) because it must be calculated
+ // after the lowest block containing all text has entered layout (the
+ // m_blocksThatHaveBegunLayout assertions cover this). Note: the multiplier is still
+ // calculated when m_autosize is false because child clusters may depend on this multiplier.
float m_multiplier;
+ HasEnoughTextToAutosize m_hasEnoughTextToAutosize;
+ // A set of blocks that are similar to this block.
+ Supercluster* m_supercluster;
+ bool m_hasTableAncestor;
+ };
+
+ enum TextLeafSearch {
+ First,
+ Last
+ };
+
+ struct FingerprintSourceData {
+ FingerprintSourceData()
+ : m_parentHash(0)
+ , m_qualifiedNameHash(0)
+ , m_packedStyleProperties(0)
+ , m_column(0)
+ , m_width(0)
+ {
+ }
+
+ unsigned m_parentHash;
+ unsigned m_qualifiedNameHash;
+ // Style specific selection of signals
+ unsigned m_packedStyleProperties;
+ unsigned m_column;
+ float m_width;
+ };
+ // Ensures efficient hashing using StringHasher.
+ COMPILE_ASSERT(!(sizeof(FingerprintSourceData) % sizeof(UChar)),
+ Sizeof_FingerprintSourceData_must_be_multiple_of_UChar);
+
+ typedef unsigned Fingerprint;
+ typedef HashMap<Fingerprint, OwnPtr<Supercluster> > SuperclusterMap;
+ typedef Vector<OwnPtr<Cluster> > ClusterStack;
+
+ // Fingerprints are computed during style recalc, for (some subset of)
+ // blocks that will become cluster roots.
+ class FingerprintMapper {
+ public:
+ void add(const RenderObject*, Fingerprint);
+ void addTentativeClusterRoot(const RenderBlock*, Fingerprint);
+ // Returns true if any BlockSet was modified or freed by the removal.
+ bool remove(const RenderObject*);
+ Fingerprint get(const RenderObject*);
+ BlockSet& getTentativeClusterRoots(Fingerprint);
+ private:
+ typedef HashMap<const RenderObject*, Fingerprint> FingerprintMap;
+ typedef HashMap<Fingerprint, OwnPtr<BlockSet> > ReverseFingerprintMap;
+
+ FingerprintMap m_fingerprints;
+ ReverseFingerprintMap m_blocksForFingerprint;
+#ifndef NDEBUG
+ void assertMapsAreConsistent();
+#endif
+ };
+
+ struct PageInfo {
+ PageInfo()
+ : m_frameWidth(0)
+ , m_layoutWidth(0)
+ , m_baseMultiplier(0)
+ , m_pageNeedsAutosizing(false)
+ , m_hasAutosized(false)
+ , m_settingEnabled(false)
+ {
+ }
+
+ int m_frameWidth; // LocalFrame width in density-independent pixels (DIPs).
+ int m_layoutWidth; // Layout width in CSS pixels.
+ float m_baseMultiplier; // Includes accessibility font scale factor and device scale adjustment.
+ bool m_pageNeedsAutosizing;
+ bool m_hasAutosized;
+ bool m_settingEnabled;
};
- explicit FastTextAutosizer(Document*);
+ explicit FastTextAutosizer(const Document*);
- AtomicString fingerprint(const RenderBlock*);
- float computeMultiplier(const Cluster*);
+ void beginLayout(RenderBlock*);
+ void endLayout(RenderBlock*);
+ void inflateAutoTable(RenderTable*);
+ float inflate(RenderObject*, InflateBehavior = ThisBlockOnly, float multiplier = 0);
+ bool shouldHandleLayout() const;
+ void setAllTextNeedsLayout();
+ void resetMultipliers();
+ BeginLayoutBehavior prepareForLayout(const RenderBlock*);
+ void prepareClusterStack(const RenderObject*);
+ bool clusterHasEnoughTextToAutosize(Cluster*, const RenderBlock* widthProvider = 0);
+ bool superclusterHasEnoughTextToAutosize(Supercluster*, const RenderBlock* widthProvider = 0);
+ bool clusterWouldHaveEnoughTextToAutosize(const RenderBlock* root, const RenderBlock* widthProvider = 0);
+ Fingerprint getFingerprint(const RenderObject*);
+ Fingerprint computeFingerprint(const RenderObject*);
+ Cluster* maybeCreateCluster(const RenderBlock*);
+ Supercluster* getSupercluster(const RenderBlock*);
+ float clusterMultiplier(Cluster*);
+ float superclusterMultiplier(Cluster*);
+ // A cluster's width provider is typically the deepest block containing all text.
+ // There are exceptions, such as tables and table cells which use the table itself for width.
+ const RenderBlock* clusterWidthProvider(const RenderBlock*);
+ const RenderBlock* maxClusterWidthProvider(const Supercluster*, const RenderBlock* currentRoot);
+ // Typically this returns a block's computed width. In the case of tables layout, this
+ // width is not yet known so the fixed width is used if it's available, or the containing
+ // block's width otherwise.
+ float widthFromBlock(const RenderBlock*);
+ float multiplierFromBlock(const RenderBlock*);
+ void applyMultiplier(RenderObject*, float, RelayoutBehavior = AlreadyInLayout);
+ bool isWiderOrNarrowerDescendant(Cluster*);
+ Cluster* currentCluster() const;
+ const RenderBlock* deepestBlockContainingAllText(Cluster*);
+ const RenderBlock* deepestBlockContainingAllText(const RenderBlock*);
+ // Returns the first text leaf that is in the current cluster. We attempt to not include text
+ // from descendant clusters but because descendant clusters may not exist, this is only an approximation.
+ // The TraversalDirection controls whether we return the first or the last text leaf.
+ const RenderObject* findTextLeaf(const RenderObject*, size_t&, TextLeafSearch);
+ BlockFlags classifyBlock(const RenderObject*, BlockFlags mask = UINT_MAX);
+#ifdef AUTOSIZING_DOM_DEBUG_INFO
+ void writeClusterDebugInfo(Cluster*);
+#endif
- Document* m_document;
+ const Document* m_document;
+ const RenderBlock* m_firstBlockToBeginLayout;
+#ifndef NDEBUG
+ BlockSet m_blocksThatHaveBegunLayout; // Used to ensure we don't compute properties of a block before beginLayout() is called on it.
+#endif
- WTF::HashMap<const RenderBlock*, Cluster*> m_clusterForBlock;
- WTF::HashMap<AtomicString, OwnPtr<Cluster> > m_clusterForFingerprint;
+ // Clusters are created and destroyed during layout. The map key is the
+ // cluster root. Clusters whose roots share the same fingerprint use the
+ // same multiplier.
+ SuperclusterMap m_superclusters;
+ ClusterStack m_clusterStack;
+ FingerprintMapper m_fingerprintMapper;
+ Vector<RefPtr<RenderStyle> > m_stylesRetainedDuringLayout;
+ // FIXME: All frames should share the same m_pageInfo instance.
+ PageInfo m_pageInfo;
+ bool m_updatePageInfoDeferred;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.cpp b/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.cpp
index ff60e9b0d76..3774afb7ec5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.cpp
@@ -45,11 +45,6 @@
#include "platform/graphics/filters/FEComponentTransfer.h"
#include "platform/graphics/filters/FEDropShadow.h"
#include "platform/graphics/filters/FEGaussianBlur.h"
-#include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
-#include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
-#include "platform/graphics/filters/custom/FECustomFilter.h"
-#include "platform/graphics/filters/custom/ValidatedCustomFilterOperation.h"
-#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
#include "wtf/MathExtras.h"
#include <algorithm>
@@ -70,35 +65,11 @@ static inline void lastMatrixRow(Vector<float>& parameters)
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;
-}
-
-static PassRefPtr<FECustomFilter> createCustomFilterEffect(Filter* filter, Document* document, ValidatedCustomFilterOperation* operation)
-{
- if (!document)
- return 0;
-
- CustomFilterGlobalContext* globalContext = document->renderView()->customFilterGlobalContext();
- globalContext->prepareContextIfNeeded();
- if (!globalContext->context())
- return 0;
-
- return FECustomFilter::create(filter, globalContext->context(), operation->validatedProgram(), operation->parameters(),
- operation->meshRows(), operation->meshColumns(), operation->meshType());
-}
-
FilterEffectRenderer::FilterEffectRenderer()
: Filter(AffineTransform())
, m_graphicsBufferAttached(false)
, m_hasFilterThatMovesPixels(false)
- , m_hasCustomShaderFilter(false)
{
- setFilterResolution(FloatSize(1, 1));
m_sourceGraphic = SourceGraphic::create(this);
}
@@ -113,14 +84,15 @@ GraphicsContext* FilterEffectRenderer::inputContext()
bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& operations)
{
- m_hasCustomShaderFilter = false;
m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
// Inverse zoom the pre-zoomed CSS shorthand filters, so that they are in the same zoom as the unzoomed reference filters.
const RenderStyle* style = renderer->style();
- // FIXME: The effects now contain high dpi information, but the software path doesn't (yet) scale its backing.
- // When the proper dpi dependant backing size is allocated, we should remove deviceScaleFactor(...) here.
+#ifdef BLINK_SCALE_FILTERS_AT_RECORD_TIME
float invZoom = 1.0f / ((style ? style->effectiveZoom() : 1.0f) * deviceScaleFactor(renderer->frame()));
+#else
+ float invZoom = style ? 1.0f / style->effectiveZoom() : 1.0f;
+#endif
RefPtr<FilterEffect> previousEffect = m_sourceGraphic;
for (size_t i = 0; i < operations.operations().size(); ++i) {
@@ -256,18 +228,6 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
effect = FEDropShadow::create(this, stdDeviation, stdDeviation, x, y, dropShadowOperation->color(), 1);
break;
}
- case FilterOperation::CUSTOM:
- // CUSTOM operations are always converted to VALIDATED_CUSTOM before getting here.
- // The conversion happens in RenderLayer::computeFilterOperations.
- ASSERT_NOT_REACHED();
- break;
- case FilterOperation::VALIDATED_CUSTOM: {
- Document* document = renderer ? &renderer->document() : 0;
- effect = createCustomFilterEffect(this, document, toValidatedCustomFilterOperation(filterOperation));
- if (effect)
- m_hasCustomShaderFilter = true;
- break;
- }
default:
break;
}
@@ -283,7 +243,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
}
}
- // We need to keep the old effects alive until this point, so that filters like FECustomFilter
+ // We need to keep the old effects alive until this point, so that SVG reference filters
// can share cached resources across frames.
m_lastEffect = previousEffect;
@@ -294,9 +254,10 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
return true;
}
-bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect)
+bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& floatFilterRect)
{
- if (!filterRect.isZero() && isFilterSizeValid(filterRect)) {
+ IntRect filterRect = enclosingIntRect(floatFilterRect);
+ if (!filterRect.isEmpty() && FilterEffect::isFilterSizeValid(filterRect)) {
FloatRect currentSourceRect = sourceImageRect();
if (filterRect != currentSourceRect) {
setSourceImageRect(filterRect);
@@ -314,13 +275,7 @@ void FilterEffectRenderer::allocateBackingStoreIfNeeded()
if (!m_graphicsBufferAttached) {
IntSize logicalSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height());
if (!sourceImage() || sourceImage()->size() != logicalSize) {
- OwnPtr<ImageBufferSurface> surface;
- if (isAccelerated()) {
- surface = adoptPtr(new AcceleratedImageBufferSurface(logicalSize));
- }
- if (!surface || !surface->isValid()) {
- surface = adoptPtr(new UnacceleratedImageBufferSurface(logicalSize));
- }
+ OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSurface(logicalSize));
setSourceImage(ImageBuffer::create(surface.release()));
}
m_graphicsBufferAttached = true;
@@ -342,18 +297,11 @@ void FilterEffectRenderer::apply()
LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
{
- 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;
- }
// The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect".
FloatRect rectForRepaint = dirtyRect;
- rectForRepaint.move(-filterBoxRect.location().x(), -filterBoxRect.location().y());
float inf = std::numeric_limits<float>::infinity();
FloatRect clipRect = FloatRect(FloatPoint(-inf, -inf), FloatSize(inf, inf));
rectForRepaint = lastEffect()->getSourceRect(rectForRepaint, clipRect);
- rectForRepaint.move(filterBoxRect.location().x(), filterBoxRect.location().y());
rectForRepaint.intersect(filterBoxRect);
return LayoutRect(rectForRepaint);
}
@@ -364,8 +312,22 @@ bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, c
m_renderLayer = renderLayer;
m_repaintRect = dirtyRect;
+ // Get the zoom factor to scale the filterSourceRect input
+ const RenderLayerModelObject* renderer = renderLayer->renderer();
+ const RenderStyle* style = renderer ? renderer->style() : 0;
+ float zoom = style ? style->effectiveZoom() : 1.0f;
+
+ // Prepare a transformation that brings the coordinates into the space
+ // filter coordinates are defined in.
+ AffineTransform absoluteTransform;
+ // FIXME: Should these really be upconverted to doubles and not rounded? crbug.com/350474
+ absoluteTransform.translate(filterBoxRect.x().toDouble(), filterBoxRect.y().toDouble());
+ absoluteTransform.scale(zoom, zoom);
+
FilterEffectRenderer* filter = renderLayer->filterRenderer();
- LayoutRect filterSourceRect = filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
+ filter->setAbsoluteTransform(absoluteTransform);
+
+ IntRect filterSourceRect = pixelSnappedIntRect(filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect));
if (filterSourceRect.isEmpty()) {
// The dirty rect is not in view, just bail out.
@@ -373,16 +335,7 @@ bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, c
return false;
}
- // Get the zoom factor to scale the filterSourceRect input
- const RenderLayerModelObject* renderer = renderLayer->renderer();
- const RenderStyle* style = renderer ? renderer->style() : 0;
- float zoom = style ? style->effectiveZoom() : 1.0f;
-
- AffineTransform absoluteTransform;
- absoluteTransform.translate(filterBoxRect.x(), filterBoxRect.y());
- filter->setAbsoluteTransform(absoluteTransform);
- filter->setAbsoluteFilterRegion(AffineTransform().scale(zoom).mapRect(filterSourceRect));
- filter->setFilterRegion(absoluteTransform.inverse().mapRect(filterSourceRect));
+ filter->setFilterRegion(filter->mapAbsoluteRectToLocalRect(filterSourceRect));
filter->lastEffect()->determineFilterPrimitiveSubregion(MapRectForward);
bool hasUpdatedBackingStore = filter->updateBackingStoreRect(filterSourceRect);
@@ -405,7 +358,7 @@ GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext*
filter->allocateBackingStoreIfNeeded();
// Paint into the context that represents the SourceGraphic of the filter.
GraphicsContext* sourceGraphicsContext = filter->inputContext();
- if (!sourceGraphicsContext || !isFilterSizeValid(filter->absoluteFilterRegion())) {
+ if (!sourceGraphicsContext || !FilterEffect::isFilterSizeValid(filter->absoluteFilterRegion())) {
// Disable the filters and continue.
m_haveFilterEffect = false;
return oldContext;
@@ -434,7 +387,7 @@ GraphicsContext* FilterEffectRendererHelper::applyFilterEffect()
filter->apply();
// Get the filtered output and draw it in place.
- m_savedGraphicsContext->drawImageBuffer(filter->output(), filter->outputRect(), CompositeSourceOver);
+ m_savedGraphicsContext->drawImageBuffer(filter->output(), filter->outputRect());
filter->clearIntermediateResults();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.h b/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.h
index 54f67f0ae8b..70c6909897e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/FilterEffectRenderer.h
@@ -30,7 +30,6 @@
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntRectExtent.h"
#include "platform/geometry/LayoutRect.h"
-#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/filters/Filter.h"
#include "platform/graphics/filters/FilterEffect.h"
@@ -42,9 +41,6 @@
namespace WebCore {
-class ShaderResource;
-class CustomFilterProgram;
-class Document;
class GraphicsContext;
class RenderLayer;
class RenderObject;
@@ -74,7 +70,7 @@ private:
bool m_haveFilterEffect;
};
-class FilterEffectRenderer : public Filter
+class FilterEffectRenderer FINAL : public Filter
{
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -83,12 +79,12 @@ public:
return adoptRef(new FilterEffectRenderer());
}
- void setSourceImageRect(const FloatRect& sourceImageRect)
+ void setSourceImageRect(const IntRect& sourceImageRect)
{
m_sourceDrawingRegion = sourceImageRect;
m_graphicsBufferAttached = false;
}
- virtual FloatRect sourceImageRect() const { return m_sourceDrawingRegion; }
+ virtual IntRect sourceImageRect() const OVERRIDE { return m_sourceDrawingRegion; }
GraphicsContext* inputContext();
ImageBuffer* output() const { return lastEffect()->asImageBuffer(); }
@@ -104,7 +100,6 @@ public:
bool hasFilterThatMovesPixels() const { return m_hasFilterThatMovesPixels; }
LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);
- bool hasCustomShaderFilter() const { return m_hasCustomShaderFilter; }
PassRefPtr<FilterEffect> lastEffect() const
{
return m_lastEffect;
@@ -114,7 +109,7 @@ private:
FilterEffectRenderer();
virtual ~FilterEffectRenderer();
- FloatRect m_sourceDrawingRegion;
+ IntRect m_sourceDrawingRegion;
RefPtr<SourceGraphic> m_sourceGraphic;
RefPtr<FilterEffect> m_lastEffect;
@@ -123,7 +118,6 @@ private:
bool m_graphicsBufferAttached;
bool m_hasFilterThatMovesPixels;
- bool m_hasCustomShaderFilter;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FixedTableLayout.cpp b/chromium/third_party/WebKit/Source/core/rendering/FixedTableLayout.cpp
index 83cc6cebe96..25e4b83ffd3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FixedTableLayout.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/FixedTableLayout.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2002 Lars Knoll (knoll@kde.org)
* (C) 2002 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -137,18 +137,13 @@ int FixedTableLayout::calcWidthArray()
unsigned currentColumn = 0;
- RenderObject* firstRow = section->firstChild();
- for (RenderObject* child = firstRow->firstChild(); child; child = child->nextSibling()) {
- if (!child->isTableCell())
- continue;
-
- RenderTableCell* cell = toRenderTableCell(child);
-
+ RenderTableRow* firstRow = section->firstRow();
+ for (RenderTableCell* cell = firstRow->firstCell(); cell; cell = cell->nextCell()) {
Length logicalWidth = cell->styleOrColLogicalWidth();
unsigned span = cell->colSpan();
int fixedBorderBoxLogicalWidth = 0;
// FIXME: Support other length types. If the width is non-auto, it should probably just use
- // RenderBox::computeLogicalWidthInRegionUsing to compute the width.
+ // RenderBox::computeLogicalWidthUsing to compute the width.
if (logicalWidth.isFixed() && logicalWidth.isPositive()) {
fixedBorderBoxLogicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(logicalWidth.value());
logicalWidth.setValue(fixedBorderBoxLogicalWidth);
@@ -330,11 +325,8 @@ void FixedTableLayout::willChangeTableLayout()
RenderTableRow* row = section->rowRendererAt(i);
if (!row)
continue;
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (!cell->isTableCell())
- continue;
+ for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
cell->setPreferredLogicalWidthsDirty();
- }
}
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.cpp b/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.cpp
index 152a3a329c6..d455f53c053 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.cpp
@@ -93,7 +93,6 @@ PassOwnPtr<FloatingObject> FloatingObject::copyToNewContainer(LayoutSize offset,
PassOwnPtr<FloatingObject> FloatingObject::unsafeClone() const
{
OwnPtr<FloatingObject> cloneObject = adoptPtr(new FloatingObject(renderer(), type(), m_frameRect, m_shouldPaint, m_isDescendant));
- cloneObject->m_originatingLine = m_originatingLine;
cloneObject->m_paginationStrut = m_paginationStrut;
cloneObject->m_isPlaced = m_isPlaced;
return cloneObject.release();
@@ -113,16 +112,16 @@ public:
{
}
+ virtual ~ComputeFloatOffsetAdapter() { }
+
int lowValue() const { return m_lineTop; }
int highValue() const { return m_lineBottom; }
void collectIfNeeded(const IntervalType&);
LayoutUnit offset() const { return m_offset; }
- LayoutUnit shapeOffset() const;
- LayoutUnit heightRemaining() const;
-private:
- bool updateOffsetIfNeeded(const FloatingObject*);
+protected:
+ virtual bool updateOffsetIfNeeded(const FloatingObject*) = 0;
const RenderBlockFlow* m_renderer;
int m_lineTop;
@@ -131,11 +130,39 @@ private:
const FloatingObject* m_outermostFloat;
};
+template <FloatingObject::Type FloatTypeValue>
+class ComputeFloatOffsetForFloatLayoutAdapter : public ComputeFloatOffsetAdapter<FloatTypeValue> {
+public:
+ ComputeFloatOffsetForFloatLayoutAdapter(const RenderBlockFlow* renderer, LayoutUnit lineTop, LayoutUnit lineBottom, LayoutUnit offset)
+ : ComputeFloatOffsetAdapter<FloatTypeValue>(renderer, lineTop, lineBottom, offset)
+ {
+ }
+
+ virtual ~ComputeFloatOffsetForFloatLayoutAdapter() { }
+
+ LayoutUnit heightRemaining() const;
+
+protected:
+ virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL;
+};
+
+template <FloatingObject::Type FloatTypeValue>
+class ComputeFloatOffsetForLineLayoutAdapter : public ComputeFloatOffsetAdapter<FloatTypeValue> {
+public:
+ ComputeFloatOffsetForLineLayoutAdapter(const RenderBlockFlow* renderer, LayoutUnit lineTop, LayoutUnit lineBottom, LayoutUnit offset)
+ : ComputeFloatOffsetAdapter<FloatTypeValue>(renderer, lineTop, lineBottom, offset)
+ {
+ }
+
+ virtual ~ComputeFloatOffsetForLineLayoutAdapter() { }
+
+protected:
+ virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL;
+};
+
FloatingObjects::~FloatingObjects()
{
- // FIXME: m_set should use OwnPtr instead.
- deleteAllValues(m_set);
}
void FloatingObjects::clearLineBoxTreePointers()
{
@@ -147,17 +174,6 @@ void FloatingObjects::clearLineBoxTreePointers()
}
}
-template<>
-inline bool ComputeFloatOffsetAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
-{
- LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject);
- if (logicalRight > m_offset) {
- m_offset = logicalRight;
- return true;
- }
- return false;
-}
-
FloatingObjects::FloatingObjects(const RenderBlockFlow* renderer, bool horizontalWritingMode)
: m_placedFloatsTree(UninitializedTree)
, m_leftObjectsCount(0)
@@ -170,7 +186,6 @@ FloatingObjects::FloatingObjects(const RenderBlockFlow* renderer, bool horizonta
void FloatingObjects::clear()
{
- deleteAllValues(m_set);
m_set.clear();
m_placedFloatsTree.clear();
m_leftObjectsCount = 0;
@@ -198,7 +213,7 @@ LayoutUnit FloatingObjects::lowestFloatLogicalBottom(FloatingObject::Type floatT
LayoutUnit lowestFloatBottomLeft = 0;
LayoutUnit lowestFloatBottomRight = 0;
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (floatingObject->isPlaced()) {
FloatingObject::Type curType = floatingObject->type();
LayoutUnit curFloatLogicalBottom = m_renderer->logicalBottomForFloat(floatingObject);
@@ -213,7 +228,7 @@ LayoutUnit FloatingObjects::lowestFloatLogicalBottom(FloatingObject::Type floatT
setCachedLowestFloatLogicalBottom(isInHorizontalWritingMode, FloatingObject::FloatRight, lowestFloatBottomRight);
} else {
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (floatingObject->isPlaced() && floatingObject->type() == floatType)
lowestFloatBottom = max(lowestFloatBottom, m_renderer->logicalBottomForFloat(floatingObject));
}
@@ -257,13 +272,11 @@ void FloatingObjects::markLowestFloatLogicalBottomCacheAsDirty()
void FloatingObjects::moveAllToFloatInfoMap(RendererToFloatInfoMap& map)
{
- FloatingObjectSetIterator end = m_set.end();
- for (FloatingObjectSetIterator it = m_set.begin(); it != end; ++it)
- map.add((*it)->renderer(), *it);
-
- // clear set before clearing this because we don't want to delete all of
- // the objects we have just transferred.
- m_set.clear();
+ while (!m_set.isEmpty()) {
+ OwnPtr<FloatingObject> floatingObject = m_set.takeFirst();
+ RenderBox* renderer = floatingObject->renderer();
+ map.add(renderer, floatingObject.release());
+ }
clear();
}
@@ -324,23 +337,22 @@ FloatingObject* FloatingObjects::add(PassOwnPtr<FloatingObject> floatingObject)
{
FloatingObject* newObject = floatingObject.leakPtr();
increaseObjectsCount(newObject->type());
- m_set.add(newObject);
+ m_set.add(adoptPtr(newObject));
if (newObject->isPlaced())
addPlacedObject(newObject);
markLowestFloatLogicalBottomCacheAsDirty();
return newObject;
}
-void FloatingObjects::remove(FloatingObject* floatingObject)
+void FloatingObjects::remove(FloatingObject* toBeRemoved)
{
- decreaseObjectsCount(floatingObject->type());
- m_set.remove(floatingObject);
+ decreaseObjectsCount(toBeRemoved->type());
+ OwnPtr<FloatingObject> floatingObject = m_set.take(toBeRemoved);
ASSERT(floatingObject->isPlaced() || !floatingObject->isInPlacedTree());
if (floatingObject->isPlaced())
- removePlacedObject(floatingObject);
+ removePlacedObject(floatingObject.get());
markLowestFloatLogicalBottomCacheAsDirty();
ASSERT(!floatingObject->originatingLine());
- delete floatingObject;
}
void FloatingObjects::computePlacedFloatsTree()
@@ -352,46 +364,16 @@ void FloatingObjects::computePlacedFloatsTree()
FloatingObjectSetIterator it = m_set.begin();
FloatingObjectSetIterator end = m_set.end();
for (; it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (floatingObject->isPlaced())
m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
}
}
-static inline ShapeOutsideInfo* shapeInfoForFloat(const FloatingObject* floatingObject, const RenderBlockFlow* containingBlock, LayoutUnit lineTop, LayoutUnit lineBottom)
-{
- if (floatingObject) {
- if (ShapeOutsideInfo* shapeOutside = floatingObject->renderer()->shapeOutsideInfo()) {
- shapeOutside->updateDeltasForContainingBlockLine(containingBlock, floatingObject, lineTop, lineBottom - lineTop);
- return shapeOutside;
- }
- }
-
- return 0;
-}
-
-template<>
-inline LayoutUnit ComputeFloatOffsetAdapter<FloatingObject::FloatLeft>::shapeOffset() const
-{
- if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(m_outermostFloat, m_renderer, m_lineTop, m_lineBottom))
- return m_offset + shapeOutside->rightMarginBoxDelta();
-
- return m_offset;
-}
-
-template<>
-inline LayoutUnit ComputeFloatOffsetAdapter<FloatingObject::FloatRight>::shapeOffset() const
-{
- if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(m_outermostFloat, m_renderer, m_lineTop, m_lineBottom))
- return m_offset + shapeOutside->leftMarginBoxDelta();
-
- return m_offset;
-}
-
LayoutUnit FloatingObjects::logicalLeftOffsetForPositioningFloat(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit *heightRemaining)
{
int logicalTopAsInt = roundToInt(logicalTop);
- ComputeFloatOffsetAdapter<FloatingObject::FloatLeft> adapter(m_renderer, logicalTopAsInt, logicalTopAsInt, fixedOffset);
+ ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft> adapter(m_renderer, logicalTopAsInt, logicalTopAsInt, fixedOffset);
placedFloatsTree().allOverlapsWithAdapter(adapter);
if (heightRemaining)
@@ -403,7 +385,7 @@ LayoutUnit FloatingObjects::logicalLeftOffsetForPositioningFloat(LayoutUnit fixe
LayoutUnit FloatingObjects::logicalRightOffsetForPositioningFloat(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit *heightRemaining)
{
int logicalTopAsInt = roundToInt(logicalTop);
- ComputeFloatOffsetAdapter<FloatingObject::FloatRight> adapter(m_renderer, logicalTopAsInt, logicalTopAsInt, fixedOffset);
+ ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatRight> adapter(m_renderer, logicalTopAsInt, logicalTopAsInt, fixedOffset);
placedFloatsTree().allOverlapsWithAdapter(adapter);
if (heightRemaining)
@@ -414,18 +396,18 @@ LayoutUnit FloatingObjects::logicalRightOffsetForPositioningFloat(LayoutUnit fix
LayoutUnit FloatingObjects::logicalLeftOffset(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit logicalHeight)
{
- ComputeFloatOffsetAdapter<FloatingObject::FloatLeft> adapter(m_renderer, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), fixedOffset);
+ ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft> adapter(m_renderer, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), fixedOffset);
placedFloatsTree().allOverlapsWithAdapter(adapter);
- return adapter.shapeOffset();
+ return adapter.offset();
}
LayoutUnit FloatingObjects::logicalRightOffset(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit logicalHeight)
{
- ComputeFloatOffsetAdapter<FloatingObject::FloatRight> adapter(m_renderer, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), fixedOffset);
+ ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatRight> adapter(m_renderer, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), fixedOffset);
placedFloatsTree().allOverlapsWithAdapter(adapter);
- return min(fixedOffset, adapter.shapeOffset());
+ return min(fixedOffset, adapter.offset());
}
FloatingObjects::FloatBottomCachedValue::FloatBottomCachedValue()
@@ -455,7 +437,18 @@ inline static bool rangesIntersect(int floatTop, int floatBottom, int objectTop,
}
template<>
-inline bool ComputeFloatOffsetAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
+inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
+{
+ LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject);
+ if (logicalRight > m_offset) {
+ m_offset = logicalRight;
+ return true;
+ }
+ return false;
+}
+
+template<>
+inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
{
LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(floatingObject);
if (logicalLeft < m_offset) {
@@ -466,6 +459,12 @@ inline bool ComputeFloatOffsetAdapter<FloatingObject::FloatRight>::updateOffsetI
}
template <FloatingObject::Type FloatTypeValue>
+LayoutUnit ComputeFloatOffsetForFloatLayoutAdapter<FloatTypeValue>::heightRemaining() const
+{
+ return this->m_outermostFloat ? this->m_renderer->logicalBottomForFloat(this->m_outermostFloat) - this->m_lineTop : LayoutUnit(1);
+}
+
+template <FloatingObject::Type FloatTypeValue>
inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval)
{
const FloatingObject* floatingObject = interval.data();
@@ -482,10 +481,52 @@ inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const Int
m_outermostFloat = floatingObject;
}
-template <FloatingObject::Type FloatTypeValue>
-LayoutUnit ComputeFloatOffsetAdapter<FloatTypeValue>::heightRemaining() const
+static inline ShapeOutsideInfo* shapeInfoForFloat(const FloatingObject& floatingObject, const RenderBlockFlow& containingBlock, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+ if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
+ shapeOutside->updateDeltasForContainingBlockLine(containingBlock, floatingObject, lineTop, lineBottom - lineTop);
+ return shapeOutside;
+ }
+
+ return 0;
+}
+
+template<>
+inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
+{
+ ASSERT(floatingObject);
+ LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject);
+ if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) {
+ if (!shapeOutside->lineOverlapsShape())
+ return false;
+
+ logicalRight += shapeOutside->rightMarginBoxDelta();
+ }
+ if (logicalRight > m_offset) {
+ m_offset = logicalRight;
+ return true;
+ }
+
+ return false;
+}
+
+template<>
+inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
{
- return m_outermostFloat ? m_renderer->logicalBottomForFloat(m_outermostFloat) - m_lineTop : LayoutUnit(1);
+ ASSERT(floatingObject);
+ LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(floatingObject);
+ if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) {
+ if (!shapeOutside->lineOverlapsShape())
+ return false;
+
+ logicalLeft += shapeOutside->leftMarginBoxDelta();
+ }
+ if (logicalLeft < m_offset) {
+ m_offset = logicalLeft;
+ return true;
+ }
+
+ return false;
}
#ifndef NDEBUG
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.h b/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.h
index ca3beb1a345..f7062249639 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/FloatingObjects.h
@@ -113,19 +113,25 @@ private:
struct FloatingObjectHashFunctions {
static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->renderer()); }
- static bool equal(FloatingObject* a, FloatingObject* b) { return a->renderer() == b->renderer(); }
+ static unsigned hash(const OwnPtr<FloatingObject>& key) { return hash(key.get()); }
+ static unsigned hash(const PassOwnPtr<FloatingObject>& key) { return hash(key.get()); }
+ static bool equal(OwnPtr<FloatingObject>& a, FloatingObject* b) { return a->renderer() == b->renderer(); }
+ static bool equal(OwnPtr<FloatingObject>& a, const OwnPtr<FloatingObject>& b) { return equal(a, b.get()); }
+ static bool equal(OwnPtr<FloatingObject>& a, const PassOwnPtr<FloatingObject>& b) { return equal(a, b.get()); }
+
static const bool safeToCompareToEmptyOrDeleted = true;
};
struct FloatingObjectHashTranslator {
static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); }
static bool equal(FloatingObject* a, RenderBox* b) { return a->renderer() == b; }
+ static bool equal(const OwnPtr<WebCore::FloatingObject>& a, RenderBox* b) { return a->renderer() == b; }
};
-typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet;
+typedef ListHashSet<OwnPtr<FloatingObject>, 4, FloatingObjectHashFunctions> FloatingObjectSet;
typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator;
typedef PODInterval<int, FloatingObject*> FloatingObjectInterval;
typedef PODIntervalTree<int, FloatingObject*> FloatingObjectTree;
typedef PODFreeListArena<PODRedBlackTree<FloatingObjectInterval>::Node> IntervalArena;
-typedef HashMap<RenderBox*, FloatingObject*> RendererToFloatInfoMap;
+typedef HashMap<RenderBox*, OwnPtr<FloatingObject> > RendererToFloatInfoMap;
class FloatingObjects {
WTF_MAKE_NONCOPYABLE(FloatingObjects); WTF_MAKE_FAST_ALLOCATED;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.cpp b/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.cpp
index 521085ee453..59e5cf1cbf6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.cpp
@@ -31,218 +31,16 @@
#include "core/rendering/FlowThreadController.h"
-#include "core/dom/NamedFlowCollection.h"
-#include "core/rendering/RenderFlowThread.h"
-#include "core/rendering/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)
- , m_flowThreadsWithAutoLogicalHeightRegions(0)
-{
-}
-
-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;
- }
- }
-
- NamedFlowCollection* namedFlows = m_view->document().namedFlows();
-
- // Sanity check for the absence of a named flow in the "CREATED" state with the same name.
- ASSERT(!namedFlows->flowByName(name));
-
- RenderNamedFlowThread* flowRenderer = RenderNamedFlowThread::createAnonymous(&m_view->document(), namedFlows->ensureFlowWithName(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::styleDidChange()
+PassOwnPtr<FlowThreadController> FlowThreadController::create()
{
- RenderStyle* viewStyle = m_view->style();
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(viewStyle));
- }
-}
-
-void FlowThreadController::layoutRenderNamedFlowThreads()
-{
- updateFlowThreadsChainIfNecessary();
-
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- flowRenderer->layoutIfNeeded();
- }
+ return adoptPtr(new FlowThreadController);
}
-void FlowThreadController::registerNamedFlowContentNode(Node* contentNode, RenderNamedFlowThread* namedFlow)
+FlowThreadController::FlowThreadController()
+ : m_currentRenderFlowThread(0)
{
- 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<const Node*, RenderNamedFlowThread*>::iterator it = m_mapNamedFlowContentNodes.find(contentNode);
- ASSERT_WITH_SECURITY_IMPLICATION(it != m_mapNamedFlowContentNodes.end());
- ASSERT(it->value);
- ASSERT(it->value->hasContentNode(contentNode));
- it->value->unregisterNamedFlowContentNode(contentNode);
- m_mapNamedFlowContentNodes.remove(contentNode);
-}
-
-void FlowThreadController::updateFlowThreadsChainIfNecessary()
-{
- ASSERT(m_renderNamedFlowThreadList);
- ASSERT(isAutoLogicalHeightRegionsCountConsistent());
-
- // Remove the left-over flow threads.
- RenderNamedFlowThreadList toRemoveList;
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- if (flowRenderer->isMarkedForDestruction())
- toRemoveList.add(flowRenderer);
- }
-
- if (toRemoveList.size() > 0)
- setIsRenderNamedFlowThreadOrderDirty(true);
-
- for (RenderNamedFlowThreadList::iterator iter = toRemoveList.begin(); iter != toRemoveList.end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- m_renderNamedFlowThreadList->remove(flowRenderer);
- flowRenderer->destroy();
- }
-
- 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);
- }
-}
-
-bool FlowThreadController::updateFlowThreadsNeedingLayout()
-{
- bool needsTwoPassLayout = false;
-
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- ASSERT(!flowRenderer->needsTwoPhasesLayout());
- flowRenderer->setInConstrainedLayoutPhase(false);
- if (flowRenderer->needsLayout() && flowRenderer->hasAutoLogicalHeightRegions())
- needsTwoPassLayout = true;
- }
-
- if (needsTwoPassLayout)
- resetFlowThreadsWithAutoHeightRegions();
-
- return needsTwoPassLayout;
-}
-
-bool FlowThreadController::updateFlowThreadsNeedingTwoStepLayout()
-{
- bool needsTwoPassLayout = false;
-
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- if (flowRenderer->needsTwoPhasesLayout()) {
- needsTwoPassLayout = true;
- break;
- }
- }
-
- if (needsTwoPassLayout)
- resetFlowThreadsWithAutoHeightRegions();
-
- return needsTwoPassLayout;
-}
-
-void FlowThreadController::resetFlowThreadsWithAutoHeightRegions()
-{
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- if (flowRenderer->hasAutoLogicalHeightRegions()) {
- flowRenderer->markAutoLogicalHeightRegionsForLayout();
- flowRenderer->invalidateRegions();
- }
- }
-}
-
-void FlowThreadController::updateFlowThreadsIntoConstrainedPhase()
-{
- // Walk the flow chain in reverse order to update the auto-height regions and compute correct sizes for the containing regions. Only after this we can
- // set the flow in the constrained layout phase.
- for (RenderNamedFlowThreadList::reverse_iterator iter = m_renderNamedFlowThreadList->rbegin(); iter != m_renderNamedFlowThreadList->rend(); ++iter) {
- RenderNamedFlowThread* flowRenderer = *iter;
- ASSERT(!flowRenderer->hasRegions() || flowRenderer->hasValidRegionInfo());
- flowRenderer->layoutIfNeeded();
- if (flowRenderer->hasAutoLogicalHeightRegions()) {
- ASSERT(flowRenderer->needsTwoPhasesLayout());
- flowRenderer->markAutoLogicalHeightRegionsForLayout();
- }
- flowRenderer->setInConstrainedLayoutPhase(true);
- flowRenderer->clearNeedsTwoPhasesLayout();
- }
-}
-
-bool FlowThreadController::isContentNodeRegisteredWithAnyNamedFlow(const Node* contentNode) const
-{
- return m_mapNamedFlowContentNodes.contains(contentNode);
-}
-
-#ifndef NDEBUG
-bool FlowThreadController::isAutoLogicalHeightRegionsCountConsistent() const
-{
- if (!hasRenderNamedFlowThreads())
- return !hasFlowThreadsWithAutoLogicalHeightRegions();
-
- for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
- if (!(*iter)->isAutoLogicalHeightRegionsCountConsistent())
- return false;
- }
-
- return true;
}
-#endif
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.h b/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.h
index 7f56615d7de..1b1372b29b1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/FlowThreadController.h
@@ -30,69 +30,26 @@
#ifndef FlowThreadController_h
#define FlowThreadController_h
-#include "core/rendering/RenderView.h"
-#include "wtf/ListHashSet.h"
-#include "wtf/OwnPtr.h"
+#include "wtf/FastAllocBase.h"
+#include "wtf/PassOwnPtr.h"
namespace WebCore {
class RenderFlowThread;
-class RenderNamedFlowThread;
-
-typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
class FlowThreadController {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<FlowThreadController> create(RenderView*);
- ~FlowThreadController();
+ static PassOwnPtr<FlowThreadController> create();
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();
- }
-
- RenderNamedFlowThread* ensureRenderFlowThreadWithName(const AtomicString&);
- const RenderNamedFlowThreadList* renderNamedFlowThreadList() const { return m_renderNamedFlowThreadList.get(); }
- bool hasRenderNamedFlowThreads() const { return m_renderNamedFlowThreadList && !m_renderNamedFlowThreadList->isEmpty(); }
- void layoutRenderNamedFlowThreads();
- void styleDidChange();
-
- void registerNamedFlowContentNode(Node*, RenderNamedFlowThread*);
- void unregisterNamedFlowContentNode(Node*);
- bool isContentNodeRegisteredWithAnyNamedFlow(const Node*) const;
-
- bool hasFlowThreadsWithAutoLogicalHeightRegions() const { return m_flowThreadsWithAutoLogicalHeightRegions; }
- void incrementFlowThreadsWithAutoLogicalHeightRegions() { ++m_flowThreadsWithAutoLogicalHeightRegions; }
- void decrementFlowThreadsWithAutoLogicalHeightRegions() { ASSERT(m_flowThreadsWithAutoLogicalHeightRegions > 0); --m_flowThreadsWithAutoLogicalHeightRegions; }
-
- bool updateFlowThreadsNeedingLayout();
- bool updateFlowThreadsNeedingTwoStepLayout();
- void updateFlowThreadsIntoConstrainedPhase();
-
-#ifndef NDEBUG
- bool isAutoLogicalHeightRegionsCountConsistent() const;
-#endif
-
protected:
- FlowThreadController(RenderView*);
- void updateFlowThreadsChainIfNecessary();
- void resetFlowThreadsWithAutoHeightRegions();
+ FlowThreadController();
private:
- RenderView* m_view;
RenderFlowThread* m_currentRenderFlowThread;
- bool m_isRenderNamedFlowThreadOrderDirty;
- unsigned m_flowThreadsWithAutoLogicalHeightRegions;
- OwnPtr<RenderNamedFlowThreadList> m_renderNamedFlowThreadList;
- // maps a content node to its render flow thread.
- HashMap<const Node*, RenderNamedFlowThread*> m_mapNamedFlowContentNodes;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.cpp b/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.cpp
index f532480df20..20d4ba557e9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.cpp
@@ -22,17 +22,10 @@
#include "config.h"
#include "core/rendering/HitTestLocation.h"
-#include "HTMLNames.h"
-#include "SVGNames.h"
-#include "XLinkNames.h"
-
namespace WebCore {
-using namespace HTMLNames;
-
HitTestLocation::HitTestLocation()
- : m_region(0)
- , m_isRectBased(false)
+ : m_isRectBased(false)
, m_isRectilinear(true)
{
}
@@ -42,7 +35,6 @@ HitTestLocation::HitTestLocation(const LayoutPoint& point)
, m_boundingBox(rectForPoint(point, 0, 0, 0, 0))
, m_transformedPoint(point)
, m_transformedRect(m_boundingBox)
- , m_region(0)
, m_isRectBased(false)
, m_isRectilinear(true)
{
@@ -53,7 +45,6 @@ HitTestLocation::HitTestLocation(const FloatPoint& point)
, m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0))
, m_transformedPoint(point)
, m_transformedRect(m_boundingBox)
- , m_region(0)
, m_isRectBased(false)
, m_isRectilinear(true)
{
@@ -62,7 +53,6 @@ HitTestLocation::HitTestLocation(const FloatPoint& point)
HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
: m_transformedPoint(point)
, m_transformedRect(quad)
- , m_region(0)
, m_isRectBased(true)
{
m_point = flooredLayoutPoint(point);
@@ -74,19 +64,17 @@ HitTestLocation::HitTestLocation(const LayoutPoint& centerPoint, unsigned topPad
: m_point(centerPoint)
, m_boundingBox(rectForPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding))
, m_transformedPoint(centerPoint)
- , m_region(0)
, m_isRectBased(topPadding || rightPadding || bottomPadding || leftPadding)
, m_isRectilinear(true)
{
m_transformedRect = FloatQuad(m_boundingBox);
}
-HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset, RenderRegion* region)
+HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset)
: m_point(other.m_point)
, m_boundingBox(other.m_boundingBox)
, m_transformedPoint(other.m_transformedPoint)
, m_transformedRect(other.m_transformedRect)
- , m_region(region ? region : other.m_region)
, m_isRectBased(other.m_isRectBased)
, m_isRectilinear(other.m_isRectilinear)
{
@@ -98,7 +86,6 @@ HitTestLocation::HitTestLocation(const HitTestLocation& other)
, m_boundingBox(other.m_boundingBox)
, m_transformedPoint(other.m_transformedPoint)
, m_transformedRect(other.m_transformedRect)
- , m_region(other.m_region)
, m_isRectBased(other.m_isRectBased)
, m_isRectilinear(other.m_isRectilinear)
{
@@ -114,7 +101,6 @@ HitTestLocation& HitTestLocation::operator=(const HitTestLocation& other)
m_boundingBox = other.m_boundingBox;
m_transformedPoint = other.m_transformedPoint;
m_transformedRect = other.m_transformedRect;
- m_region = other.m_region;
m_isRectBased = other.m_isRectBased;
m_isRectilinear = other.m_isRectilinear;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.h b/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.h
index 7edcd8e03bc..ff18d79c646 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/HitTestLocation.h
@@ -33,14 +33,6 @@
namespace WebCore {
-class Element;
-class Frame;
-class Image;
-class KURL;
-class Node;
-class RenderRegion;
-class Scrollbar;
-
class HitTestLocation {
public:
@@ -50,8 +42,7 @@ public:
HitTestLocation(const FloatPoint&, const FloatQuad&);
// Pass non-zero padding values to perform a rect-based hit test.
HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
- // Make a copy the HitTestLocation in a new region by applying given offset to internal point and area.
- HitTestLocation(const HitTestLocation&, const LayoutSize& offset, RenderRegion* = 0);
+ HitTestLocation(const HitTestLocation&, const LayoutSize& offset);
HitTestLocation(const HitTestLocation&);
~HitTestLocation();
HitTestLocation& operator=(const HitTestLocation&);
@@ -59,8 +50,6 @@ public:
const LayoutPoint& point() const { return m_point; }
IntPoint roundedPoint() const { return roundedIntPoint(m_point); }
- RenderRegion* region() const { return m_region; }
-
// Rect-based hit test related methods.
bool isRectBasedTest() const { return m_isRectBased; }
bool isRectilinear() const { return m_isRectilinear; }
@@ -91,8 +80,6 @@ private:
FloatPoint m_transformedPoint;
FloatQuad m_transformedRect;
- RenderRegion* m_region; // The region we're inside.
-
bool m_isRectBased;
bool m_isRectilinear;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/HitTestRequest.h b/chromium/third_party/WebKit/Source/core/rendering/HitTestRequest.h
index 97dfa5165a7..c8a63ef9c49 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/HitTestRequest.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/HitTestRequest.h
@@ -40,7 +40,7 @@ public:
AllowFrameScrollbars = 1 << 9,
AllowChildFrameContent = 1 << 10,
ChildFrameHitTest = 1 << 11,
- IgnorePointerEventsNone = 1 << 12
+ IgnorePointerEventsNone = 1 << 12,
};
typedef unsigned HitTestRequestType;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.cpp b/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.cpp
index ad4e162801f..bce50193911 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.cpp
@@ -22,26 +22,23 @@
#include "config.h"
#include "core/rendering/HitTestResult.h"
-#include "HTMLNames.h"
-#include "SVGNames.h"
-#include "XLinkNames.h"
+#include "core/HTMLNames.h"
+#include "core/XLinkNames.h"
#include "core/dom/DocumentMarkerController.h"
#include "core/dom/NodeRenderingTraversal.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/FrameSelection.h"
#include "core/fetch/ImageResource.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAnchorElement.h"
-#include "core/html/HTMLAreaElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMediaElement.h"
-#include "core/html/HTMLTextAreaElement.h"
-#include "core/html/HTMLVideoElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
-#include "core/frame/Frame.h"
#include "core/page/FrameTree.h"
#include "core/rendering/RenderImage.h"
#include "core/rendering/RenderTextFragment.h"
+#include "core/svg/SVGElement.h"
#include "platform/scroll/Scrollbar.h"
namespace WebCore {
@@ -91,7 +88,7 @@ HitTestResult::HitTestResult(const HitTestResult& other)
, m_isFirstLetter(other.m_isFirstLetter)
{
// Only copy the NodeSet in case of rect hit test.
- m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
+ m_rectBasedTestResult = adoptPtrWillBeNoop(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
}
HitTestResult::~HitTestResult()
@@ -112,7 +109,7 @@ HitTestResult& HitTestResult::operator=(const HitTestResult& other)
m_isOverWidget = other.isOverWidget();
// Only copy the NodeSet in case of rect hit test.
- m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
+ m_rectBasedTestResult = adoptPtrWillBeNoop(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
return *this;
}
@@ -182,7 +179,7 @@ void HitTestResult::setScrollbar(Scrollbar* s)
m_scrollbar = s;
}
-Frame* HitTestResult::innerNodeFrame() const
+LocalFrame* HitTestResult::innerNodeFrame() const
{
if (m_innerNonSharedNode)
return m_innerNonSharedNode->document().frame();
@@ -191,24 +188,12 @@ Frame* HitTestResult::innerNodeFrame() const
return 0;
}
-Frame* HitTestResult::targetFrame() const
-{
- if (!m_innerURLElement)
- return 0;
-
- Frame* frame = m_innerURLElement->document().frame();
- if (!frame)
- return 0;
-
- return frame->tree().find(m_innerURLElement->target());
-}
-
bool HitTestResult::isSelected() const
{
if (!m_innerNonSharedNode)
return false;
- if (Frame* frame = m_innerNonSharedNode->document().frame())
+ if (LocalFrame* frame = m_innerNonSharedNode->document().frame())
return frame->selection().contains(m_hitTestLocation.point());
return false;
}
@@ -221,7 +206,7 @@ String HitTestResult::spellingToolTip(TextDirection& dir) const
if (!m_innerNonSharedNode)
return String();
- DocumentMarker* marker = m_innerNonSharedNode->document().markers()->markerContainingPoint(m_hitTestLocation.point(), DocumentMarker::Grammar);
+ DocumentMarker* marker = m_innerNonSharedNode->document().markers().markerContainingPoint(m_hitTestLocation.point(), DocumentMarker::Grammar);
if (!marker)
return String();
@@ -253,14 +238,14 @@ const AtomicString& HitTestResult::altDisplayString() const
if (!m_innerNonSharedNode)
return nullAtom;
- if (m_innerNonSharedNode->hasTagName(imgTag)) {
- HTMLImageElement* image = toHTMLImageElement(m_innerNonSharedNode);
- return image->getAttribute(altAttr);
+ if (isHTMLImageElement(*m_innerNonSharedNode)) {
+ HTMLImageElement& image = toHTMLImageElement(*m_innerNonSharedNode);
+ return image.getAttribute(altAttr);
}
- if (m_innerNonSharedNode->hasTagName(inputTag)) {
- HTMLInputElement* input = toHTMLInputElement(m_innerNonSharedNode);
- return input->alt();
+ if (isHTMLInputElement(*m_innerNonSharedNode)) {
+ HTMLInputElement& input = toHTMLInputElement(*m_innerNonSharedNode);
+ return input.alt();
}
return nullAtom;
@@ -293,17 +278,19 @@ KURL HitTestResult::absoluteImageURL() const
if (!m_innerNonSharedNode)
return KURL();
- if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isImage()))
+ RenderObject* renderer = m_innerNonSharedNode->renderer();
+ if (!(renderer && (renderer->isImage() || renderer->isCanvas())))
return KURL();
AtomicString urlString;
- if (m_innerNonSharedNode->hasTagName(embedTag)
- || m_innerNonSharedNode->hasTagName(imgTag)
- || m_innerNonSharedNode->hasTagName(inputTag)
- || m_innerNonSharedNode->hasTagName(objectTag)
- || m_innerNonSharedNode->hasTagName(SVGNames::imageTag)
+ if (isHTMLCanvasElement(*m_innerNonSharedNode)
+ || isHTMLEmbedElement(*m_innerNonSharedNode)
+ || isHTMLImageElement(*m_innerNonSharedNode)
+ || isHTMLInputElement(*m_innerNonSharedNode)
+ || isHTMLObjectElement(*m_innerNonSharedNode)
+ || isSVGImageElement(*m_innerNonSharedNode)
) {
- urlString = toElement(m_innerNonSharedNode)->imageSourceURL();
+ urlString = toElement(*m_innerNonSharedNode).imageSourceURL();
} else
return KURL();
@@ -325,8 +312,8 @@ HTMLMediaElement* HitTestResult::mediaElement() const
if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isMedia()))
return 0;
- if (isHTMLVideoElement(m_innerNonSharedNode.get()) || m_innerNonSharedNode->hasTagName(HTMLNames::audioTag))
- return toHTMLMediaElement(m_innerNonSharedNode.get());
+ if (isHTMLMediaElement(*m_innerNonSharedNode))
+ return toHTMLMediaElement(m_innerNonSharedNode);
return 0;
}
@@ -336,9 +323,9 @@ KURL HitTestResult::absoluteLinkURL() const
return KURL();
AtomicString urlString;
- if (isHTMLAnchorElement(m_innerURLElement.get()) || isHTMLAreaElement(m_innerURLElement.get()) || m_innerURLElement->hasTagName(linkTag))
+ if (isHTMLAnchorElement(*m_innerURLElement) || isHTMLAreaElement(*m_innerURLElement) || isHTMLLinkElement(*m_innerURLElement))
urlString = m_innerURLElement->getAttribute(hrefAttr);
- else if (m_innerURLElement->hasTagName(SVGNames::aTag))
+ else if (isSVGAElement(*m_innerURLElement))
urlString = m_innerURLElement->getAttribute(XLinkNames::hrefAttr);
else
return KURL();
@@ -351,10 +338,10 @@ bool HitTestResult::isLiveLink() const
if (!m_innerURLElement)
return false;
- if (isHTMLAnchorElement(m_innerURLElement.get()))
+ if (isHTMLAnchorElement(*m_innerURLElement))
return toHTMLAnchorElement(m_innerURLElement)->isLiveLink();
- if (m_innerURLElement->hasTagName(SVGNames::aTag))
+ if (isSVGAElement(*m_innerURLElement))
return m_innerURLElement->isLink();
return false;
@@ -362,12 +349,12 @@ bool HitTestResult::isLiveLink() const
bool HitTestResult::isMisspelled() const
{
- if (!targetNode())
+ if (!targetNode() || !targetNode()->renderer())
return false;
VisiblePosition pos(targetNode()->renderer()->positionForPoint(localPoint()));
if (pos.isNull())
return false;
- return m_innerNonSharedNode->document().markers()->markersInRange(
+ return m_innerNonSharedNode->document().markers().markersInRange(
makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers()).size() > 0;
}
@@ -376,14 +363,6 @@ bool HitTestResult::isOverLink() const
return m_innerURLElement && m_innerURLElement->isLink();
}
-String HitTestResult::titleDisplayString() const
-{
- if (!m_innerURLElement)
- return String();
-
- return m_innerURLElement->title();
-}
-
String HitTestResult::textContent() const
{
if (!m_innerURLElement)
@@ -400,11 +379,11 @@ bool HitTestResult::isContentEditable() const
if (!m_innerNonSharedNode)
return false;
- if (isHTMLTextAreaElement(m_innerNonSharedNode.get()))
+ if (isHTMLTextAreaElement(*m_innerNonSharedNode))
return true;
- if (m_innerNonSharedNode->hasTagName(inputTag))
- return toHTMLInputElement(m_innerNonSharedNode)->isTextField();
+ if (isHTMLInputElement(*m_innerNonSharedNode))
+ return toHTMLInputElement(*m_innerNonSharedNode).isTextField();
return m_innerNonSharedNode->rendererIsEditable();
}
@@ -477,14 +456,14 @@ void HitTestResult::append(const HitTestResult& other)
const HitTestResult::NodeSet& HitTestResult::rectBasedTestResult() const
{
if (!m_rectBasedTestResult)
- m_rectBasedTestResult = adoptPtr(new NodeSet);
+ m_rectBasedTestResult = adoptPtrWillBeNoop(new NodeSet);
return *m_rectBasedTestResult;
}
HitTestResult::NodeSet& HitTestResult::mutableRectBasedTestResult()
{
if (!m_rectBasedTestResult)
- m_rectBasedTestResult = adoptPtr(new NodeSet);
+ m_rectBasedTestResult = adoptPtrWillBeNoop(new NodeSet);
return *m_rectBasedTestResult;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.h b/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.h
index 490596e4035..4db557a1fc1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/HitTestResult.h
@@ -27,6 +27,7 @@
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/LayoutRect.h"
+#include "platform/heap/Handle.h"
#include "platform/text/TextDirection.h"
#include "wtf/Forward.h"
#include "wtf/ListHashSet.h"
@@ -36,18 +37,17 @@
namespace WebCore {
class Element;
-class Frame;
+class LocalFrame;
class HTMLMediaElement;
class Image;
class KURL;
class Node;
class RenderObject;
-class RenderRegion;
class Scrollbar;
class HitTestResult {
public:
- typedef ListHashSet<RefPtr<Node> > NodeSet;
+ typedef WillBeHeapListHashSet<RefPtrWillBeMember<Node> > NodeSet;
HitTestResult();
HitTestResult(const LayoutPoint&);
@@ -76,7 +76,7 @@ public:
// The hit-tested point in the coordinates of the innerNode frame, the frame containing innerNode.
const LayoutPoint& pointInInnerNodeFrame() const { return m_pointInInnerNodeFrame; }
IntPoint roundedPointInInnerNodeFrame() const { return roundedIntPoint(pointInInnerNodeFrame()); }
- Frame* innerNodeFrame() const;
+ LocalFrame* innerNodeFrame() const;
// The hit-tested point in the coordinates of the inner node.
const LayoutPoint& localPoint() const { return m_localPoint; }
@@ -96,12 +96,10 @@ public:
void setIsFirstLetter(bool b) { m_isFirstLetter = b; }
void setIsOverWidget(bool b) { m_isOverWidget = b; }
- Frame* targetFrame() const;
bool isSelected() const;
String spellingToolTip(TextDirection&) const;
String title(TextDirection&) const;
const AtomicString& altDisplayString() const;
- String titleDisplayString() const;
Image* image() const;
IntRect imageRect() const;
KURL absoluteImageURL() const;
@@ -132,18 +130,18 @@ private:
HitTestLocation m_hitTestLocation;
- RefPtr<Node> m_innerNode;
- RefPtr<Node> m_innerPossiblyPseudoNode;
- RefPtr<Node> m_innerNonSharedNode;
+ RefPtrWillBePersistent<Node> m_innerNode;
+ RefPtrWillBePersistent<Node> m_innerPossiblyPseudoNode;
+ RefPtrWillBePersistent<Node> m_innerNonSharedNode;
LayoutPoint m_pointInInnerNodeFrame; // The hit-tested point in innerNode frame coordinates.
LayoutPoint m_localPoint; // A point in the local coordinate space of m_innerNonSharedNode's renderer. Allows us to efficiently
// determine where inside the renderer we hit on subsequent operations.
- RefPtr<Element> m_innerURLElement;
+ RefPtrWillBePersistent<Element> m_innerURLElement;
RefPtr<Scrollbar> m_scrollbar;
bool m_isOverWidget; // Returns true if we are over a widget (and not in the border/padding area of a RenderWidget for example).
bool m_isFirstLetter;
- mutable OwnPtr<NodeSet> m_rectBasedTestResult;
+ mutable OwnPtrWillBePersistent<NodeSet> m_rectBasedTestResult;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.cpp b/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.cpp
index ef4c23b73c8..09751291106 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.cpp
@@ -31,8 +31,8 @@
#include "config.h"
#include "core/rendering/ImageQualityController.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "platform/graphics/GraphicsContext.h"
namespace WebCore {
@@ -60,6 +60,21 @@ void ImageQualityController::remove(RenderObject* renderer)
}
}
+InterpolationQuality ImageQualityController::chooseInterpolationQuality(GraphicsContext* context, RenderObject* object, Image* image, const void* layer, const LayoutSize& layoutSize)
+{
+ if (InterpolationDefault == InterpolationLow)
+ return InterpolationLow;
+
+ if (shouldPaintAtLowQuality(context, object, image, layer, layoutSize))
+ return InterpolationLow;
+
+ // For images that are potentially animated we paint them at medium quality.
+ if (image && image->maybeAnimated())
+ return InterpolationMedium;
+
+ return InterpolationDefault;
+}
+
ImageQualityController::~ImageQualityController()
{
// This will catch users of ImageQualityController that forget to call cleanUp.
@@ -109,14 +124,14 @@ void ImageQualityController::highQualityRepaintTimerFired(Timer<ImageQualityCont
m_animatedResizeIsActive = false;
for (ObjectLayerSizeMap::iterator it = m_objectLayerSizeMap.begin(); it != m_objectLayerSizeMap.end(); ++it) {
- if (Frame* frame = it->key->document().frame()) {
+ if (LocalFrame* frame = it->key->document().frame()) {
// If this renderer's containing FrameView is in live resize, punt the timer and hold back for now.
if (frame->view() && frame->view()->inLiveResize()) {
restartTimer();
return;
}
}
- it->key->repaint();
+ it->key->paintInvalidationForWholeRenderer();
}
m_liveResizeOptimizationIsActive = false;
@@ -124,7 +139,7 @@ void ImageQualityController::highQualityRepaintTimerFired(Timer<ImageQualityCont
void ImageQualityController::restartTimer()
{
- m_timer.startOneShot(cLowQualityTimeThreshold);
+ m_timer.startOneShot(cLowQualityTimeThreshold, FROM_HERE);
}
bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, RenderObject* object, Image* image, const void *layer, const LayoutSize& layoutSize)
@@ -159,7 +174,7 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R
LayoutSize scaledLayoutSize = currentTransform.mapSize(roundedIntSize(layoutSize));
// If the containing FrameView is being resized, paint at low quality until resizing is finished.
- if (Frame* frame = object->document().frame()) {
+ if (LocalFrame* frame = object->document().frame()) {
bool frameViewIsCurrentlyInLiveResize = frame->view() && frame->view()->inLiveResize();
if (frameViewIsCurrentlyInLiveResize) {
set(object, innerMap, layer, scaledLayoutSize);
@@ -174,6 +189,9 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R
}
}
+ // See crbug.com/382491. This test is insufficient to ensure that there is no scale
+ // applied in the compositor, but it is probably adequate here. In the worst case we
+ // draw at high quality when we need not.
if (!contextIsScaled && scaledLayoutSize == scaledImageSize) {
// There is no scale in effect. If we had a scale in effect before, we can just remove this object from the list.
removeLayer(object, innerMap, layer);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.h b/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.h
index a9e8b108d88..71544283b8f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/ImageQualityController.h
@@ -53,11 +53,12 @@ public:
static void remove(RenderObject*);
- bool shouldPaintAtLowQuality(GraphicsContext*, RenderObject*, Image*, const void* layer, const LayoutSize&);
+ InterpolationQuality chooseInterpolationQuality(GraphicsContext*, RenderObject*, Image*, const void* layer, const LayoutSize&);
private:
ImageQualityController();
+ bool shouldPaintAtLowQuality(GraphicsContext*, RenderObject*, Image*, const void* layer, const LayoutSize&);
void removeLayer(RenderObject*, LayerSizeMap* innerMap, const void* layer);
void set(RenderObject*, LayerSizeMap* innerMap, const void* layer, const LayoutSize&);
void objectDestroyed(RenderObject*);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/InlineBox.cpp
index 0e1e21ea874..9ec715c6e63 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineBox.cpp
@@ -58,10 +58,10 @@ InlineBox::~InlineBox()
#endif
-void InlineBox::remove()
+void InlineBox::remove(MarkLineBoxes markLineBoxes)
{
if (parent())
- parent()->removeChild(this);
+ parent()->removeChild(this, markLineBoxes);
}
void* InlineBox::operator new(size_t sz)
@@ -82,14 +82,12 @@ const char* InlineBox::boxName() const
void InlineBox::showTreeForThis() const
{
- if (m_renderer)
- m_renderer->showTreeForThis();
+ renderer().showTreeForThis();
}
void InlineBox::showLineTreeForThis() const
{
- if (m_renderer)
- m_renderer->containingBlock()->showLineTreeAndMark(this, "*");
+ renderer().containingBlock()->showLineTreeAndMark(this, "*");
}
void InlineBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj, int depth) const
@@ -99,7 +97,7 @@ void InlineBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* mar
printedCharacters += fprintf(stderr, "%s", markedLabel1);
if (this == markedBox2)
printedCharacters += fprintf(stderr, "%s", markedLabel2);
- if (renderer() == obj)
+ if (&renderer() == obj)
printedCharacters += fprintf(stderr, "*");
for (; printedCharacters < depth * 2; printedCharacters++)
fputc(' ', stderr);
@@ -112,7 +110,10 @@ void InlineBox::showBox(int printedCharacters) const
printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
fputc(' ', stderr);
- fprintf(stderr, "\t%s %p\n", renderer() ? renderer()->renderName() : "No Renderer", renderer());
+ fprintf(stderr, "\t%s %p {pos=%g,%g size=%g,%g} baseline=%i/%i\n",
+ renderer().renderName(), &renderer(), x(), y(), width(), height(),
+ baselinePosition(AlphabeticBaseline),
+ baselinePosition(IdeographicBaseline));
}
#endif
@@ -121,14 +122,14 @@ float InlineBox::logicalHeight() const
if (hasVirtualLogicalHeight())
return virtualLogicalHeight();
- if (renderer()->isText())
- return m_bitfields.isText() ? renderer()->style(isFirstLineStyle())->fontMetrics().height() : 0;
- if (renderer()->isBox() && parent())
- return isHorizontal() ? toRenderBox(m_renderer)->height() : toRenderBox(m_renderer)->width();
+ if (renderer().isText())
+ return m_bitfields.isText() ? renderer().style(isFirstLineStyle())->fontMetrics().height() : 0;
+ if (renderer().isBox() && parent())
+ return isHorizontal() ? toRenderBox(renderer()).height().toFloat() : toRenderBox(renderer()).width().toFloat();
ASSERT(isInlineFlowBox());
RenderBoxModelObject* flowObject = boxModelObject();
- const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
+ const FontMetrics& fontMetrics = renderer().style(isFirstLineStyle())->fontMetrics();
float result = fontMetrics.height();
if (parent())
result += flowObject->borderAndPaddingLogicalHeight();
@@ -147,12 +148,12 @@ LayoutUnit InlineBox::lineHeight() const
int InlineBox::caretMinOffset() const
{
- return m_renderer->caretMinOffset();
+ return renderer().caretMinOffset();
}
int InlineBox::caretMaxOffset() const
{
- return m_renderer->caretMaxOffset();
+ return renderer().caretMaxOffset();
}
void InlineBox::dirtyLineBoxes()
@@ -164,43 +165,43 @@ void InlineBox::dirtyLineBoxes()
void InlineBox::deleteLine()
{
- if (!m_bitfields.extracted() && m_renderer->isBox())
- toRenderBox(m_renderer)->setInlineBoxWrapper(0);
+ if (!m_bitfields.extracted() && renderer().isBox())
+ toRenderBox(renderer()).setInlineBoxWrapper(0);
destroy();
}
void InlineBox::extractLine()
{
m_bitfields.setExtracted(true);
- if (m_renderer->isBox())
- toRenderBox(m_renderer)->setInlineBoxWrapper(0);
+ if (renderer().isBox())
+ toRenderBox(renderer()).setInlineBoxWrapper(0);
}
void InlineBox::attachLine()
{
m_bitfields.setExtracted(false);
- if (m_renderer->isBox())
- toRenderBox(m_renderer)->setInlineBoxWrapper(this);
+ if (renderer().isBox())
+ toRenderBox(renderer()).setInlineBoxWrapper(this);
}
void InlineBox::adjustPosition(float dx, float dy)
{
m_topLeft.move(dx, dy);
- if (m_renderer->isReplaced())
- toRenderBox(m_renderer)->move(dx, dy);
+ if (renderer().isReplaced())
+ toRenderBox(renderer()).move(dx, dy);
}
void InlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
{
- if (!paintInfo.shouldPaintWithinRoot(renderer()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+ if (!paintInfo.shouldPaintWithinRoot(&renderer()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
return;
LayoutPoint childPoint = paintOffset;
- if (parent()->renderer()->style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
- childPoint = renderer()->containingBlock()->flipForWritingModeForChild(toRenderBox(renderer()), childPoint);
+ if (parent()->renderer().style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
+ childPoint = renderer().containingBlock()->flipForWritingModeForChild(&toRenderBox(renderer()), childPoint);
- RenderBlock::paintAsInlineBlock(renderer(), paintInfo, childPoint);
+ RenderBlock::paintAsInlineBlock(&renderer(), paintInfo, childPoint);
}
bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
@@ -209,26 +210,26 @@ bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
// own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
// specification.)
LayoutPoint childPoint = accumulatedOffset;
- if (parent()->renderer()->style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
- childPoint = renderer()->containingBlock()->flipForWritingModeForChild(toRenderBox(renderer()), childPoint);
+ if (parent()->renderer().style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
+ childPoint = renderer().containingBlock()->flipForWritingModeForChild(&toRenderBox(renderer()), childPoint);
- return renderer()->hitTest(request, result, locationInContainer, childPoint);
+ return renderer().hitTest(request, result, locationInContainer, childPoint);
}
-const RootInlineBox* InlineBox::root() const
+const RootInlineBox& InlineBox::root() const
{
if (m_parent)
return m_parent->root();
ASSERT(isRootInlineBox());
- return static_cast<const RootInlineBox*>(this);
+ return static_cast<const RootInlineBox&>(*this);
}
-RootInlineBox* InlineBox::root()
+RootInlineBox& InlineBox::root()
{
if (m_parent)
return m_parent->root();
ASSERT(isRootInlineBox());
- return static_cast<RootInlineBox*>(this);
+ return static_cast<RootInlineBox&>(*this);
}
bool InlineBox::nextOnLineExists() const
@@ -284,13 +285,13 @@ InlineBox* InlineBox::prevLeafChildIgnoringLineBreak() const
RenderObject::SelectionState InlineBox::selectionState()
{
- return renderer()->selectionState();
+ return renderer().selectionState();
}
bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const
{
// Non-replaced elements can always accommodate an ellipsis.
- if (!m_renderer || !m_renderer->isReplaced())
+ if (!renderer().isReplaced())
return true;
IntRect boxRect(left(), 0, m_logicalWidth, 10);
@@ -314,41 +315,41 @@ void InlineBox::clearKnownToHaveNoOverflow()
FloatPoint InlineBox::locationIncludingFlipping()
{
- if (!renderer()->style()->isFlippedBlocksWritingMode())
+ if (!renderer().style()->isFlippedBlocksWritingMode())
return FloatPoint(x(), y());
- RenderBlockFlow* block = root()->block();
- if (block->style()->isHorizontalWritingMode())
- return FloatPoint(x(), block->height() - height() - y());
- else
- return FloatPoint(block->width() - width() - x(), y());
+ RenderBlockFlow& block = root().block();
+ if (block.style()->isHorizontalWritingMode())
+ return FloatPoint(x(), block.height() - height() - y());
+
+ return FloatPoint(block.width() - width() - x(), y());
}
void InlineBox::flipForWritingMode(FloatRect& rect)
{
- if (!renderer()->style()->isFlippedBlocksWritingMode())
+ if (!renderer().style()->isFlippedBlocksWritingMode())
return;
- root()->block()->flipForWritingMode(rect);
+ root().block().flipForWritingMode(rect);
}
FloatPoint InlineBox::flipForWritingMode(const FloatPoint& point)
{
- if (!renderer()->style()->isFlippedBlocksWritingMode())
+ if (!renderer().style()->isFlippedBlocksWritingMode())
return point;
- return root()->block()->flipForWritingMode(point);
+ return root().block().flipForWritingMode(point);
}
void InlineBox::flipForWritingMode(LayoutRect& rect)
{
- if (!renderer()->style()->isFlippedBlocksWritingMode())
+ if (!renderer().style()->isFlippedBlocksWritingMode())
return;
- root()->block()->flipForWritingMode(rect);
+ root().block().flipForWritingMode(rect);
}
LayoutPoint InlineBox::flipForWritingMode(const LayoutPoint& point)
{
- if (!renderer()->style()->isFlippedBlocksWritingMode())
+ if (!renderer().style()->isFlippedBlocksWritingMode())
return point;
- return root()->block()->flipForWritingMode(point);
+ return root().block().flipForWritingMode(point);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineBox.h b/chromium/third_party/WebKit/Source/core/rendering/InlineBox.h
index 5803cd17e2b..f319c846d5d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineBox.h
@@ -30,11 +30,14 @@ class HitTestRequest;
class HitTestResult;
class RootInlineBox;
+enum MarkLineBoxes { MarkLineBoxesDirty, DontMarkLineBoxes };
+
// InlineBox represents a rectangle that occurs on a line. It corresponds to
// some RenderObject (i.e., it represents a portion of that RenderObject).
class InlineBox {
+ WTF_MAKE_NONCOPYABLE(InlineBox);
public:
- InlineBox(RenderObject* obj)
+ InlineBox(RenderObject& obj)
: m_next(0)
, m_prev(0)
, m_parent(0)
@@ -46,7 +49,7 @@ public:
{
}
- InlineBox(RenderObject* obj, FloatPoint topLeft, float logicalWidth, bool firstLine, bool constructed,
+ InlineBox(RenderObject& obj, FloatPoint topLeft, float logicalWidth, bool firstLine, bool constructed,
bool dirty, bool extracted, bool isHorizontal, InlineBox* next, InlineBox* prev, InlineFlowBox* parent)
: m_next(next)
, m_prev(prev)
@@ -146,7 +149,7 @@ public:
void setFirstLineStyleBit(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
bool isFirstLineStyle() const { return m_bitfields.firstLine(); }
- void remove();
+ void remove(MarkLineBoxes = MarkLineBoxesDirty);
InlineBox* nextOnLine() const { return m_next; }
InlineBox* prevOnLine() const { return m_prev; }
@@ -173,7 +176,7 @@ public:
InlineBox* nextLeafChildIgnoringLineBreak() const;
InlineBox* prevLeafChildIgnoringLineBreak() const;
- RenderObject* renderer() const { return m_renderer; }
+ RenderObject& renderer() const { return m_renderer; }
InlineFlowBox* parent() const
{
@@ -182,8 +185,8 @@ public:
}
void setParent(InlineFlowBox* par) { m_parent = par; }
- const RootInlineBox* root() const;
- RootInlineBox* root();
+ const RootInlineBox& root() const;
+ RootInlineBox& root();
// x() is the left side of the box in the containing block's coordinate system.
void setX(float x) { m_topLeft.setX(x); }
@@ -254,7 +257,7 @@ public:
virtual void clearTruncation() { }
bool isDirty() const { return m_bitfields.dirty(); }
- virtual void markDirty(bool dirty = true) { m_bitfields.setDirty(dirty); }
+ virtual void markDirty() { m_bitfields.setDirty(true); }
virtual void dirtyLineBoxes();
@@ -270,15 +273,15 @@ public:
int expansion() const { return m_bitfields.expansion(); }
- bool visibleToHitTestRequest(const HitTestRequest& request) const { return renderer()->visibleToHitTestRequest(request); }
+ bool visibleToHitTestRequest(const HitTestRequest& request) const { return renderer().visibleToHitTestRequest(request); }
- EVerticalAlign verticalAlign() const { return renderer()->style(m_bitfields.firstLine())->verticalAlign(); }
+ EVerticalAlign verticalAlign() const { return renderer().style(m_bitfields.firstLine())->verticalAlign(); }
// Use with caution! The type is not checked!
RenderBoxModelObject* boxModelObject() const
{
- if (!m_renderer->isText())
- return toRenderBoxModelObject(m_renderer);
+ if (!renderer().isText())
+ return toRenderBoxModelObject(&renderer());
return 0;
}
@@ -377,6 +380,7 @@ private:
InlineBox* m_prev; // The previous element on the same line as us.
InlineFlowBox* m_parent; // The box that contains us.
+ RenderObject& m_renderer;
protected:
// For RootInlineBox
@@ -398,8 +402,6 @@ protected:
// For InlineFlowBox and InlineTextBox
bool extracted() const { return m_bitfields.extracted(); }
- RenderObject* m_renderer;
-
FloatPoint m_topLeft;
float m_logicalWidth;
@@ -427,6 +429,14 @@ inline void InlineBox::setHasBadParent()
#define DEFINE_INLINE_BOX_TYPE_CASTS(typeName) \
DEFINE_TYPE_CASTS(typeName, InlineBox, box, box->is##typeName(), box.is##typeName())
+// Allow equality comparisons of InlineBox's by reference or pointer, interchangeably.
+inline bool operator==(const InlineBox& a, const InlineBox& b) { return &a == &b; }
+inline bool operator==(const InlineBox& a, const InlineBox* b) { return &a == b; }
+inline bool operator==(const InlineBox* a, const InlineBox& b) { return a == &b; }
+inline bool operator!=(const InlineBox& a, const InlineBox& b) { return !(a == b); }
+inline bool operator!=(const InlineBox& a, const InlineBox* b) { return !(a == b); }
+inline bool operator!=(const InlineBox* a, const InlineBox& b) { return !(a == b); }
+
} // namespace WebCore
#ifndef NDEBUG
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.cpp
index 68952fc6e18..b3384b2e33c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/InlineFlowBox.h"
-#include "CSSPropertyNames.h"
+#include "core/CSSPropertyNames.h"
#include "core/dom/Document.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/InlineTextBox.h"
@@ -109,7 +109,7 @@ void InlineFlowBox::addToLine(InlineBox* child)
child->setFirstLineStyleBit(isFirstLineStyle());
child->setIsHorizontal(isHorizontal());
if (child->isText()) {
- if (child->renderer()->parent() == renderer())
+ if (child->renderer().parent() == renderer())
m_hasTextChildren = true;
setHasTextDescendantsOnAncestors(this);
} else if (child->isInlineFlowBox()) {
@@ -117,14 +117,14 @@ void InlineFlowBox::addToLine(InlineBox* child)
setHasTextDescendantsOnAncestors(this);
}
- if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer()->isOutOfFlowPositioned()) {
- RenderStyle* parentStyle = renderer()->style(isFirstLineStyle());
- RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
+ if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer().isOutOfFlowPositioned()) {
+ RenderStyle* parentStyle = renderer().style(isFirstLineStyle());
+ RenderStyle* childStyle = child->renderer().style(isFirstLineStyle());
bool shouldClearDescendantsHaveSameLineHeightAndBaseline = false;
- if (child->renderer()->isReplaced())
+ if (child->renderer().isReplaced())
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
else if (child->isText()) {
- if (child->renderer()->isBR() || child->renderer()->parent() != renderer()) {
+ if (child->renderer().isBR() || child->renderer().parent() != renderer()) {
if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
|| parentStyle->lineHeight() != childStyle->lineHeight()
|| (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE)
@@ -133,7 +133,7 @@ void InlineFlowBox::addToLine(InlineBox* child)
if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
} else {
- if (child->renderer()->isBR()) {
+ if (child->renderer().isBR()) {
// FIXME: This is dumb. We only turn off because current layout test results expect the <br> to be 0-height on the baseline.
// Other than making a zillion tests have to regenerate results, there's no reason to ditch the optimization here.
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
@@ -154,19 +154,21 @@ void InlineFlowBox::addToLine(InlineBox* child)
clearDescendantsHaveSameLineHeightAndBaseline();
}
- if (!child->renderer()->isOutOfFlowPositioned()) {
+ if (!child->renderer().isOutOfFlowPositioned()) {
if (child->isText()) {
- RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
+ 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())
+ } 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(isFirstLineStyle())->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
- || (child->renderer()->isListMarker() && !toRenderListMarker(child->renderer())->isInside())
- || child->renderer()->style(isFirstLineStyle())->hasBorderImageOutsets()))
+ } else if (!child->renderer().isBR() && (child->renderer().style(isFirstLineStyle())->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
+ || (child->renderer().isListMarker() && !toRenderListMarker(child->renderer()).isInside())
+ || child->renderer().style(isFirstLineStyle())->hasBorderImageOutsets()
+ || child->renderer().style(isFirstLineStyle())->hasOutline())) {
child->clearKnownToHaveNoOverflow();
+ }
if (knownToHaveNoOverflow() && child->isInlineFlowBox() && !toInlineFlowBox(child)->knownToHaveNoOverflow())
clearKnownToHaveNoOverflow();
@@ -175,14 +177,14 @@ void InlineFlowBox::addToLine(InlineBox* child)
checkConsistency();
}
-void InlineFlowBox::removeChild(InlineBox* child)
+void InlineFlowBox::removeChild(InlineBox* child, MarkLineBoxes markDirty)
{
checkConsistency();
- if (!isDirty())
+ if (markDirty == MarkLineBoxesDirty && !isDirty())
dirtyLineBoxes();
- root()->childRemoved(child);
+ root().childRemoved(child);
if (child == m_firstChild)
m_firstChild = child->nextOnLine();
@@ -222,7 +224,7 @@ void InlineFlowBox::deleteLine()
void InlineFlowBox::removeLineBoxFromRenderObject()
{
- toRenderInline(renderer())->lineBoxes()->removeLineBox(this);
+ rendererLineBoxes()->removeLineBox(this);
}
void InlineFlowBox::extractLine()
@@ -235,7 +237,7 @@ void InlineFlowBox::extractLine()
void InlineFlowBox::extractLineBoxFromRenderObject()
{
- toRenderInline(renderer())->lineBoxes()->extractLineBox(this);
+ rendererLineBoxes()->extractLineBox(this);
}
void InlineFlowBox::attachLine()
@@ -248,7 +250,7 @@ void InlineFlowBox::attachLine()
void InlineFlowBox::attachLineBoxToRenderObject()
{
- toRenderInline(renderer())->lineBoxes()->attachLineBox(this);
+ rendererLineBoxes()->attachLineBox(this);
}
void InlineFlowBox::adjustPosition(float dx, float dy)
@@ -262,7 +264,7 @@ void InlineFlowBox::adjustPosition(float dx, float dy)
RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const
{
- return toRenderInline(renderer())->lineBoxes();
+ return toRenderInline(renderer()).lineBoxes();
}
static inline bool isLastChildForRenderer(RenderObject* ancestor, RenderObject* child)
@@ -276,7 +278,7 @@ static inline bool isLastChildForRenderer(RenderObject* ancestor, RenderObject*
RenderObject* curr = child;
RenderObject* parent = curr->parent();
while (parent && (!parent->isRenderBlock() || parent->isInline())) {
- if (parent->lastChild() != curr)
+ if (parent->slowLastChild() != curr)
return false;
if (parent == ancestor)
return true;
@@ -308,13 +310,13 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogically
// The root inline box never has borders/margins/padding.
if (parent()) {
- bool ltr = renderer()->style()->isLeftToRightDirection();
+ bool ltr = renderer().style()->isLeftToRightDirection();
// Check to see if all initial lines are unconstructed. If so, then
// we know the inline began on this line (unless we are a continuation).
RenderLineBoxList* lineBoxList = rendererLineBoxes();
- if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineElementContinuation()) {
- if (renderer()->style()->boxDecorationBreak() == DCLONE)
+ if (!lineBoxList->firstLineBox()->isConstructed() && !renderer().isInlineElementContinuation()) {
+ if (renderer().style()->boxDecorationBreak() == DCLONE)
includeLeftEdge = includeRightEdge = true;
else if (ltr && lineBoxList->firstLineBox() == this)
includeLeftEdge = true;
@@ -323,23 +325,23 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogically
}
if (!lineBoxList->lastLineBox()->isConstructed()) {
- RenderInline* inlineFlow = toRenderInline(renderer());
- bool isLastObjectOnLine = !isAnsectorAndWithinBlock(renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped);
+ RenderInline& inlineFlow = toRenderInline(renderer());
+ bool isLastObjectOnLine = !isAnsectorAndWithinBlock(&renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(&renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped);
// We include the border under these conditions:
// (1) The next line was not created, or it is constructed. We check the previous line for rtl.
// (2) The logicallyLastRun is not a descendant of this renderer.
// (3) The logicallyLastRun is a descendant of this renderer, but it is the last child of this renderer and it does not wrap to the next line.
// (4) The decoration break is set to clone therefore there will be borders on every sides.
- if (renderer()->style()->boxDecorationBreak() == DCLONE)
+ if (renderer().style()->boxDecorationBreak() == DCLONE)
includeLeftEdge = includeRightEdge = true;
else if (ltr) {
if (!nextLineBox()
- && ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
+ && ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation()))
includeRightEdge = true;
} else {
if ((!prevLineBox() || prevLineBox()->isConstructed())
- && ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
+ && ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation()))
includeLeftEdge = true;
}
}
@@ -377,13 +379,13 @@ float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsW
float InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
for (InlineBox* curr = firstChild; curr && curr != lastChild; curr = curr->nextOnLine()) {
- if (curr->renderer()->isText()) {
+ if (curr->renderer().isText()) {
InlineTextBox* text = toInlineTextBox(curr);
- RenderText* rt = toRenderText(text->renderer());
- if (rt->textLength()) {
- if (needsWordSpacing && isSpaceOrNewline(rt->characterAt(text->start())))
- logicalLeft += rt->style(isFirstLineStyle())->font().wordSpacing();
- needsWordSpacing = !isSpaceOrNewline(rt->characterAt(text->end()));
+ RenderText& rt = toRenderText(text->renderer());
+ if (rt.textLength()) {
+ if (needsWordSpacing && isSpaceOrNewline(rt.characterAt(text->start())))
+ logicalLeft += rt.style(isFirstLineStyle())->font().fontDescription().wordSpacing();
+ needsWordSpacing = !isSpaceOrNewline(rt.characterAt(text->end()));
}
text->setLogicalLeft(logicalLeft);
if (knownToHaveNoOverflow())
@@ -392,17 +394,18 @@ float InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, Inlin
if (knownToHaveNoOverflow())
maxLogicalRight = max(logicalLeft, maxLogicalRight);
} else {
- if (curr->renderer()->isOutOfFlowPositioned()) {
- if (curr->renderer()->parent()->style()->isLeftToRightDirection())
+ if (curr->renderer().isOutOfFlowPositioned()) {
+ if (curr->renderer().parent()->style()->isLeftToRightDirection()) {
curr->setLogicalLeft(logicalLeft);
- else
+ } else {
// Our offset that we cache needs to be from the edge of the right border box and
// not the left border box. We have to subtract |x| from the width of the block
// (which can be obtained from the root line box).
- curr->setLogicalLeft(root()->block()->logicalWidth() - logicalLeft);
+ curr->setLogicalLeft(root().block().logicalWidth() - logicalLeft);
+ }
continue; // The positioned object has no effect on the width.
}
- if (curr->renderer()->isRenderInline()) {
+ if (curr->renderer().isRenderInline()) {
InlineFlowBox* flow = toInlineFlowBox(curr);
logicalLeft += flow->marginLogicalLeft();
if (knownToHaveNoOverflow())
@@ -411,7 +414,7 @@ float InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, Inlin
if (knownToHaveNoOverflow())
maxLogicalRight = max(logicalLeft, maxLogicalRight);
logicalLeft += flow->marginLogicalRight();
- } else if (!curr->renderer()->isListMarker() || toRenderListMarker(curr->renderer())->isInside()) {
+ } else if (!curr->renderer().isListMarker() || toRenderListMarker(curr->renderer()).isInside()) {
// The box can have a different writing-mode than the overall line, so this is a bit complicated.
// Just get all the physical margin and overflow values by hand based off |isVertical|.
LayoutUnit logicalLeftMargin = isHorizontal() ? curr->boxModelObject()->marginLeft() : curr->boxModelObject()->marginTop();
@@ -438,19 +441,19 @@ bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFo
if (isHorizontal())
return false;
- if (renderer()->style(isFirstLineStyle())->fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright
- || renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
+ if (renderer().style(isFirstLineStyle())->fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright
+ || renderer().style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
return true;
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
if (curr->isInlineFlowBox()) {
if (toInlineFlowBox(curr)->requiresIdeographicBaseline(textBoxDataMap))
return true;
} else {
- if (curr->renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
+ if (curr->renderer().style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
return true;
const Vector<const SimpleFontData*>* usedFonts = 0;
@@ -476,7 +479,7 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, i
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
// The computed lineheight needs to be extended for the
// positioned elements
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
if (curr->verticalAlign() == TOP || curr->verticalAlign() == BOTTOM) {
int lineHeight = curr->lineHeight();
@@ -543,7 +546,7 @@ void InlineFlowBox::computeLogicalBoxHeights(RootInlineBox* rootBox, LayoutUnit&
return;
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
InlineFlowBox* inlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0;
@@ -554,7 +557,7 @@ void InlineFlowBox::computeLogicalBoxHeights(RootInlineBox* rootBox, LayoutUnit&
// The verticalPositionForBox function returns the distance between the child box's baseline
// and the root box's baseline. The value is negative if the child box's baseline is above the
// root box's baseline, and it is positive if the child box's baseline is below the root box's baseline.
- curr->setLogicalTop(rootBox->verticalPositionForBox(curr, verticalPositionCache));
+ curr->setLogicalTop(rootBox->verticalPositionForBox(curr, verticalPositionCache).toFloat());
int ascent = 0;
int descent = 0;
@@ -600,7 +603,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
{
bool isRootBox = isRootInlineBox();
if (isRootBox) {
- const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
+ 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)));
@@ -614,20 +617,20 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
}
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
if (descendantsHaveSameLineHeightAndBaseline()) {
- curr->adjustBlockDirectionPosition(adjustmentForChildrenWithSameLineHeightAndBaseline);
+ curr->adjustBlockDirectionPosition(adjustmentForChildrenWithSameLineHeightAndBaseline.toFloat());
continue;
}
InlineFlowBox* inlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0;
bool childAffectsTopBottomPos = true;
if (curr->verticalAlign() == TOP)
- curr->setLogicalTop(top);
+ curr->setLogicalTop(top.toFloat());
else if (curr->verticalAlign() == BOTTOM)
- curr->setLogicalTop(top + maxHeight - curr->lineHeight());
+ curr->setLogicalTop((top + maxHeight - curr->lineHeight()).toFloat());
else {
if (!strictMode && inlineFlowBox && !inlineFlowBox->hasTextChildren() && !curr->boxModelObject()->hasInlineDirectionBordersOrPadding()
&& !(inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants()))
@@ -642,48 +645,48 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
LayoutUnit boxHeightIncludingMargins = boxHeight;
if (curr->isText() || curr->isInlineFlowBox()) {
- const FontMetrics& fontMetrics = curr->renderer()->style(isFirstLineStyle())->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(isFirstLineStyle())->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() :
- boxObject->borderRight() + boxObject->paddingRight();
+ RenderBoxModelObject& boxObject = toRenderBoxModelObject(curr->renderer());
+ newLogicalTop -= boxObject.style(isFirstLineStyle())->isHorizontalWritingMode() ? boxObject.borderTop() + boxObject.paddingTop() :
+ boxObject.borderRight() + boxObject.paddingRight();
}
newLogicalTopIncludingMargins = newLogicalTop;
- } else if (!curr->renderer()->isBR()) {
- RenderBox* box = toRenderBox(curr->renderer());
+ } else if (!curr->renderer().isBR()) {
+ RenderBox& box = toRenderBox(curr->renderer());
newLogicalTopIncludingMargins = newLogicalTop;
- LayoutUnit overSideMargin = curr->isHorizontal() ? box->marginTop() : box->marginRight();
- LayoutUnit underSideMargin = curr->isHorizontal() ? box->marginBottom() : box->marginLeft();
+ LayoutUnit overSideMargin = curr->isHorizontal() ? box.marginTop() : box.marginRight();
+ LayoutUnit underSideMargin = curr->isHorizontal() ? box.marginBottom() : box.marginLeft();
newLogicalTop += overSideMargin;
boxHeightIncludingMargins += overSideMargin + underSideMargin;
}
- curr->setLogicalTop(newLogicalTop);
+ curr->setLogicalTop(newLogicalTop.toFloat());
if (childAffectsTopBottomPos) {
- if (curr->renderer()->isRubyRun()) {
+ if (curr->renderer().isRubyRun()) {
// Treat the leading on the first and last lines of ruby runs as not being part of the overall lineTop/lineBottom.
// Really this is a workaround hack for the fact that ruby should have been done as line layout and not done using
// inline-block.
- if (renderer()->style()->isFlippedLinesWritingMode() == (curr->renderer()->style()->rubyPosition() == RubyPositionAfter))
+ if (renderer().style()->isFlippedLinesWritingMode() == (curr->renderer().style()->rubyPosition() == RubyPositionAfter))
hasAnnotationsBefore = true;
else
hasAnnotationsAfter = true;
- RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
- if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) {
+ RenderRubyRun& rubyRun = toRenderRubyRun(curr->renderer());
+ if (RenderRubyBase* rubyBase = rubyRun.rubyBase()) {
LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : LayoutUnit());
LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : LayoutUnit());
- newLogicalTop += !renderer()->style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading;
+ newLogicalTop += !renderer().style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading;
boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading);
}
}
if (curr->isInlineTextBox()) {
TextEmphasisPosition emphasisMarkPosition;
- if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer()->style(isFirstLineStyle()), emphasisMarkPosition)) {
+ if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer().style(isFirstLineStyle()), emphasisMarkPosition)) {
bool emphasisMarkIsOver = emphasisMarkPosition == TextEmphasisPositionOver;
- if (emphasisMarkIsOver != curr->renderer()->style(isFirstLineStyle())->isFlippedLinesWritingMode())
+ if (emphasisMarkIsOver != curr->renderer().style(isFirstLineStyle())->isFlippedLinesWritingMode())
hasAnnotationsBefore = true;
else
hasAnnotationsAfter = true;
@@ -723,7 +726,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
lineBottomIncludingMargins = max(lineBottom, lineBottomIncludingMargins);
}
- if (renderer()->style()->isFlippedLinesWritingMode())
+ if (renderer().style()->isFlippedLinesWritingMode())
flipLinesInBlockDirection(lineTopIncludingMargins, lineBottomIncludingMargins);
}
}
@@ -731,7 +734,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
void InlineFlowBox::computeMaxLogicalTop(float& maxLogicalTop) const
{
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
if (descendantsHaveSameLineHeightAndBaseline())
@@ -751,7 +754,7 @@ void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lin
setLogicalTop(lineBottom - (logicalTop() - lineTop) - logicalHeight());
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders aren't affected here.
if (curr->isInlineFlowBox())
@@ -767,7 +770,7 @@ inline void InlineFlowBox::addBoxShadowVisualOverflow(LayoutRect& logicalVisualO
if (!parent())
return;
- RenderStyle* style = renderer()->style(isFirstLineStyle());
+ RenderStyle* style = renderer().style(isFirstLineStyle());
if (!style->boxShadow())
return;
@@ -800,7 +803,7 @@ inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisu
if (!parent())
return;
- RenderStyle* style = renderer()->style(isFirstLineStyle());
+ RenderStyle* style = renderer().style(isFirstLineStyle());
if (!style->hasBorderImageOutsets())
return;
@@ -829,12 +832,25 @@ inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisu
logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
}
+inline void InlineFlowBox::addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow)
+{
+ // Outline on root line boxes is applied to the block and not to the lines.
+ if (!parent())
+ return;
+
+ RenderStyle* style = renderer().style(isFirstLineStyle());
+ if (!style->hasOutline())
+ return;
+
+ logicalVisualOverflow.inflate(style->outlineSize());
+}
+
inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, LayoutRect& logicalVisualOverflow)
{
if (textBox->knownToHaveNoOverflow())
return;
- RenderStyle* style = textBox->renderer()->style(isFirstLineStyle());
+ RenderStyle* style = textBox->renderer().style(isFirstLineStyle());
GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
@@ -862,7 +878,7 @@ inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, Glyp
// If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is
// applied to the right, so this is not an issue with left overflow.
- rightGlyphOverflow -= min(0, (int)style->font().letterSpacing());
+ rightGlyphOverflow -= min(0, (int)style->font().fontDescription().letterSpacing());
LayoutUnit textShadowLogicalTop;
LayoutUnit textShadowLogicalBottom;
@@ -891,13 +907,13 @@ inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, Glyp
inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow)
{
- RenderBox* box = toRenderBox(inlineBox->renderer());
+ RenderBox& box = toRenderBox(inlineBox->renderer());
// Visual overflow only propagates if the box doesn't have a self-painting layer. This rectangle does not include
// transforms or relative positioning (since those objects always have self-painting layers), but it does need to be adjusted
// for writing-mode differences.
- if (!box->hasSelfPaintingLayer()) {
- LayoutRect childLogicalVisualOverflow = box->logicalVisualOverflowRectForPropagation(renderer()->style());
+ if (!box.hasSelfPaintingLayer()) {
+ LayoutRect childLogicalVisualOverflow = box.logicalVisualOverflowRectForPropagation(renderer().style());
childLogicalVisualOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
logicalVisualOverflow.unite(childLogicalVisualOverflow);
}
@@ -905,7 +921,7 @@ inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox,
// Layout overflow internal to the child box only propagates if the child box doesn't have overflow clip set.
// Otherwise the child border box propagates as layout overflow. This rectangle must include transforms and relative positioning
// and be adjusted for writing-mode differences.
- LayoutRect childLogicalLayoutOverflow = box->logicalLayoutOverflowRectForPropagation(renderer()->style());
+ LayoutRect childLogicalLayoutOverflow = box.logicalLayoutOverflowRectForPropagation(renderer().style());
childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
logicalLayoutOverflow.unite(childLogicalLayoutOverflow);
}
@@ -913,8 +929,13 @@ inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox,
void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
// If we know we have no overflow, we can just bail.
- if (knownToHaveNoOverflow())
+ if (knownToHaveNoOverflow()) {
+ ASSERT(!m_overflow);
return;
+ }
+
+ if (m_overflow)
+ m_overflow.clear();
// Visual overflow just includes overflow for stuff we need to repaint ourselves. Self-painting layers are ignored.
// Layout overflow is used to determine scrolling extent, so it still includes child layers and also factors in
@@ -924,20 +945,21 @@ void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, G
addBoxShadowVisualOverflow(logicalVisualOverflow);
addBorderOutsetVisualOverflow(logicalVisualOverflow);
+ addOutlineVisualOverflow(logicalVisualOverflow);
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
- if (curr->renderer()->isText()) {
+ if (curr->renderer().isText()) {
InlineTextBox* text = toInlineTextBox(curr);
- RenderText* rt = toRenderText(text->renderer());
- if (rt->isBR())
+ RenderText& rt = toRenderText(text->renderer());
+ if (rt.isBR())
continue;
LayoutRect textBoxOverflow(enclosingLayoutRect(text->logicalFrameRect()));
addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow);
logicalVisualOverflow.unite(textBoxOverflow);
- } else if (curr->renderer()->isRenderInline()) {
+ } else if (curr->renderer().isRenderInline()) {
InlineFlowBox* flow = toInlineFlowBox(curr);
flow->computeOverflow(lineTop, lineBottom, textBoxDataMap);
if (!flow->boxModelObject()->hasSelfPaintingLayer())
@@ -945,16 +967,16 @@ void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, G
LayoutRect childLayoutOverflow = flow->logicalLayoutOverflowRect(lineTop, lineBottom);
childLayoutOverflow.move(flow->boxModelObject()->relativePositionLogicalOffset());
logicalLayoutOverflow.unite(childLayoutOverflow);
- } else
+ } else {
addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow);
+ }
}
setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, lineTop, lineBottom);
}
-void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
+void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, const LayoutRect& frameBox)
{
- LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
if (frameBox.contains(rect) || rect.isEmpty())
return;
@@ -964,9 +986,8 @@ void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, LayoutUnit lineTop
m_overflow->setLayoutOverflow(rect);
}
-void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
+void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, const LayoutRect& frameBox)
{
- LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
if (frameBox.contains(rect) || rect.isEmpty())
return;
@@ -978,11 +999,13 @@ void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, LayoutUnit lineTop
void InlineFlowBox::setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom)
{
+ LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+
LayoutRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect());
- setLayoutOverflow(layoutOverflow, lineTop, lineBottom);
+ setLayoutOverflow(layoutOverflow, frameBox);
LayoutRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect());
- setVisualOverflow(visualOverflow, lineTop, lineBottom);
+ setVisualOverflow(visualOverflow, frameBox);
}
bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
@@ -997,11 +1020,11 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
// We need to account for culled inline parents of the hit-tested nodes, so that they may also get included in area-based hit-tests.
RenderObject* culledParent = 0;
for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
- if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) {
+ if (curr->renderer().isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) {
RenderObject* newParent = 0;
// Culled parents are only relevant for area-based hit-tests, so ignore it in point-based ones.
if (locationInContainer.isRectBasedTest()) {
- newParent = curr->renderer()->parent();
+ newParent = curr->renderer().parent();
if (newParent == renderer())
newParent = 0;
}
@@ -1018,7 +1041,7 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
culledParent = newParent;
}
if (curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
- renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+ renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
return true;
}
}
@@ -1038,13 +1061,13 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
LayoutUnit height = frameRect.height();
// Constrain our hit testing to the line top and bottom if necessary.
- bool noQuirksMode = renderer()->document().inNoQuirksMode();
+ bool noQuirksMode = renderer().document().inNoQuirksMode();
if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
- RootInlineBox* rootBox = root();
+ RootInlineBox& rootBox = root();
LayoutUnit& top = isHorizontal() ? minY : minX;
LayoutUnit& logicalHeight = isHorizontal() ? height : width;
- LayoutUnit bottom = min(rootBox->lineBottom(), top + logicalHeight);
- top = max(rootBox->lineTop(), top);
+ LayoutUnit bottom = min(rootBox.lineBottom(), top + logicalHeight);
+ top = max(rootBox.lineTop(), top);
logicalHeight = bottom - top;
}
@@ -1054,8 +1077,8 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
rect.moveBy(accumulatedOffset);
if (visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); // Don't add in m_x or m_y here, we want coords in the containing block's space.
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+ renderer().updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); // Don't add in m_x or m_y here, we want coords in the containing block's space.
+ if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect))
return true;
}
@@ -1065,7 +1088,6 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
- overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase));
flipForWritingMode(overflowRect);
overflowRect.moveBy(paintOffset);
@@ -1076,16 +1098,16 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
// Add ourselves to the paint info struct's list of inlines that need to paint their
// outlines.
- if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
- RenderInline* inlineFlow = toRenderInline(renderer());
+ if (renderer().style()->visibility() == VISIBLE && renderer().hasOutline() && !isRootInlineBox()) {
+ RenderInline& inlineFlow = toRenderInline(renderer());
RenderBlock* cb = 0;
- bool containingBlockPaintsContinuationOutline = inlineFlow->continuation() || inlineFlow->isInlineElementContinuation();
+ bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isInlineElementContinuation();
if (containingBlockPaintsContinuationOutline) {
// FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
// after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
// anonymous blocks. In this case, it is better to bail out and paint it ourself.
- RenderBlock* enclosingAnonymousBlock = renderer()->containingBlock();
+ RenderBlock* enclosingAnonymousBlock = renderer().containingBlock();
if (!enclosingAnonymousBlock->isAnonymousBlock())
containingBlockPaintsContinuationOutline = false;
else {
@@ -1102,9 +1124,9 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (containingBlockPaintsContinuationOutline) {
// Add ourselves to the containing block of the entire continuation so that it can
// paint us atomically.
- cb->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));
- } else if (!inlineFlow->isInlineElementContinuation()) {
- paintInfo.outlineObjects()->add(inlineFlow);
+ cb->addContinuationWithOutline(toRenderInline(renderer().node()->renderer()));
+ } else if (!inlineFlow.isInlineElementContinuation()) {
+ paintInfo.outlineObjects()->add(&inlineFlow);
}
}
} else if (paintInfo.phase == PaintPhaseMask) {
@@ -1120,14 +1142,19 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
return;
PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
- PaintInfo childInfo(paintInfo);
- childInfo.phase = paintPhase;
- childInfo.updatePaintingRootForChildren(renderer());
// Paint our children.
if (paintPhase != PaintPhaseSelfOutline) {
+ PaintInfo childInfo(paintInfo);
+ childInfo.phase = paintPhase;
+
+ if (childInfo.paintingRoot && childInfo.paintingRoot->isDescendantOf(&renderer()))
+ childInfo.paintingRoot = 0;
+ else
+ childInfo.updatePaintingRootForChildren(&renderer());
+
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
+ if (curr->renderer().isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
curr->paint(childInfo, paintOffset, lineTop, lineBottom);
}
}
@@ -1146,17 +1173,17 @@ bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackg
// The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow
// would be clipped out, so it has to be drawn separately).
StyleImage* image = lastBackgroundLayer.image();
- bool hasFillImage = image && image->canRender(renderer(), renderer()->style()->effectiveZoom());
- return (!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent();
+ bool hasFillImage = image && image->canRender(renderer(), renderer().style()->effectiveZoom());
+ return (!hasFillImage && !renderer().style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent();
}
void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
{
StyleImage* img = fillLayer->image();
- bool hasFillImage = img && img->canRender(renderer(), renderer()->style()->effectiveZoom());
- if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
+ bool hasFillImage = img && img->canRender(renderer(), renderer().style()->effectiveZoom());
+ if ((!hasFillImage && !renderer().style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent()) {
boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
- else if (renderer()->style()->boxDecorationBreak() == DCLONE) {
+ } else if (renderer().style()->boxDecorationBreak() == DCLONE) {
GraphicsContextStateSaver stateSaver(*paintInfo.context);
paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
@@ -1169,7 +1196,7 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c
// the previous line left off.
LayoutUnit logicalOffsetOnLine = 0;
LayoutUnit totalLogicalWidth;
- if (renderer()->style()->direction() == LTR) {
+ if (renderer().style()->direction() == LTR) {
for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
logicalOffsetOnLine += curr->logicalWidth();
totalLogicalWidth = logicalOffsetOnLine;
@@ -1206,13 +1233,13 @@ void InlineFlowBox::paintBoxShadow(const PaintInfo& info, RenderStyle* s, Shadow
void InlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
{
- bool noQuirksMode = renderer()->document().inNoQuirksMode();
+ bool noQuirksMode = renderer().document().inNoQuirksMode();
if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
- const RootInlineBox* rootBox = root();
+ const RootInlineBox& rootBox = root();
LayoutUnit logicalTop = isHorizontal() ? rect.y() : rect.x();
LayoutUnit logicalHeight = isHorizontal() ? rect.height() : rect.width();
- LayoutUnit bottom = min(rootBox->lineBottom(), logicalTop + logicalHeight);
- logicalTop = max(rootBox->lineTop(), logicalTop);
+ LayoutUnit bottom = min(rootBox.lineBottom(), logicalTop + logicalHeight);
+ logicalTop = max(rootBox.lineTop(), logicalTop);
logicalHeight = bottom - logicalTop;
if (isHorizontal()) {
rect.setY(logicalTop);
@@ -1227,7 +1254,7 @@ void InlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
{
LayoutRect clipRect(paintRect);
- RenderStyle* style = box->renderer()->style();
+ RenderStyle* style = box->renderer().style();
LayoutBoxExtent outsets = style->imageOutsets(image);
if (box->isHorizontal()) {
clipRect.setY(paintRect.y() - outsets.top());
@@ -1253,7 +1280,7 @@ static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NineP
void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
+ if (!paintInfo.shouldPaintWithinRoot(&renderer()) || renderer().style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
return;
// Pixel snap background/border painting.
@@ -1270,21 +1297,21 @@ 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(isFirstLineStyle());
- if ((!parent() && isFirstLineStyle() && 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))
paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
- Color c = renderer()->resolveColor(styleToUse, CSSPropertyBackgroundColor);
+ Color c = renderer().resolveColor(styleToUse, CSSPropertyBackgroundColor);
paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect);
paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
// :first-line cannot be used to put borders on a line. Always paint borders with our
// non-first-line style.
- if (parent() && renderer()->style()->hasBorder()) {
- const NinePieceImage& borderImage = renderer()->style()->borderImage();
+ if (parent() && renderer().style()->hasBorder()) {
+ const NinePieceImage& borderImage = renderer().style()->borderImage();
StyleImage* borderImageSource = borderImage.image();
bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom());
if (hasBorderImage && !borderImageSource->isLoaded())
@@ -1293,7 +1320,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(isFirstLineStyle()), 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.
@@ -1317,7 +1344,7 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&
LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
GraphicsContextStateSaver stateSaver(*context);
context->clip(clipRect);
- boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(isFirstLineStyle()));
+ boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(isFirstLineStyle()));
}
}
}
@@ -1325,7 +1352,7 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&
void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+ if (!paintInfo.shouldPaintWithinRoot(&renderer()) || renderer().style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
return;
// Pixel snap mask painting.
@@ -1338,16 +1365,16 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
flipForWritingMode(localRect);
LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
- const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
- StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();
+ const NinePieceImage& maskNinePieceImage = renderer().style()->maskBoxImage();
+ StyleImage* maskBoxImage = renderer().style()->maskBoxImage().image();
// 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;
+ bool compositedMask = renderer().hasLayer() && boxModelObject()->layer()->hasCompositedMask();
+ bool flattenCompositingLayers = renderer().view()->frameView() && renderer().view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
CompositeOperator compositeOp = CompositeSourceOver;
if (!compositedMask || flattenCompositingLayers) {
- if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
+ if ((maskBoxImage && renderer().style()->maskLayers()->hasImage()) || renderer().style()->maskLayers()->next())
pushTransparencyLayer = true;
compositeOp = CompositeDestinationIn;
@@ -1359,9 +1386,9 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
}
LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
- paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), paintRect, compositeOp);
+ paintFillLayers(paintInfo, Color::transparent, renderer().style()->maskLayers(), paintRect, compositeOp);
- bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer()->style()->effectiveZoom());
+ bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer().style()->effectiveZoom());
if (!hasBoxImage || !maskBoxImage->isLoaded()) {
if (pushTransparencyLayer)
paintInfo.context->endLayer();
@@ -1371,7 +1398,7 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// The simple case is where we are the only box for this object. In those
// cases only a single call to draw is required.
if (!prevLineBox() && !nextLineBox()) {
- boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(adjustedPaintOffset, frameRect.size()), renderer()->style(), maskNinePieceImage, compositeOp);
+ boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(adjustedPaintOffset, frameRect.size()), renderer().style(), maskNinePieceImage, compositeOp);
} else {
// We have a mask image that spans multiple lines.
// We need to adjust _tx and _ty by the width of all previous lines.
@@ -1389,7 +1416,7 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
LayoutRect clipRect = clipRectForNinePieceImageStrip(this, maskNinePieceImage, paintRect);
GraphicsContextStateSaver stateSaver(*paintInfo.context);
paintInfo.context->clip(clipRect);
- boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(), maskNinePieceImage, compositeOp);
+ boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(), maskNinePieceImage, compositeOp);
}
if (pushTransparencyLayer)
@@ -1466,19 +1493,19 @@ LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosi
{
LayoutUnit result = 0;
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
if (curr->isInlineFlowBox())
result = max(result, toInlineFlowBox(curr)->computeOverAnnotationAdjustment(allowedPosition));
- if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionBefore) {
- RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
- RenderRubyText* rubyText = rubyRun->rubyText();
+ if (curr->renderer().isReplaced() && curr->renderer().isRubyRun() && curr->renderer().style()->rubyPosition() == RubyPositionBefore) {
+ RenderRubyRun& rubyRun = toRenderRubyRun(curr->renderer());
+ RenderRubyText* rubyText = rubyRun.rubyText();
if (!rubyText)
continue;
- if (!rubyRun->style()->isFlippedLinesWritingMode()) {
+ if (!rubyRun.style()->isFlippedLinesWritingMode()) {
LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
if (topOfFirstRubyTextLine >= 0)
continue;
@@ -1494,7 +1521,7 @@ LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosi
}
if (curr->isInlineTextBox()) {
- RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
+ RenderStyle* style = curr->renderer().style(isFirstLineStyle());
TextEmphasisPosition emphasisMarkPosition;
if (style->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(style, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
if (!style->isFlippedLinesWritingMode()) {
@@ -1514,19 +1541,19 @@ LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPos
{
LayoutUnit result = 0;
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->renderer()->isOutOfFlowPositioned())
+ if (curr->renderer().isOutOfFlowPositioned())
continue; // Positioned placeholders don't affect calculations.
if (curr->isInlineFlowBox())
result = max(result, toInlineFlowBox(curr)->computeUnderAnnotationAdjustment(allowedPosition));
- if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionAfter) {
- RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
- RenderRubyText* rubyText = rubyRun->rubyText();
+ if (curr->renderer().isReplaced() && curr->renderer().isRubyRun() && curr->renderer().style()->rubyPosition() == RubyPositionAfter) {
+ RenderRubyRun& rubyRun = toRenderRubyRun(curr->renderer());
+ RenderRubyText* rubyText = rubyRun.rubyText();
if (!rubyText)
continue;
- if (rubyRun->style()->isFlippedLinesWritingMode()) {
+ if (rubyRun.style()->isFlippedLinesWritingMode()) {
LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
if (topOfFirstRubyTextLine >= 0)
continue;
@@ -1542,7 +1569,7 @@ LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPos
}
if (curr->isInlineTextBox()) {
- RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
+ 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());
@@ -1573,7 +1600,7 @@ void InlineFlowBox::collectLeafBoxesInLogicalOrder(Vector<InlineBox*>& leafBoxes
leafBoxesInLogicalOrder.append(leaf);
}
- if (renderer()->style()->rtlOrdering() == VisualOrder)
+ if (renderer().style()->rtlOrdering() == VisualOrder)
return;
// Reverse of reordering of the line (L2 according to Bidi spec):
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.h b/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.h
index 066098fdac8..795cab50a45 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineFlowBox.h
@@ -40,7 +40,7 @@ typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphO
class InlineFlowBox : public InlineBox {
public:
- InlineFlowBox(RenderObject* obj)
+ InlineFlowBox(RenderObject& obj)
: InlineBox(obj)
, m_firstChild(0)
, m_lastChild(0)
@@ -52,6 +52,9 @@ public:
, m_baselineType(AlphabeticBaseline)
, m_hasAnnotationsBefore(false)
, m_hasAnnotationsAfter(false)
+ , m_lineBreakBidiStatusEor(WTF::Unicode::LeftToRight)
+ , m_lineBreakBidiStatusLastStrong(WTF::Unicode::LeftToRight)
+ , m_lineBreakBidiStatusLast(WTF::Unicode::LeftToRight)
#ifndef NDEBUG
, m_hasBadChildList(false)
#endif
@@ -61,15 +64,15 @@ public:
// an invisible marker exists. The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
// text children must not apply. This change also means that gaps will exist between image bullet list items. Even when the list bullet
// is an image, the line is still considered to be immune from the quirk.
- m_hasTextChildren = obj->style()->display() == LIST_ITEM;
+ m_hasTextChildren = obj.style()->display() == LIST_ITEM;
m_hasTextDescendants = m_hasTextChildren;
}
#ifndef NDEBUG
virtual ~InlineFlowBox();
- virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
- virtual const char* boxName() const;
+ virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const OVERRIDE;
+ virtual const char* boxName() const OVERRIDE;
#endif
InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
@@ -99,7 +102,7 @@ public:
virtual void deleteLine() OVERRIDE FINAL;
virtual void extractLine() OVERRIDE FINAL;
virtual void attachLine() OVERRIDE FINAL;
- virtual void adjustPosition(float dx, float dy);
+ virtual void adjustPosition(float dx, float dy) OVERRIDE;
virtual void extractLineBoxFromRenderObject();
virtual void attachLineBoxToRenderObject();
@@ -114,7 +117,7 @@ public:
void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(const PaintInfo&, RenderStyle*, ShadowStyle, const LayoutRect&);
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
@@ -140,13 +143,13 @@ public:
{
if (!includeLogicalLeftEdge())
return 0;
- return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderLeftWidth() : renderer()->style(isFirstLineStyle())->borderTopWidth();
+ return isHorizontal() ? renderer().style(isFirstLineStyle())->borderLeftWidth() : renderer().style(isFirstLineStyle())->borderTopWidth();
}
int borderLogicalRight() const
{
if (!includeLogicalRightEdge())
return 0;
- return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderRightWidth() : renderer()->style(isFirstLineStyle())->borderBottomWidth();
+ return isHorizontal() ? renderer().style(isFirstLineStyle())->borderRightWidth() : renderer().style(isFirstLineStyle())->borderBottomWidth();
}
int paddingLogicalLeft() const
{
@@ -197,9 +200,9 @@ public:
void computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap&);
- void removeChild(InlineBox* child);
+ void removeChild(InlineBox* child, MarkLineBoxes);
- virtual RenderObject::SelectionState selectionState();
+ virtual RenderObject::SelectionState selectionState() OVERRIDE;
virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const OVERRIDE FINAL;
virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool&) OVERRIDE;
@@ -244,7 +247,7 @@ public:
LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
{
LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
- if (!renderer()->isHorizontalWritingMode())
+ if (!renderer().isHorizontalWritingMode())
result = result.transposedRect();
return result;
}
@@ -270,25 +273,23 @@ public:
LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
{
LayoutRect result = visualOverflowRect(lineTop, lineBottom);
- if (!renderer()->isHorizontalWritingMode())
+ if (!renderer().isHorizontalWritingMode())
result = result.transposedRect();
return result;
}
void setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom);
- void setLayoutOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
- void setVisualOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
{
if (isHorizontal())
- return FloatRect(m_topLeft.x(), lineTop, width(), lineBottom - lineTop);
- return FloatRect(lineTop, m_topLeft.y(), lineBottom - lineTop, height());
+ return FloatRect(m_topLeft.x(), lineTop.toFloat(), width(), (lineBottom - lineTop).toFloat());
+ return FloatRect(lineTop.toFloat(), m_topLeft.y(), (lineBottom - lineTop).toFloat(), height());
}
FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
{
- return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
+ return FloatRect(logicalLeft(), lineTop.toFloat(), logicalWidth(), (lineBottom - lineTop).toFloat());
}
bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
@@ -302,10 +303,14 @@ public:
private:
void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow);
void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow);
+ void addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow);
void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
void addReplacedChildOverflow(const InlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
+ void setLayoutOverflow(const LayoutRect&, const LayoutRect&);
+ void setVisualOverflow(const LayoutRect&, const LayoutRect&);
+
protected:
OwnPtr<RenderOverflow> m_overflow;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineIterator.h b/chromium/third_party/WebKit/Source/core/rendering/InlineIterator.h
index c0c30d9ad8a..e0ecc103241 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineIterator.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineIterator.h
@@ -25,6 +25,7 @@
#include "core/rendering/BidiRun.h"
#include "core/rendering/RenderBlockFlow.h"
+#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderText.h"
#include "wtf/StdLibExtras.h"
@@ -43,16 +44,16 @@ public:
InlineIterator()
: m_root(0)
, m_obj(0)
- , m_pos(0)
, m_nextBreakablePosition(-1)
+ , m_pos(0)
{
}
InlineIterator(RenderObject* root, RenderObject* o, unsigned p)
: m_root(root)
, m_obj(o)
- , m_pos(p)
, m_nextBreakablePosition(-1)
+ , m_pos(p)
{
}
@@ -73,7 +74,11 @@ public:
RenderObject* object() const { return m_obj; }
void setObject(RenderObject* object) { m_obj = object; }
+ int nextBreakablePosition() const { return m_nextBreakablePosition; }
+ void setNextBreakablePosition(int position) { m_nextBreakablePosition = position; }
+
unsigned offset() const { return m_pos; }
+ void setOffset(unsigned position) { m_pos = position; }
RenderObject* root() const { return m_root; }
void fastIncrementInTextNode();
@@ -100,20 +105,18 @@ private:
RenderObject* m_root;
RenderObject* m_obj;
-// FIXME: These should be private.
-public:
- unsigned m_pos;
int m_nextBreakablePosition;
+ unsigned m_pos;
};
inline bool operator==(const InlineIterator& it1, const InlineIterator& it2)
{
- return it1.m_pos == it2.m_pos && it1.object() == it2.object();
+ return it1.offset() == it2.offset() && it1.object() == it2.object();
}
inline bool operator!=(const InlineIterator& it1, const InlineIterator& it2)
{
- return it1.m_pos != it2.m_pos || it1.object() != it2.object();
+ return it1.offset() != it2.offset() || it1.object() != it2.object();
}
static inline WTF::Unicode::Direction embedCharFromDirection(TextDirection dir, EUnicodeBidi unicodeBidi)
@@ -187,7 +190,7 @@ static bool isEmptyInline(RenderObject* object)
if (!object->isRenderInline())
return false;
- for (RenderObject* curr = object->firstChild(); curr; curr = curr->nextSibling()) {
+ for (RenderObject* curr = toRenderInline(object)->firstChild(); curr; curr = curr->nextSibling()) {
if (curr->isFloatingOrOutOfFlowPositioned())
continue;
if (curr->isText() && toRenderText(curr)->isAllCollapsibleWhitespace())
@@ -213,7 +216,7 @@ static inline RenderObject* bidiNextShared(RenderObject* root, RenderObject* cur
while (current) {
next = 0;
if (!oldEndOfInline && !isIteratorTarget(current)) {
- next = current->firstChild();
+ next = current->slowFirstChild();
notifyObserverEnteredObject(observer, next);
}
@@ -280,7 +283,7 @@ static inline RenderObject* bidiNextIncludingEmptyInlines(RenderObject* root, Re
return bidiNextShared(root, current, observer, IncludeEmptyInlines, endOfInlinePtr);
}
-static inline RenderObject* bidiFirstSkippingEmptyInlines(RenderObject* root, InlineBidiResolver* resolver = 0)
+static inline RenderObject* bidiFirstSkippingEmptyInlines(RenderBlockFlow* root, InlineBidiResolver* resolver = 0)
{
RenderObject* o = root->firstChild();
if (!o)
@@ -308,7 +311,7 @@ static inline RenderObject* bidiFirstSkippingEmptyInlines(RenderObject* root, In
}
// FIXME: This method needs to be renamed when bidiNext finds a good name.
-static inline RenderObject* bidiFirstIncludingEmptyInlines(RenderObject* root)
+static inline RenderObject* bidiFirstIncludingEmptyInlines(RenderBlock* root)
{
RenderObject* o = root->firstChild();
// If either there are no children to walk, or the first one is correct
@@ -332,7 +335,7 @@ inline void InlineIterator::fastIncrementInTextNode()
// it shouldn't use functions called bidiFirst and bidiNext.
class InlineWalker {
public:
- InlineWalker(RenderObject* root)
+ InlineWalker(RenderBlock* root)
: m_root(root)
, m_current(0)
, m_atEndOfInline(false)
@@ -341,7 +344,7 @@ public:
m_current = bidiFirstIncludingEmptyInlines(m_root);
}
- RenderObject* root() { return m_root; }
+ RenderBlock* root() { return m_root; }
RenderObject* current() { return m_current; }
bool atEndOfInline() { return m_atEndOfInline; }
@@ -354,7 +357,7 @@ public:
return m_current;
}
private:
- RenderObject* m_root;
+ RenderBlock* m_root;
RenderObject* m_current;
bool m_atEndOfInline;
};
@@ -442,13 +445,74 @@ inline bool InlineBidiResolver::isEndOfLine(const InlineIterator& end)
{
bool inEndOfLine = m_current == end || m_current.atEnd() || (inIsolate() && m_current.object() == end.object());
if (inIsolate() && inEndOfLine) {
- m_current.moveTo(m_current.object(), end.m_pos, m_current.m_nextBreakablePosition);
+ m_current.moveTo(m_current.object(), end.offset(), m_current.nextBreakablePosition());
m_last = m_current;
updateStatusLastFromCurrentDirection(WTF::Unicode::OtherNeutral);
}
return inEndOfLine;
}
+static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
+{
+ if (character == ' ' || character == '\t' || character == softHyphen)
+ return true;
+ if (character == '\n')
+ return !renderer->style()->preserveNewline();
+ return false;
+}
+
+template <typename CharacterType>
+static inline int findFirstTrailingSpace(RenderText* lastText, const CharacterType* characters, int start, int stop)
+{
+ int firstSpace = stop;
+ while (firstSpace > start) {
+ UChar current = characters[firstSpace - 1];
+ if (!isCollapsibleSpace(current, lastText))
+ break;
+ firstSpace--;
+ }
+
+ return firstSpace;
+}
+
+template <>
+inline int InlineBidiResolver::findFirstTrailingSpaceAtRun(BidiRun* run)
+{
+ ASSERT(run);
+ RenderObject* lastObject = run->m_object;
+ if (!lastObject->isText())
+ return run->m_stop;
+
+ RenderText* lastText = toRenderText(lastObject);
+ int firstSpace;
+ if (lastText->is8Bit())
+ firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), run->start(), run->stop());
+ else
+ firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(), run->start(), run->stop());
+ return firstSpace;
+}
+
+template <>
+inline BidiRun* InlineBidiResolver::addTrailingRun(int start, int stop, BidiRun* run, BidiContext* context, TextDirection direction)
+{
+ BidiRun* newTrailingRun = new BidiRun(start, stop, run->m_object, context, WTF::Unicode::OtherNeutral);
+ if (direction == LTR)
+ m_runs.addRun(newTrailingRun);
+ else
+ m_runs.prependRun(newTrailingRun);
+
+ return newTrailingRun;
+}
+
+template <>
+inline bool InlineBidiResolver::needsToApplyL1Rule()
+{
+ if (!m_runs.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
+ || !m_runs.logicallyLastRun()->m_object->style()->autoWrap())
+ return false;
+ return true;
+}
+
static inline bool isIsolatedInline(RenderObject* object)
{
ASSERT(object);
@@ -569,18 +633,18 @@ static void adjustMidpointsAndAppendRunsForObjectIfNeeded(RenderObject* obj, uns
return;
LineMidpointState& lineMidpointState = resolver.midpointState();
- bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointState.numMidpoints);
+ bool haveNextMidpoint = (lineMidpointState.currentMidpoint() < lineMidpointState.numMidpoints());
InlineIterator nextMidpoint;
if (haveNextMidpoint)
- nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidpoint];
- if (lineMidpointState.betweenMidpoints) {
+ nextMidpoint = lineMidpointState.midpoints()[lineMidpointState.currentMidpoint()];
+ if (lineMidpointState.betweenMidpoints()) {
if (!(haveNextMidpoint && nextMidpoint.object() == obj))
return;
// This is a new start point. Stop ignoring objects and
// adjust our start.
- lineMidpointState.betweenMidpoints = false;
- start = nextMidpoint.m_pos;
- lineMidpointState.currentMidpoint++;
+ lineMidpointState.setBetweenMidpoints(false);
+ start = nextMidpoint.offset();
+ lineMidpointState.incrementCurrentMidpoint();
if (start < end)
return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, resolver, behavior, tracker);
} else {
@@ -591,13 +655,13 @@ static void adjustMidpointsAndAppendRunsForObjectIfNeeded(RenderObject* obj, uns
// An end midpoint has been encountered within our object. We
// need to go ahead and append a run with our endpoint.
- if (nextMidpoint.m_pos + 1 <= end) {
- lineMidpointState.betweenMidpoints = true;
- lineMidpointState.currentMidpoint++;
- if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it.
- if (nextMidpoint.m_pos + 1 > start)
- appendRunObjectIfNecessary(obj, start, nextMidpoint.m_pos + 1, resolver, behavior, tracker);
- return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMidpoint.m_pos + 1, end, resolver, behavior, tracker);
+ if (nextMidpoint.offset() + 1 <= end) {
+ lineMidpointState.setBetweenMidpoints(true);
+ lineMidpointState.incrementCurrentMidpoint();
+ if (nextMidpoint.offset() != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it.
+ if (nextMidpoint.offset() + 1 > start)
+ appendRunObjectIfNecessary(obj, start, nextMidpoint.offset() + 1, resolver, behavior, tracker);
+ return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMidpoint.offset() + 1, end, resolver, behavior, tracker);
}
} else {
appendRunObjectIfNecessary(obj, start, end, resolver, behavior, tracker);
@@ -619,7 +683,7 @@ inline void InlineBidiResolver::appendRun()
// Initialize our state depending on if we're starting in the middle of such an inline.
// FIXME: Could this initialize from this->inIsolate() instead of walking up the render tree?
IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor));
- int start = m_sor.m_pos;
+ int start = m_sor.offset();
RenderObject* obj = m_sor.object();
while (obj && obj != m_eor.object() && obj != m_endOfRunAtEndOfLine.object()) {
if (isolateTracker.inIsolate())
@@ -630,12 +694,12 @@ inline void InlineBidiResolver::appendRun()
start = 0;
obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracker);
}
- bool isEndOfLine = obj == m_endOfLine.object() && !m_endOfLine.m_pos;
+ bool isEndOfLine = obj == m_endOfLine.object() && !m_endOfLine.offset();
if (obj && !isEndOfLine) {
- unsigned pos = obj == m_eor.object() ? m_eor.m_pos : INT_MAX;
- if (obj == m_endOfRunAtEndOfLine.object() && m_endOfRunAtEndOfLine.m_pos <= pos) {
+ unsigned pos = obj == m_eor.object() ? m_eor.offset() : INT_MAX;
+ if (obj == m_endOfRunAtEndOfLine.object() && m_endOfRunAtEndOfLine.offset() <= pos) {
m_reachedEndOfLine = true;
- pos = m_endOfRunAtEndOfLine.m_pos;
+ pos = m_endOfRunAtEndOfLine.offset();
}
// It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be
int end = obj->length() ? pos + 1 : 0;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.cpp
index 60a35deccf1..af997333d2d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.cpp
@@ -27,9 +27,11 @@
#include "core/dom/DocumentMarkerController.h"
#include "core/dom/RenderedDocumentMarker.h"
#include "core/dom/Text.h"
+#include "core/editing/CompositionUnderline.h"
+#include "core/editing/CompositionUnderlineRangeFilter.h"
#include "core/editing/Editor.h"
#include "core/editing/InputMethodController.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/rendering/AbstractInlineTextBox.h"
@@ -45,13 +47,16 @@
#include "core/rendering/style/ShadowList.h"
#include "core/rendering/svg/SVGTextRunRenderingContext.h"
#include "platform/fonts/FontCache.h"
+#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/WidthIterator.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "wtf/Vector.h"
#include "wtf/text/CString.h"
#include "wtf/text/StringBuilder.h"
+#include <algorithm>
+
using namespace std;
namespace WebCore {
@@ -78,13 +83,11 @@ void InlineTextBox::destroy()
InlineBox::destroy();
}
-void InlineTextBox::markDirty(bool dirty)
+void InlineTextBox::markDirty()
{
- if (dirty) {
- m_len = 0;
- m_start = 0;
- }
- InlineBox::markDirty(dirty);
+ m_len = 0;
+ m_start = 0;
+ InlineBox::markDirty();
}
LayoutRect InlineTextBox::logicalOverflowRect() const
@@ -106,35 +109,35 @@ int InlineTextBox::baselinePosition(FontBaseline baselineType) const
{
if (!isText() || !parent())
return 0;
- if (parent()->renderer() == renderer()->parent())
+ if (parent()->renderer() == renderer().parent())
return parent()->baselinePosition(baselineType);
- return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+ return toRenderBoxModelObject(renderer().parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
}
LayoutUnit InlineTextBox::lineHeight() const
{
- if (!isText() || !renderer()->parent())
+ if (!isText() || !renderer().parent())
return 0;
- if (m_renderer->isBR())
- return toRenderBR(m_renderer)->lineHeight(isFirstLineStyle());
- if (parent()->renderer() == renderer()->parent())
+ if (renderer().isBR())
+ return toRenderBR(renderer()).lineHeight(isFirstLineStyle());
+ if (parent()->renderer() == renderer().parent())
return parent()->lineHeight();
- return toRenderBoxModelObject(renderer()->parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+ return toRenderBoxModelObject(renderer().parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
}
LayoutUnit InlineTextBox::selectionTop()
{
- return root()->selectionTop();
+ return root().selectionTop();
}
LayoutUnit InlineTextBox::selectionBottom()
{
- return root()->selectionBottom();
+ return root().selectionBottom();
}
LayoutUnit InlineTextBox::selectionHeight()
{
- return root()->selectionHeight();
+ return root().selectionHeight();
}
bool InlineTextBox::isSelected(int startPos, int endPos) const
@@ -148,16 +151,16 @@ bool InlineTextBox::isSelected(int startPos, int endPos) const
RenderObject::SelectionState InlineTextBox::selectionState()
{
- RenderObject::SelectionState state = renderer()->selectionState();
+ RenderObject::SelectionState state = renderer().selectionState();
if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {
int startPos, endPos;
- renderer()->selectionStartEnd(startPos, endPos);
+ renderer().selectionStartEnd(startPos, endPos);
// The position after a hard line break is considered to be past its end.
// See the corresponding code in InlineTextBox::isSelected.
int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);
// FIXME: Remove -webkit-line-break: LineBreakAfterWhiteSpace.
- int endOfLineAdjustmentForCSSLineBreak = renderer()->style()->lineBreak() == LineBreakAfterWhiteSpace ? -1 : 0;
+ int endOfLineAdjustmentForCSSLineBreak = renderer().style()->lineBreak() == LineBreakAfterWhiteSpace ? -1 : 0;
bool start = (state != RenderObject::SelectionEnd && startPos >= m_start && startPos <= m_start + m_len + endOfLineAdjustmentForCSSLineBreak);
bool end = (state != RenderObject::SelectionStart && endPos > m_start && endPos <= lastSelectable);
if (start && end)
@@ -174,8 +177,8 @@ RenderObject::SelectionState InlineTextBox::selectionState()
}
// If there are ellipsis following, make sure their selection is updated.
- if (m_truncation != cNoTruncation && root()->ellipsisBox()) {
- EllipsisBox* ellipsis = root()->ellipsisBox();
+ if (m_truncation != cNoTruncation && root().ellipsisBox()) {
+ EllipsisBox* ellipsis = root().ellipsisBox();
if (state != RenderObject::SelectionNone) {
int start, end;
selectionStartEnd(start, end);
@@ -202,24 +205,21 @@ LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
FontCachePurgePreventer fontCachePurgePreventer;
- RenderText* textObj = textRenderer();
LayoutUnit selTop = selectionTop();
LayoutUnit selHeight = selectionHeight();
- RenderStyle* styleToUse = textObj->style(isFirstLineStyle());
+ RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle());
const Font& font = styleToUse->font();
StringBuilder charactersWithHyphen;
bool respectHyphen = ePos == m_len && hasHyphen();
TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0);
- if (respectHyphen)
- endPos = textRun.length();
- FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop);
+ FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat());
LayoutRect r;
if (sPos || ePos != static_cast<int>(m_len))
r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, selHeight, sPos, ePos));
else // Avoid computing the font width when the entire line box is selected as an optimization.
- r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight)));
+ r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight.toFloat())));
LayoutUnit logicalWidth = r.width();
if (r.x() > logicalRight())
@@ -236,7 +236,7 @@ LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
void InlineTextBox::deleteLine()
{
- toRenderText(renderer())->removeTextBox(this);
+ toRenderText(renderer()).removeTextBox(this);
destroy();
}
@@ -245,7 +245,7 @@ void InlineTextBox::extractLine()
if (extracted())
return;
- toRenderText(renderer())->extractTextBox(this);
+ toRenderText(renderer()).extractTextBox(this);
}
void InlineTextBox::attachLine()
@@ -253,7 +253,7 @@ void InlineTextBox::attachLine()
if (!extracted())
return;
- toRenderText(renderer())->attachTextBox(this);
+ toRenderText(renderer()).attachTextBox(this);
}
float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
@@ -307,7 +307,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(), isFirstLineStyle());
+ float widthOfVisibleText = toRenderText(renderer()).width(m_start, offset, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle());
// The ellipsis needs to be placed just after the last visible character.
// Where "after" is defined by the flow directionality, not the inline
@@ -369,7 +369,7 @@ void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, con
bool InlineTextBox::isLineBreak() const
{
- return renderer()->isBR() || (renderer()->style()->preserveNewline() && len() == 1 && (*textRenderer()->text().impl())[start()] == '\n');
+ return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*textRenderer().text().impl())[start()] == '\n');
}
bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
@@ -381,15 +381,15 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
boxOrigin.moveBy(accumulatedOffset);
FloatRect rect(boxOrigin, size());
if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset)));
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+ renderer().updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset)));
+ if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect))
return true;
}
return false;
}
static void paintTextWithShadows(GraphicsContext* context,
- const RenderObject* renderer, const Font& font, const TextRun& textRun,
+ const RenderObject& renderer, const Font& font, const TextRun& textRun,
const AtomicString& emphasisMark, int emphasisMarkOffset,
int startOffset, int endOffset, int truncationPoint,
const FloatPoint& textOrigin, const FloatRect& boxRect,
@@ -399,17 +399,17 @@ static void paintTextWithShadows(GraphicsContext* context,
bool hasShadow = shadowList && !context->printing();
if (hasShadow) {
- DrawLooper drawLooper;
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
for (size_t i = shadowList->shadows().size(); i--; ) {
const ShadowData& shadow = shadowList->shadows()[i];
- int shadowX = horizontal ? shadow.x() : shadow.y();
- int shadowY = horizontal ? shadow.y() : -shadow.x();
+ float shadowX = horizontal ? shadow.x() : shadow.y();
+ float shadowY = horizontal ? shadow.y() : -shadow.x();
FloatSize offset(shadowX, shadowY);
- drawLooper.addShadow(offset, shadow.blur(), renderer->resolveColor(shadow.color()),
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
+ drawLooperBuilder->addShadow(offset, shadow.blur(), shadow.color(),
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha);
}
- drawLooper.addUnmodifiedContent();
- context->setDrawLooper(drawLooper);
+ drawLooperBuilder->addUnmodifiedContent();
+ context->setDrawLooper(drawLooperBuilder.release());
}
TextRunPaintInfo textRunPaintInfo(textRun);
@@ -454,7 +454,7 @@ bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
if (emphasisPosition == TextEmphasisPositionUnder)
return true; // Ruby text is always over, so it cannot suppress emphasis marks under.
- RenderBlock* containingBlock = renderer()->containingBlock();
+ RenderBlock* containingBlock = renderer().containingBlock();
if (!containingBlock->isRubyBase())
return true; // This text is not inside a ruby base, so it does not have ruby text over it.
@@ -469,8 +469,8 @@ bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/)
{
- if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE ||
- m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline || !m_len)
+ if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || renderer().style()->visibility() != VISIBLE
+ || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline || !m_len)
return;
ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
@@ -483,12 +483,18 @@ 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 = roundedIntPoint(paintOffset);
+ // When subpixel font scaling is enabled text runs are positioned at
+ // subpixel boundaries on the x-axis and thus there is no reason to
+ // snap the x value. We still round the y-axis to ensure consistent
+ // line heights.
+ LayoutPoint adjustedPaintOffset = RuntimeEnabledFeatures::subpixelFontScalingEnabled()
+ ? LayoutPoint(paintOffset.x(), paintOffset.y().round())
+ : roundedIntPoint(paintOffset);
if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart)
return;
- bool isPrinting = textRenderer()->document().printing();
+ bool isPrinting = textRenderer().document().printing();
// Determine whether or not we're selected.
bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;
@@ -497,7 +503,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
return;
if (m_truncation != cNoTruncation) {
- if (renderer()->containingBlock()->style()->isLeftToRightDirection() != isLeftToRightDirection()) {
+ if (renderer().containingBlock()->style()->isLeftToRightDirection() != isLeftToRightDirection()) {
// Make the visible fragment of text hug the edge closest to the rest of the run by moving the origin
// at which we start drawing text.
// e.g. In the case of LTR text truncated in an RTL Context, the correct behavior is:
@@ -506,7 +512,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(), isFirstLineStyle());
+ LayoutUnit widthOfVisibleText = toRenderText(renderer()).width(m_start, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, 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,24 +522,24 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
GraphicsContext* context = paintInfo.context;
- RenderObject* rendererToUse = renderer();
- RenderStyle* styleToUse = rendererToUse->style(isFirstLineStyle());
+ RenderObject& rendererToUse = renderer();
+ RenderStyle* styleToUse = rendererToUse.style(isFirstLineStyle());
adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -logicalHeight());
FloatPoint boxOrigin = locationIncludingFlipping();
- boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y());
+ boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().toFloat());
FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight()));
- RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRenderer()->isCombineText() && toRenderCombineText(textRenderer())->isCombined() ? toRenderCombineText(textRenderer()) : 0;
+ RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRenderer().isCombineText() && toRenderCombineText(textRenderer()).isCombined() ? &toRenderCombineText(textRenderer()) : 0;
bool shouldRotate = !isHorizontal() && !combinedText;
if (shouldRotate)
context->concatCTM(rotation(boxRect, Clockwise));
// Determine whether or not we have composition underlines to draw.
- bool containsComposition = renderer()->node() && renderer()->frame()->inputMethodController().compositionNode() == renderer()->node();
- bool useCustomUnderlines = containsComposition && renderer()->frame()->inputMethodController().compositionUsesCustomUnderlines();
+ bool containsComposition = renderer().node() && renderer().frame()->inputMethodController().compositionNode() == renderer().node();
+ bool useCustomUnderlines = containsComposition && renderer().frame()->inputMethodController().compositionUsesCustomUnderlines();
// Determine the text colors and selection colors.
Color textFillColor;
@@ -549,13 +555,13 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
textStrokeColor = Color::black;
emphasisMarkColor = Color::black;
} else {
- textFillColor = rendererToUse->resolveColor(styleToUse, CSSPropertyWebkitTextFillColor);
+ textFillColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebkitTextFillColor);
bool forceBackgroundToWhite = false;
if (isPrinting) {
if (styleToUse->printColorAdjust() == PrintColorAdjustEconomy)
forceBackgroundToWhite = true;
- if (textRenderer()->document().settings() && textRenderer()->document().settings()->shouldPrintBackgrounds())
+ if (textRenderer().document().settings() && textRenderer().document().settings()->shouldPrintBackgrounds())
forceBackgroundToWhite = false;
}
@@ -563,13 +569,13 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (forceBackgroundToWhite)
textFillColor = correctedTextColor(textFillColor, Color::white);
- textStrokeColor = rendererToUse->resolveColor(styleToUse, CSSPropertyWebkitTextStrokeColor);
+ textStrokeColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebkitTextStrokeColor);
// Make the text stroke color legible against a white background
if (forceBackgroundToWhite)
textStrokeColor = correctedTextColor(textStrokeColor, Color::white);
- emphasisMarkColor = rendererToUse->resolveColor(styleToUse, CSSPropertyWebkitTextEmphasisColor);
+ emphasisMarkColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebkitTextEmphasisColor);
// Make the text stroke color legible against a white background
if (forceBackgroundToWhite)
@@ -586,21 +592,21 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
const ShadowList* selectionShadow = textShadow;
if (haveSelection) {
// Check foreground color first.
- Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
- if (foreground.isValid() && foreground != selectionFillColor && foreground != Color::transparent) {
+ Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor();
+ if (foreground != selectionFillColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
selectionFillColor = foreground;
}
- Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionEmphasisMarkColor();
- if (emphasisMarkForeground.isValid() && emphasisMarkForeground != selectionEmphasisMarkColor) {
+ Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black : renderer().selectionEmphasisMarkColor();
+ if (emphasisMarkForeground != selectionEmphasisMarkColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
selectionEmphasisMarkColor = emphasisMarkForeground;
}
- if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) {
+ if (RenderStyle* pseudoStyle = renderer().getCachedPseudoStyle(SELECTION)) {
// Text shadows are disabled when printing. http://crbug.com/258321
const ShadowList* shadow = (context->printing() || paintInfo.forceBlackText()) ? 0 : pseudoStyle->textShadow();
if (shadow != selectionShadow) {
@@ -616,7 +622,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
selectionStrokeWidth = strokeWidth;
}
- Color stroke = paintInfo.forceBlackText() ? Color::black : rendererToUse->resolveColor(pseudoStyle, CSSPropertyWebkitTextStrokeColor);
+ Color stroke = paintInfo.forceBlackText() ? Color::black : rendererToUse.resolveColor(pseudoStyle, CSSPropertyWebkitTextStrokeColor);
if (stroke != selectionStrokeColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
@@ -634,13 +640,10 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
combinedText->adjustTextOrigin(textOrigin, boxRect);
// 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
- // and composition underlines.
+ // and composition highlights.
if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
-
- if (containsComposition && !useCustomUnderlines) {
- paintCompositionBackground(context, boxOrigin, styleToUse, font,
- renderer()->frame()->inputMethodController().compositionStart(),
- renderer()->frame()->inputMethodController().compositionEnd());
+ if (containsComposition) {
+ paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, useCustomUnderlines);
}
paintDocumentMarkers(context, boxOrigin, styleToUse, font, true);
@@ -654,10 +657,10 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
int maximumLength;
StringView string;
if (!combinedText) {
- string = textRenderer()->text().createView();
+ string = textRenderer().text().createView();
if (static_cast<unsigned>(length) != string.length() || m_start)
string.narrow(m_start, length);
- maximumLength = textRenderer()->textLength() - m_start;
+ maximumLength = textRenderer().textLength() - m_start;
} else {
combinedText->getStringToRender(m_start, string, length);
maximumLength = length;
@@ -708,12 +711,19 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (combinedText)
context->concatCTM(rotation(boxRect, Clockwise));
- if (!paintSelectedTextSeparately || ePos <= sPos) {
- // FIXME: Truncate right-to-left text correctly.
- paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, 0, length, length, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
- } else {
- paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, ePos, sPos, length, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
+ int startOffset = 0;
+ int endOffset = length;
+ int paintRunLength = length;
+ if (combinedText) {
+ startOffset = 0;
+ endOffset = objectReplacementCharacterTextRun.length();
+ paintRunLength = endOffset;
+ } else if (paintSelectedTextSeparately && ePos > sPos) {
+ startOffset = ePos;
+ endOffset = sPos;
}
+ // FIXME: Truncate right-to-left text correctly.
+ paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, startOffset, endOffset, paintRunLength, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
if (combinedText)
context->concatCTM(rotation(boxRect, Counterclockwise));
@@ -735,7 +745,10 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (combinedText)
context->concatCTM(rotation(boxRect, Clockwise));
- paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, sPos, ePos, length, emphasisMarkTextOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
+ int startOffset = combinedText ? 0 : sPos;
+ int endOffset = combinedText ? objectReplacementCharacterTextRun.length() : ePos;
+ int paintRunLength = combinedText ? endOffset : length;
+ paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, startOffset, endOffset, paintRunLength, emphasisMarkTextOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
if (combinedText)
context->concatCTM(rotation(boxRect, Counterclockwise));
@@ -748,7 +761,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth);
if (combinedText)
context->concatCTM(rotation(boxRect, Clockwise));
- paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDecorationStyle(), textShadow);
+ paintDecoration(context, boxOrigin, textDecorations, textShadow);
if (combinedText)
context->concatCTM(rotation(boxRect, Counterclockwise));
}
@@ -756,28 +769,14 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (paintInfo.phase == PaintPhaseForeground) {
paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
+ // Paint custom underlines for compositions.
if (useCustomUnderlines) {
- const Vector<CompositionUnderline>& underlines = renderer()->frame()->inputMethodController().customCompositionUnderlines();
- size_t numUnderlines = underlines.size();
-
- for (size_t index = 0; index < numUnderlines; ++index) {
- const CompositionUnderline& underline = underlines[index];
-
- if (underline.endOffset <= start())
- // underline is completely before this run. This might be an underline that sits
- // before the first run we draw, or underlines that were within runs we skipped
- // due to truncation.
+ const Vector<CompositionUnderline>& underlines = renderer().frame()->inputMethodController().customCompositionUnderlines();
+ CompositionUnderlineRangeFilter filter(underlines, start(), end());
+ for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin(); it != filter.end(); ++it) {
+ if (it->color == Color::transparent)
continue;
-
- if (underline.startOffset <= end()) {
- // underline intersects this run. Paint it.
- paintCompositionUnderline(context, boxOrigin, underline);
- if (underline.endOffset > end() + 1)
- // underline also runs into the next run. Bail now, no more marker advancement.
- break;
- } else
- // underline is completely after this run, bail. A later run will paint it.
- break;
+ paintCompositionUnderline(context, boxOrigin, *it);
}
}
}
@@ -789,14 +788,14 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
{
int startPos, endPos;
- if (renderer()->selectionState() == RenderObject::SelectionInside) {
+ if (renderer().selectionState() == RenderObject::SelectionInside) {
startPos = 0;
- endPos = textRenderer()->textLength();
+ endPos = textRenderer().textLength();
} else {
- textRenderer()->selectionStartEnd(startPos, endPos);
- if (renderer()->selectionState() == RenderObject::SelectionStart)
- endPos = textRenderer()->textLength();
- else if (renderer()->selectionState() == RenderObject::SelectionEnd)
+ textRenderer().selectionStartEnd(startPos, endPos);
+ if (renderer().selectionState() == RenderObject::SelectionStart)
+ endPos = textRenderer().textLength();
+ else if (renderer().selectionState() == RenderObject::SelectionEnd)
startPos = 0;
}
@@ -822,8 +821,8 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
if (sPos >= ePos)
return;
- Color c = renderer()->selectionBackgroundColor();
- if (!c.isValid() || !c.alpha())
+ Color c = renderer().selectionBackgroundColor();
+ if (!c.alpha())
return;
// If the text color ends up being the same as the selection background, invert the selection
@@ -837,21 +836,21 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
// If the text is truncated, let the thing being painted in the truncation
// draw its own highlight.
int length = m_truncation != cNoTruncation ? m_truncation : m_len;
- StringView string = textRenderer()->text().createView();
+ StringView string = textRenderer().text().createView();
if (string.length() != static_cast<unsigned>(length) || m_start)
string.narrow(m_start, length);
StringBuilder charactersWithHyphen;
bool respectHyphen = ePos == length && hasHyphen();
- TextRun textRun = constructTextRun(style, font, string, textRenderer()->textLength() - m_start, respectHyphen ? &charactersWithHyphen : 0);
+ TextRun textRun = constructTextRun(style, font, string, textRenderer().textLength() - m_start, respectHyphen ? &charactersWithHyphen : 0);
if (respectHyphen)
ePos = textRun.length();
- LayoutUnit selectionBottom = root()->selectionBottom();
- LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock();
+ LayoutUnit selectionBottom = root().selectionBottom();
+ LayoutUnit selectionTop = root().selectionTopAdjustedForPrecedingBlock();
- int deltaY = roundToInt(renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop);
+ int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop);
int selHeight = max(0, roundToInt(selectionBottom - selectionTop));
FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
@@ -863,25 +862,34 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos, ePos);
}
-void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, int startPos, int endPos)
+unsigned InlineTextBox::underlinePaintStart(const CompositionUnderline& underline)
+{
+ return std::max(static_cast<unsigned>(m_start), underline.startOffset);
+}
+
+unsigned InlineTextBox::underlinePaintEnd(const CompositionUnderline& underline)
{
- int offset = m_start;
- int sPos = max(startPos - offset, 0);
- int ePos = min(endPos - offset, (int)m_len);
+ unsigned paintEnd = std::min(end() + 1, underline.endOffset); // end() points at the last char, not past it.
+ if (m_truncation != cNoTruncation)
+ paintEnd = std::min(paintEnd, static_cast<unsigned>(m_start + m_truncation));
+ return paintEnd;
+}
+void InlineTextBox::paintSingleCompositionBackgroundRun(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, Color backgroundColor, int startPos, int endPos)
+{
+ int sPos = std::max(startPos - m_start, 0);
+ int ePos = std::min(endPos - m_start, static_cast<int>(m_len));
if (sPos >= ePos)
return;
GraphicsContextStateSaver stateSaver(*context);
- Color c = Color(225, 221, 85);
+ updateGraphicsContext(context, backgroundColor, backgroundColor, 0); // Don't draw text at all!
- updateGraphicsContext(context, c, c, 0); // Don't draw text at all!
-
- int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+ int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
int selHeight = selectionHeight();
FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
- context->drawHighlightForText(font, constructTextRun(style, font), localOrigin, selHeight, c, sPos, ePos);
+ context->drawHighlightForText(font, constructTextRun(style, font), localOrigin, selHeight, backgroundColor, sPos, ePos);
}
static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorationStyle)
@@ -912,7 +920,18 @@ static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
{
// Compute the gap between the font and the underline. Use at least one
// pixel gap, if underline is thick then use a bigger gap.
- const int gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f));
+ int gap = 0;
+
+ // Underline position of zero means draw underline on Baseline Position,
+ // in Blink we need at least 1-pixel gap to adding following check.
+ // Positive underline Position means underline should be drawn above baselin e
+ // and negative value means drawing below baseline, negating the value as in Blink
+ // downward Y-increases.
+
+ if (fontMetrics.underlinePosition())
+ gap = -fontMetrics.underlinePosition();
+ else
+ gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f));
// FIXME: We support only horizontal text for now.
switch (underlinePosition) {
@@ -920,7 +939,7 @@ static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
return fontMetrics.ascent() + gap; // Position underline near the alphabetic baseline.
case TextUnderlinePositionUnder: {
// Position underline relative to the under edge of the lowest element's content box.
- const float offset = inlineTextBox->root()->maxLogicalTop() - inlineTextBox->logicalTop();
+ const float offset = inlineTextBox->root().maxLogicalTop() - inlineTextBox->logicalTop();
if (offset > 0)
return inlineTextBox->logicalHeight() + gap + offset;
return inlineTextBox->logicalHeight() + gap;
@@ -976,7 +995,7 @@ static void adjustStepToDecorationLength(float& step, float& controlPointDistanc
* |-----------|
* step
*/
-static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, FloatPoint& p2, float strokeThickness)
+static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint p1, FloatPoint p2, float strokeThickness)
{
context->adjustLineToPixelBoundaries(p1, p2, strokeThickness, context->strokeStyle());
@@ -1053,7 +1072,39 @@ static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, F
context->strokePath(path);
}
-void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, TextDecorationStyle decorationStyle, const ShadowList* shadowList)
+static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle)
+{
+ return decorationStyle == TextDecorationStyleDotted || decorationStyle == TextDecorationStyleDashed;
+}
+
+static bool shouldSetDecorationAntialias(TextDecorationStyle underline, TextDecorationStyle overline, TextDecorationStyle linethrough)
+{
+ return shouldSetDecorationAntialias(underline) || shouldSetDecorationAntialias(overline) || shouldSetDecorationAntialias(linethrough);
+}
+
+static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, float width, float doubleOffset, int wavyOffsetFactor,
+ RenderObject::AppliedTextDecoration decoration, float thickness, bool antialiasDecoration, bool isPrinting)
+{
+ context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style));
+ context->setStrokeColor(decoration.color);
+
+ switch (decoration.style) {
+ case TextDecorationStyleWavy:
+ strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * wavyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), thickness);
+ break;
+ case TextDecorationStyleDotted:
+ case TextDecorationStyleDashed:
+ context->setShouldAntialias(antialiasDecoration);
+ // Fall through
+ default:
+ context->drawLineForText(start, width, isPrinting);
+
+ if (decoration.style == TextDecorationStyleDouble)
+ context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting);
+ }
+}
+
+void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList)
{
GraphicsContextStateSaver stateSaver(*context);
@@ -1064,43 +1115,53 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
float width = m_logicalWidth;
if (m_truncation != cNoTruncation) {
- width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
+ width = toRenderText(renderer()).width(m_start, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
if (!isLeftToRightDirection())
localOrigin.move(m_logicalWidth - width, 0);
}
// Get the text decoration colors.
- Color underline, overline, linethrough;
- renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true);
+ RenderObject::AppliedTextDecoration underline, overline, linethrough;
+
+ renderer().getTextDecorations(deco, underline, overline, linethrough, true);
if (isFirstLineStyle())
- renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true, true);
+ renderer().getTextDecorations(deco, underline, overline, linethrough, true, true);
// Use a special function for underlines to get the positioning exactly right.
- bool isPrinting = textRenderer()->document().printing();
+ bool isPrinting = textRenderer().document().printing();
- bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.alpha() == 255);
+ bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.color.alpha() == 255);
- RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
+ RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
int baseline = styleToUse->fontMetrics().ascent();
size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
// Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px.
// Using computedFontSize should take care of zoom as well.
- const float textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f);
+
+ // Update Underline thickness, in case we have Faulty Font Metrics calculating underline thickness by old method.
+ float textDecorationThickness = styleToUse->fontMetrics().underlineThickness();
+ int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5);
+ if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHeightInt >> 1)))
+ textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f);
+
context->setStrokeThickness(textDecorationThickness);
- int extraOffset = 0;
+ bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, underline.style, linethrough.style)
+ && RenderBoxModelObject::shouldAntialiasLines(context);
+
+ float extraOffset = 0;
if (!linesAreOpaque && shadowCount > 1) {
FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2));
for (size_t i = shadowCount; i--; ) {
const ShadowData& s = shadowList->shadows()[i];
FloatRect shadowRect(localOrigin, FloatSize(width, baseline + 2));
shadowRect.inflate(s.blur());
- int shadowX = isHorizontal() ? s.x() : s.y();
- int shadowY = isHorizontal() ? s.y() : -s.x();
+ float shadowX = isHorizontal() ? s.x() : s.y();
+ float shadowY = isHorizontal() ? s.y() : -s.x();
shadowRect.move(shadowX, shadowY);
clipRect.unite(shadowRect);
- extraOffset = max(extraOffset, max(0, shadowY) + s.blur());
+ extraOffset = max(extraOffset, max(0.0f, shadowY) + s.blur());
}
context->clip(clipRect);
extraOffset += baseline + 2;
@@ -1116,60 +1177,24 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
extraOffset = 0;
}
const ShadowData& shadow = shadowList->shadows()[i];
- int shadowX = isHorizontal() ? shadow.x() : shadow.y();
- int shadowY = isHorizontal() ? shadow.y() : -shadow.x();
+ float shadowX = isHorizontal() ? shadow.x() : shadow.y();
+ float shadowY = isHorizontal() ? shadow.y() : -shadow.x();
context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow.blur(), shadow.color());
}
// Offset between lines - always non-zero, so lines never cross each other.
float doubleOffset = textDecorationThickness + 1.f;
- context->setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle));
+
if (deco & TextDecorationUnderline) {
- context->setStrokeColor(underline);
const int underlineOffset = computeUnderlineOffset(styleToUse->textUnderlinePosition(), styleToUse->fontMetrics(), this, textDecorationThickness);
- switch (decorationStyle) {
- case TextDecorationStyleWavy: {
- FloatPoint start(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset);
- FloatPoint end(localOrigin.x() + width, localOrigin.y() + underlineOffset + doubleOffset);
- strokeWavyTextDecoration(context, start, end, textDecorationThickness);
- break;
- }
- default:
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset), width, isPrinting);
-
- if (decorationStyle == TextDecorationStyleDouble)
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset), width, isPrinting);
- }
+ paintAppliedDecoration(context, localOrigin + FloatPoint(0, underlineOffset), width, doubleOffset, 1, underline, textDecorationThickness, antialiasDecoration, isPrinting);
}
if (deco & TextDecorationOverline) {
- context->setStrokeColor(overline);
- switch (decorationStyle) {
- case TextDecorationStyleWavy: {
- FloatPoint start(localOrigin.x(), localOrigin.y() - doubleOffset);
- FloatPoint end(localOrigin.x() + width, localOrigin.y() - doubleOffset);
- strokeWavyTextDecoration(context, start, end, textDecorationThickness);
- break;
- }
- default:
- context->drawLineForText(localOrigin, width, isPrinting);
- if (decorationStyle == TextDecorationStyleDouble)
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() - doubleOffset), width, isPrinting);
- }
+ paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPrinting);
}
if (deco & TextDecorationLineThrough) {
- context->setStrokeColor(linethrough);
- switch (decorationStyle) {
- case TextDecorationStyleWavy: {
- FloatPoint start(localOrigin.x(), localOrigin.y() + 2 * baseline / 3);
- FloatPoint end(localOrigin.x() + width, localOrigin.y() + 2 * baseline / 3);
- strokeWavyTextDecoration(context, start, end, textDecorationThickness);
- break;
- }
- default:
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting);
- if (decorationStyle == TextDecorationStyleDouble)
- context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + doubleOffset + 2 * baseline / 3), width, isPrinting);
- }
+ const float lineThroughOffset = 2 * baseline / 3;
+ paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThroughOffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antialiasDecoration, isPrinting);
}
}
}
@@ -1190,7 +1215,7 @@ static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM
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())
+ if (textRenderer().document().printing())
return;
if (m_truncation == cFullTruncation)
@@ -1216,7 +1241,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
endPosition = min<int>(endPosition, m_truncation);
// Calculate start & width
- int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+ int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
int selHeight = selectionHeight();
FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
TextRun run = constructTextRun(style, font);
@@ -1230,7 +1255,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
// display a toolTip. We don't do this for misspelling markers.
if (grammar) {
markerRect.move(-boxOrigin.x(), -boxOrigin.y());
- markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
+ markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
}
}
@@ -1242,7 +1267,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
// 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 = misspellingLineThickness;
- int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+ int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
int descent = logicalHeight() - baseline;
int underlineOffset;
if (descent <= (2 + lineThickness)) {
@@ -1259,7 +1284,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
{
// Use same y positioning and height as for selection, so that when the selection and this highlight are on
// the same word there are no pieces sticking out.
- int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+ int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
int selHeight = selectionHeight();
int sPos = max(marker->startOffset() - m_start, (unsigned)0);
@@ -1268,11 +1293,11 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
// Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates.
IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(x(), selectionTop()), selHeight, sPos, ePos));
- markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
+ markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
// Optionally highlight the text
- if (renderer()->frame()->editor().markedTextMatchesAreHighlighted()) {
+ if (renderer().frame()->editor().markedTextMatchesAreHighlighted()) {
Color color = marker->activeMatch() ?
RenderTheme::theme().platformActiveTextSearchHighlightColor() :
RenderTheme::theme().platformInactiveTextSearchHighlightColor();
@@ -1283,17 +1308,36 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
}
}
+void InlineTextBox::paintCompositionBackgrounds(GraphicsContext* pt, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, bool useCustomUnderlines)
+{
+ if (useCustomUnderlines) {
+ // Paint custom background highlights for compositions.
+ const Vector<CompositionUnderline>& underlines = renderer().frame()->inputMethodController().customCompositionUnderlines();
+ CompositionUnderlineRangeFilter filter(underlines, start(), end());
+ for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin(); it != filter.end(); ++it) {
+ if (it->backgroundColor == Color::transparent)
+ continue;
+ paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, it->backgroundColor, underlinePaintStart(*it), underlinePaintEnd(*it));
+ }
+
+ } else {
+ paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, RenderTheme::theme().platformDefaultCompositionBackgroundColor(),
+ renderer().frame()->inputMethodController().compositionStart(),
+ renderer().frame()->inputMethodController().compositionEnd());
+ }
+}
+
void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, bool background)
{
- if (!renderer()->node())
+ if (!renderer().node())
return;
- Vector<DocumentMarker*> markers = renderer()->document().markers()->markersFor(renderer()->node());
- Vector<DocumentMarker*>::const_iterator markerIt = markers.begin();
+ WillBeHeapVector<DocumentMarker*> markers = renderer().document().markers().markersFor(renderer().node());
+ WillBeHeapVector<DocumentMarker*>::const_iterator markerIt = markers.begin();
// Give any document markers that touch this run a chance to draw before the text has been drawn.
// Note end() points at the last char, not one past it like endOffset and ranges do.
- for ( ; markerIt != markers.end(); markerIt++) {
+ for ( ; markerIt != markers.end(); ++markerIt) {
DocumentMarker* marker = *markerIt;
// Paint either the background markers or the foreground markers, but not both
@@ -1343,33 +1387,21 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP
if (m_truncation == cFullTruncation)
return;
- float start = 0; // start of line to draw, relative to tx
- float width = m_logicalWidth; // how much line to draw
- bool useWholeWidth = true;
- unsigned paintStart = m_start;
- unsigned paintEnd = end() + 1; // end points at the last char, not past it
- if (paintStart <= underline.startOffset) {
- paintStart = underline.startOffset;
- useWholeWidth = false;
- 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);
- useWholeWidth = false;
- }
- if (m_truncation != cNoTruncation) {
- paintEnd = min(paintEnd, (unsigned)m_start + m_truncation);
- useWholeWidth = false;
- }
- if (!useWholeWidth) {
- width = toRenderText(renderer())->width(paintStart, paintEnd - paintStart, textPos() + start, isFirstLineStyle());
- }
+ unsigned paintStart = underlinePaintStart(underline);
+ unsigned paintEnd = underlinePaintEnd(underline);
+
+ // start of line to draw, relative to paintOffset.
+ float start = paintStart == static_cast<unsigned>(m_start) ? 0 :
+ toRenderText(renderer()).width(m_start, paintStart - m_start, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
+ // how much line to draw
+ float width = (paintStart == static_cast<unsigned>(m_start) && paintEnd == static_cast<unsigned>(end()) + 1) ? m_logicalWidth :
+ toRenderText(renderer()).width(paintStart, paintEnd - paintStart, textPos() + start, isLeftToRightDirection() ? LTR : RTL, 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(isFirstLineStyle())->fontMetrics().ascent();
+ int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
if (underline.thick && logicalHeight() - baseline >= 2)
lineThickness = 2;
@@ -1380,7 +1412,7 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP
ctx->setStrokeColor(underline.color);
ctx->setStrokeThickness(lineThickness);
- ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logicalHeight() - lineThickness), width, textRenderer()->document().printing());
+ ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logicalHeight() - lineThickness), width, textRenderer().document().printing());
}
int InlineTextBox::caretMinOffset() const
@@ -1399,7 +1431,7 @@ float InlineTextBox::textPos() const
// from the containing block edge in its measurement. textPos() should be consistent so the text are rendered in the same width.
if (logicalLeft() == 0)
return 0;
- return logicalLeft() - root()->logicalLeft();
+ return logicalLeft() - root().logicalLeft();
}
int InlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs) const
@@ -1414,8 +1446,8 @@ int InlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs
FontCachePurgePreventer fontCachePurgePreventer;
- RenderText* text = toRenderText(renderer());
- RenderStyle* style = text->style(isFirstLineStyle());
+ RenderText& text = toRenderText(renderer());
+ RenderStyle* style = text.style(isFirstLineStyle());
const Font& font = style->font();
return font.offsetForPosition(constructTextRun(style, font), lineOffset - logicalLeft(), includePartialGlyphs);
}
@@ -1430,8 +1462,8 @@ float InlineTextBox::positionForOffset(int offset) const
FontCachePurgePreventer fontCachePurgePreventer;
- RenderText* text = toRenderText(renderer());
- RenderStyle* styleToUse = text->style(isFirstLineStyle());
+ RenderText& text = toRenderText(renderer());
+ RenderStyle* styleToUse = text.style(isFirstLineStyle());
ASSERT(styleToUse);
const Font& font = styleToUse->font();
int from = !isLeftToRightDirection() ? offset - m_start : 0;
@@ -1468,8 +1500,7 @@ void InlineTextBox::characterWidths(Vector<float>& widths) const
{
FontCachePurgePreventer fontCachePurgePreventer;
- RenderText* textObj = textRenderer();
- RenderStyle* styleToUse = textObj->style(isFirstLineStyle());
+ RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle());
const Font& font = styleToUse->font();
TextRun textRun = constructTextRun(styleToUse, font);
@@ -1488,28 +1519,22 @@ void InlineTextBox::characterWidths(Vector<float>& widths) const
TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, StringBuilder* charactersWithHyphen) const
{
ASSERT(style);
+ ASSERT(textRenderer().text());
- RenderText* textRenderer = this->textRenderer();
- ASSERT(textRenderer);
- ASSERT(textRenderer->text());
-
- StringView string = textRenderer->text().createView();
+ StringView string = textRenderer().text().createView();
unsigned startPos = start();
unsigned length = len();
if (string.length() != length || startPos)
string.narrow(startPos, length);
- return constructTextRun(style, font, string, textRenderer->textLength() - startPos, charactersWithHyphen);
+ return constructTextRun(style, font, string, textRenderer().textLength() - startPos, charactersWithHyphen);
}
TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, StringView string, int maximumLength, StringBuilder* charactersWithHyphen) const
{
ASSERT(style);
- RenderText* textRenderer = this->textRenderer();
- ASSERT(textRenderer);
-
if (charactersWithHyphen) {
const AtomicString& hyphenString = style->hyphenString();
charactersWithHyphen->reserveCapacity(string.length() + hyphenString.length());
@@ -1521,10 +1546,11 @@ TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St
ASSERT(maximumLength >= static_cast<int>(string.length()));
- TextRun run(string, textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer->canUseSimpleFontCodePath());
+ TextRun run(string, textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer().canUseSimpleFontCodePath());
run.setTabSize(!style->collapseWhiteSpace(), style->tabSize());
+ run.setCharacterScanForCodePath(!textRenderer().canUseSimpleFontCodePath());
if (textRunNeedsRenderingContext(font))
- run.setRenderingContext(SVGTextRunRenderingContext::create(textRenderer));
+ run.setRenderingContext(SVGTextRunRenderingContext::create(&textRenderer()));
// Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
run.setCharactersLength(maximumLength);
@@ -1546,15 +1572,15 @@ const char* InlineTextBox::boxName() const
void InlineTextBox::showBox(int printedCharacters) const
{
- const RenderText* obj = toRenderText(renderer());
- String value = obj->text();
+ const RenderText& obj = toRenderText(renderer());
+ String value = obj.text();
value = value.substring(start(), len());
value.replaceWithLiteral('\\', "\\\\");
value.replaceWithLiteral('\n', "\\n");
printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
fputc(' ', stderr);
- printedCharacters = fprintf(stderr, "\t%s %p", obj->renderName(), obj);
+ printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj);
const int rendererCharacterOffset = 24;
for (; printedCharacters < rendererCharacterOffset; printedCharacters++)
fputc(' ', stderr);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.h b/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.h
index 27579edf5cb..5c0a6f0f338 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/InlineTextBox.h
@@ -25,7 +25,6 @@
#include "core/rendering/InlineBox.h"
#include "core/rendering/RenderText.h" // so textRenderer() can be inline
-#include "platform/graphics/GraphicsContext.h"
#include "platform/text/TextRun.h"
#include "wtf/Forward.h"
@@ -33,6 +32,7 @@ namespace WebCore {
struct CompositionUnderline;
class DocumentMarker;
+class GraphicsContext;
const unsigned short cNoTruncation = USHRT_MAX;
const unsigned short cFullTruncation = USHRT_MAX - 1;
@@ -43,7 +43,7 @@ Color correctedTextColor(Color textColor, Color backgroundColor);
class InlineTextBox : public InlineBox {
public:
- InlineTextBox(RenderObject* obj)
+ InlineTextBox(RenderObject& obj)
: InlineBox(obj)
, m_prevTextBox(0)
, m_nextTextBox(0)
@@ -72,7 +72,7 @@ public:
unsigned short truncation() { return m_truncation; }
- virtual void markDirty(bool dirty = true) OVERRIDE FINAL;
+ virtual void markDirty() OVERRIDE FINAL;
using InlineBox::hasHyphen;
using InlineBox::setHasHyphen;
@@ -94,8 +94,8 @@ public:
LayoutUnit logicalRightVisualOverflow() const { return logicalOverflowRect().maxX(); }
#ifndef NDEBUG
- virtual void showBox(int = 0) const;
- virtual const char* boxName() const;
+ virtual void showBox(int = 0) const OVERRIDE;
+ virtual const char* boxName() const OVERRIDE;
#endif
enum RotationDirection { Counterclockwise, Clockwise };
@@ -111,18 +111,18 @@ private:
public:
TextRun constructTextRunForInspector(RenderStyle*, const Font&) const;
- virtual FloatRect calculateBoundaries() const { return FloatRect(x(), y(), width(), height()); }
+ virtual FloatRect calculateBoundaries() const OVERRIDE { return FloatRect(x(), y(), width(), height()); }
virtual LayoutRect localSelectionRect(int startPos, int endPos);
bool isSelected(int startPos, int endPos) const;
void selectionStartEnd(int& sPos, int& ePos);
protected:
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
public:
- RenderText* textRenderer() const;
+ RenderText& textRenderer() const;
private:
virtual void deleteLine() OVERRIDE FINAL;
@@ -175,16 +175,22 @@ private:
unsigned short m_truncation; // Where to truncate when text overflow is applied. We use special constants to
// denote no truncation (the whole run paints) and full truncation (nothing paints at all).
+ unsigned underlinePaintStart(const CompositionUnderline&);
+ unsigned underlinePaintEnd(const CompositionUnderline&);
+
protected:
- void paintCompositionBackground(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, int startPos, int endPos);
+ void paintSingleCompositionBackgroundRun(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, Color backgroundColor, int startPos, int endPos);
+ void paintCompositionBackgrounds(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, bool useCustomUnderlines);
void paintDocumentMarkers(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, bool background);
void paintCompositionUnderline(GraphicsContext*, const FloatPoint& boxOrigin, const CompositionUnderline&);
+ // These functions both paint markers and update the DocumentMarker's renderedRect.
+ virtual void paintDocumentMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&, bool grammar);
+ virtual void paintTextMatchMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&);
+
private:
- void paintDecoration(GraphicsContext*, const FloatPoint& boxOrigin, TextDecoration, TextDecorationStyle, const ShadowList*);
+ void paintDecoration(GraphicsContext*, const FloatPoint& boxOrigin, TextDecoration, const ShadowList*);
void paintSelection(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, Color textColor);
- void paintDocumentMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&, bool grammar);
- void paintTextMatchMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&);
TextRun::ExpansionBehavior expansionBehavior() const
{
@@ -195,7 +201,7 @@ private:
DEFINE_INLINE_BOX_TYPE_CASTS(InlineTextBox);
-inline RenderText* InlineTextBox::textRenderer() const
+inline RenderText& InlineTextBox::textRenderer() const
{
return toRenderText(renderer());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayerPaintingInfo.h b/chromium/third_party/WebKit/Source/core/rendering/LayerPaintingInfo.h
index b9af0314271..421e61b2f09 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LayerPaintingInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/LayerPaintingInfo.h
@@ -74,13 +74,12 @@ typedef unsigned PaintLayerFlags;
struct LayerPaintingInfo {
LayerPaintingInfo(RenderLayer* inRootLayer, const LayoutRect& inDirtyRect,
PaintBehavior inPaintBehavior, const LayoutSize& inSubPixelAccumulation,
- RenderObject* inPaintingRoot = 0, RenderRegion*inRegion = 0,
+ RenderObject* inPaintingRoot = 0,
OverlapTestRequestMap* inOverlapTestRequests = 0)
: rootLayer(inRootLayer)
, paintingRoot(inPaintingRoot)
, paintDirtyRect(inDirtyRect)
, subPixelAccumulation(inSubPixelAccumulation)
- , region(inRegion)
, overlapTestRequests(inOverlapTestRequests)
, paintBehavior(inPaintBehavior)
, clipToDirtyRect(true)
@@ -89,7 +88,6 @@ struct LayerPaintingInfo {
RenderObject* paintingRoot; // only paint descendants of this object
LayoutRect paintDirtyRect; // relative to rootLayer;
LayoutSize subPixelAccumulation;
- RenderRegion* region; // May be null.
OverlapTestRequestMap* overlapTestRequests; // May be null.
PaintBehavior paintBehavior;
bool clipToDirtyRect;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.cpp b/chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.cpp
deleted file mode 100644
index a57c53c11d1..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2013 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 "core/rendering/LayoutIndicator.h"
-
-namespace WebCore {
-
-#ifndef NDEBUG
-
-size_t LayoutIndicator::s_inLayout = 0;
-
-#endif
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.h b/chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.h
deleted file mode 100644
index 6337da949cf..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutIndicator.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2013 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 LayoutIndicator_h
-#define LayoutIndicator_h
-
-#include "wtf/Assertions.h"
-
-namespace WebCore {
-
-#ifndef NDEBUG
-
-class LayoutIndicator {
-public:
- LayoutIndicator() { ++s_inLayout; }
- ~LayoutIndicator() { --s_inLayout; }
-
- static bool inLayout() { return s_inLayout; }
-
-private:
- static size_t s_inLayout;
-};
-
-#else
-
-class LayoutIndicator {
-public:
- LayoutIndicator() { }
- ~LayoutIndicator() { }
-};
-
-#endif
-
-}
-
-#endif // LayoutIndicator_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.cpp b/chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.cpp
deleted file mode 100644
index 90c50d32884..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2013, 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 "core/rendering/LayoutRectRecorder.h"
-
-#include "core/rendering/RenderObject.h"
-
-namespace WebCore {
-
-bool LayoutRectRecorder::shouldRecordLayoutRects()
-{
- bool isTracing;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), &isTracing);
- return RuntimeEnabledFeatures::repaintAfterLayoutEnabled() || isTracing;
-}
-
-LayoutRectRecorder::LayoutRectRecorder(RenderObject& object, bool skipRecording)
- : m_object(object)
- , m_skipRecording(skipRecording)
-{
- if (!shouldRecordLayoutRects())
- return;
- if (m_skipRecording)
- return;
-
- if (!m_object.layoutDidGetCalled())
- m_object.setOldRepaintRect(m_object.clippedOverflowRectForRepaint(m_object.containerForRepaint()));
-
- // If should do repaint was set previously make sure we don't accidentally unset it.
- if (!m_object.shouldDoFullRepaintAfterLayout())
- m_object.setShouldDoFullRepaintAfterLayout(m_object.selfNeedsLayout());
-
- m_object.setLayoutDidGetCalled(true);
-}
-
-LayoutRectRecorder::~LayoutRectRecorder()
-{
- if (!shouldRecordLayoutRects())
- return;
- if (m_skipRecording)
- return;
-
- // Note, we don't store the repaint container because it can change during layout.
- m_object.setNewRepaintRect(m_object.clippedOverflowRectForRepaint(m_object.containerForRepaint()));
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.h b/chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.h
deleted file mode 100644
index c92eb5efc90..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutRectRecorder.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2013, 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 LayoutRectRecorder_h
-#define LayoutRectRecorder_h
-
-#include "platform/geometry/LayoutRect.h"
-#include "wtf/Noncopyable.h"
-
-namespace WebCore {
-
-class RenderLayerModelObject;
-class RenderObject;
-
-class LayoutRectRecorder {
- WTF_MAKE_NONCOPYABLE(LayoutRectRecorder);
-public:
- LayoutRectRecorder(RenderObject&, bool skipRecording = false);
- ~LayoutRectRecorder();
-
- static bool shouldRecordLayoutRects();
-
-private:
- RenderObject& m_object;
- bool m_skipRecording;
-};
-
-} // namespace WebCore
-
-#endif // LayoutRectRecorder_h
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.cpp b/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.cpp
index fc06e0b3b21..046222e8729 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderObject.h"
namespace WebCore {
@@ -39,9 +40,13 @@ LayoutRepainter::LayoutRepainter(RenderObject& object, bool checkForRepaint)
return;
if (m_checkForRepaint) {
- m_repaintContainer = m_object.containerForRepaint();
- m_oldBounds = m_object.clippedOverflowRectForRepaint(m_repaintContainer);
- m_oldOutlineBox = m_object.outlineBoundsForRepaint(m_repaintContainer);
+ m_repaintContainer = m_object.containerForPaintInvalidation();
+ {
+ // Hits in compositing/video/video-controls-layer-creation.html
+ DisableCompositingQueryAsserts disabler;
+ m_oldBounds = m_object.boundsRectForPaintInvalidation(m_repaintContainer);
+ m_oldOffset = RenderLayer::positionFromPaintInvalidationContainer(&m_object, m_repaintContainer);
+ }
}
}
@@ -50,7 +55,10 @@ bool LayoutRepainter::repaintAfterLayout()
if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
return false;
- return m_checkForRepaint ? m_object.repaintAfterLayoutIfNeeded(m_repaintContainer, m_object.selfNeedsLayout(), m_oldBounds, m_oldOutlineBox) : false;
+ // Hits in compositing/video/video-controls-layer-creation.html
+ DisableCompositingQueryAsserts disabler;
+
+ return m_checkForRepaint ? m_object.invalidatePaintAfterLayoutIfNeeded(m_repaintContainer, m_object.selfNeedsLayout(), m_oldBounds, m_oldOffset) : false;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.h b/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.h
index 55fdd1eb23a..30a3aef00c5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/LayoutRepainter.h
@@ -44,10 +44,10 @@ public:
private:
RenderObject& m_object;
- RenderLayerModelObject* m_repaintContainer;
+ const RenderLayerModelObject* m_repaintContainer;
// We store these values as LayoutRects, but the final invalidations will be pixel snapped
LayoutRect m_oldBounds;
- LayoutRect m_oldOutlineBox;
+ LayoutPoint m_oldOffset;
bool m_checkForRepaint;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutState.cpp b/chromium/third_party/WebKit/Source/core/rendering/LayoutState.cpp
index 940f21ccc16..45c0d76f1ac 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutState.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/LayoutState.cpp
@@ -33,27 +33,42 @@
namespace WebCore {
-LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo)
- : m_columnInfo(columnInfo)
- , m_lineGrid(0)
- , m_next(prev)
- , m_shapeInsideInfo(0)
-#ifndef NDEBUG
- , m_renderer(renderer)
+LayoutState::LayoutState(LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, RenderView& view)
+ : m_clipped(false)
+ , m_isPaginated(pageLogicalHeight)
+ , m_pageLogicalHeightChanged(pageLogicalHeightChanged)
+ , m_cachedOffsetsEnabled(true)
+#if ASSERT_ENABLED
+ , m_layoutDeltaXSaturated(false)
+ , m_layoutDeltaYSaturated(false)
#endif
+ , m_columnInfo(0)
+ , m_next(0)
+ , m_pageLogicalHeight(pageLogicalHeight)
+ , m_renderer(view)
{
- ASSERT(m_next);
+ ASSERT(!view.layoutState());
+ view.pushLayoutState(*this);
+}
- bool fixed = renderer->isOutOfFlowPositioned() && renderer->style()->position() == FixedPosition;
+LayoutState::LayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo)
+ : m_columnInfo(columnInfo)
+ , m_next(renderer.view()->layoutState())
+ , m_renderer(renderer)
+{
+ renderer.view()->pushLayoutState(*this);
+ m_cachedOffsetsEnabled = m_next->m_cachedOffsetsEnabled && renderer.supportsLayoutStateCachedOffsets();
+ bool fixed = renderer.isOutOfFlowPositioned() && renderer.style()->position() == FixedPosition;
if (fixed) {
// FIXME: This doesn't work correctly with transforms.
- FloatPoint fixedOffset = renderer->view()->localToAbsolute(FloatPoint(), IsFixed);
+ FloatPoint fixedOffset = renderer.view()->localToAbsolute(FloatPoint(), IsFixed);
m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
- } else
- m_paintOffset = prev->m_paintOffset + offset;
+ } else {
+ m_paintOffset = m_next->m_paintOffset + offset;
+ }
- if (renderer->isOutOfFlowPositioned() && !fixed) {
- if (RenderObject* container = renderer->container()) {
+ if (renderer.isOutOfFlowPositioned() && !fixed) {
+ if (RenderObject* container = renderer.container()) {
if (container->isInFlowPositioned() && container->isRenderInline())
m_paintOffset += toRenderInline(container)->offsetForInFlowPositionedInline(renderer);
}
@@ -61,15 +76,17 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz
m_layoutOffset = m_paintOffset;
- if (renderer->isInFlowPositioned() && renderer->hasLayer())
- m_paintOffset += renderer->layer()->offsetForInFlowPosition();
+ if (renderer.isInFlowPositioned() && renderer.hasLayer())
+ m_paintOffset += renderer.layer()->offsetForInFlowPosition();
- m_clipped = !fixed && prev->m_clipped;
+ m_clipped = !fixed && m_next->m_clipped;
if (m_clipped)
- m_clipRect = prev->m_clipRect;
+ m_clipRect = m_next->m_clipRect;
+
+ if (renderer.hasOverflowClip()) {
+ LayoutSize deltaSize = RuntimeEnabledFeatures::repaintAfterLayoutEnabled() ? LayoutSize() : renderer.view()->layoutDelta();
- if (renderer->hasOverflowClip()) {
- LayoutRect clipRect(toPoint(m_paintOffset) + renderer->view()->layoutDelta(), renderer->cachedSizeForOverflowClip());
+ LayoutRect clipRect(toPoint(m_paintOffset) + deltaSize, renderer.cachedSizeForOverflowClip());
if (m_clipped)
m_clipRect.intersect(clipRect);
else {
@@ -77,17 +94,18 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz
m_clipped = true;
}
- m_paintOffset -= renderer->scrolledContentOffset();
+ m_paintOffset -= renderer.scrolledContentOffset();
}
// If we establish a new page height, then cache the offset to the top of the first page.
// We can compare this later on to figure out what part of the page we're actually on,
- if (pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread()) {
+ if (pageLogicalHeight || m_columnInfo || renderer.isRenderFlowThread()) {
m_pageLogicalHeight = pageLogicalHeight;
- bool isFlipped = renderer->style()->isFlippedBlocksWritingMode();
- m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer->borderLeft() + renderer->paddingLeft() : renderer->borderRight() + renderer->paddingRight()),
- m_layoutOffset.height() + (!isFlipped ? renderer->borderTop() + renderer->paddingTop() : renderer->borderBottom() + renderer->paddingBottom()));
+ bool isFlipped = renderer.style()->isFlippedBlocksWritingMode();
+ m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer.borderLeft() + renderer.paddingLeft() : renderer.borderRight() + renderer.paddingRight()),
+ m_layoutOffset.height() + (!isFlipped ? renderer.borderTop() + renderer.paddingTop() : renderer.borderBottom() + renderer.paddingBottom()));
m_pageLogicalHeightChanged = pageLogicalHeightChanged;
+ m_isPaginated = true;
} else {
// If we don't establish a new page height, then propagate the old page height and offset down.
m_pageLogicalHeight = m_next->m_pageLogicalHeight;
@@ -96,59 +114,62 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz
// Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
// writing mode roots.
- if (renderer->isUnsplittableForPagination())
+ if (renderer.isUnsplittableForPagination()) {
m_pageLogicalHeight = 0;
+ m_isPaginated = false;
+ } else {
+ m_isPaginated = m_pageLogicalHeight || m_next->m_columnInfo || renderer.flowThreadContainingBlock();
+ }
}
- // Propagate line grid information.
- propagateLineGridInfo(renderer);
-
if (!m_columnInfo)
m_columnInfo = m_next->m_columnInfo;
- if (renderer->isRenderBlock()) {
- const RenderBlock* renderBlock = toRenderBlock(renderer);
- m_shapeInsideInfo = renderBlock->shapeInsideInfo();
- if (!m_shapeInsideInfo && m_next->m_shapeInsideInfo && renderBlock->allowsShapeInsideInfoSharing(m_next->m_shapeInsideInfo->owner()))
- m_shapeInsideInfo = m_next->m_shapeInsideInfo;
- }
-
- m_layoutDelta = m_next->m_layoutDelta;
-#if !ASSERT_DISABLED
- m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated;
- m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated;
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ m_layoutDelta = m_next->m_layoutDelta;
+#if ASSERT_ENABLED
+ m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated;
+ m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated;
#endif
-
- m_isPaginated = m_pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread();
-
- if (lineGrid() && renderer->hasColumns() && renderer->style()->hasInlineColumnAxis())
- computeLineGridPaginationOrigin(renderer);
-
- // If we have a new grid to track, then add it to our set.
- if (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isRenderBlockFlow())
- establishLineGrid(toRenderBlockFlow(renderer));
+ }
// FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
-LayoutState::LayoutState(RenderObject* root)
+inline static bool shouldDisableLayoutStateForSubtree(RenderObject& renderer)
+{
+ RenderObject* object = &renderer;
+ while (object) {
+ if (object->supportsLayoutStateCachedOffsets())
+ return true;
+ object = object->container();
+ }
+ return false;
+}
+
+LayoutState::LayoutState(RenderObject& root)
: m_clipped(false)
, m_isPaginated(false)
, m_pageLogicalHeightChanged(false)
-#if !ASSERT_DISABLED
+ , m_cachedOffsetsEnabled(shouldDisableLayoutStateForSubtree(root))
+#if ASSERT_ENABLED
, m_layoutDeltaXSaturated(false)
, m_layoutDeltaYSaturated(false)
#endif
, m_columnInfo(0)
- , m_lineGrid(0)
- , m_next(0)
- , m_shapeInsideInfo(0)
+ , m_next(root.view()->layoutState())
, m_pageLogicalHeight(0)
-#ifndef NDEBUG
, m_renderer(root)
-#endif
{
- RenderObject* container = root->container();
+ // FIXME: Why does RenderTableSection create this wonky LayoutState?
+ ASSERT(!m_next || root.isTableSection());
+ // We'll end up pushing in RenderView itself, so don't bother adding it.
+ if (root.isRenderView())
+ return;
+
+ root.view()->pushLayoutState(*this);
+
+ RenderObject* container = root.container();
FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), UseTransforms);
m_paintOffset = LayoutSize(absContentPoint.x(), absContentPoint.y());
@@ -160,14 +181,12 @@ LayoutState::LayoutState(RenderObject* root)
}
}
-void* LayoutState::operator new(size_t sz)
-{
- return partitionAlloc(Partitions::getRenderingPartition(), sz);
-}
-
-void LayoutState::operator delete(void* ptr)
+LayoutState::~LayoutState()
{
- partitionFree(ptr);
+ if (m_renderer.view()->layoutState()) {
+ ASSERT(m_renderer.view()->layoutState() == this);
+ m_renderer.view()->popLayoutState();
+ }
}
void LayoutState::clearPaginationInformation()
@@ -177,98 +196,18 @@ void LayoutState::clearPaginationInformation()
m_columnInfo = m_next->m_columnInfo;
}
-LayoutUnit LayoutState::pageLogicalOffset(RenderBox* child, LayoutUnit childLogicalOffset) const
+LayoutUnit LayoutState::pageLogicalOffset(const RenderBox& child, const LayoutUnit& childLogicalOffset) const
{
- if (child->isHorizontalWritingMode())
+ if (child.isHorizontalWritingMode())
return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height();
return m_layoutOffset.width() + childLogicalOffset - m_pageOffset.width();
}
-void LayoutState::addForcedColumnBreak(RenderBox* child, LayoutUnit childLogicalOffset)
+void LayoutState::addForcedColumnBreak(const RenderBox& child, const LayoutUnit& childLogicalOffset)
{
if (!m_columnInfo || m_columnInfo->columnHeight())
return;
m_columnInfo->addForcedBreak(pageLogicalOffset(child, childLogicalOffset));
}
-void LayoutState::propagateLineGridInfo(RenderBox* renderer)
-{
- // Disable line grids for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
- // writing mode roots.
- if (!m_next || renderer->isUnsplittableForPagination())
- return;
-
- m_lineGrid = m_next->m_lineGrid;
- m_lineGridOffset = m_next->m_lineGridOffset;
- m_lineGridPaginationOrigin = m_next->m_lineGridPaginationOrigin;
-}
-
-void LayoutState::establishLineGrid(RenderBlockFlow* block)
-{
- // First check to see if this grid has been established already.
- if (m_lineGrid) {
- if (m_lineGrid->style()->lineGrid() == block->style()->lineGrid())
- return;
- RenderBlockFlow* currentGrid = m_lineGrid;
- for (LayoutState* currentState = m_next; currentState; currentState = currentState->m_next) {
- if (currentState->m_lineGrid == currentGrid)
- continue;
- currentGrid = currentState->m_lineGrid;
- if (!currentGrid)
- break;
- if (currentGrid->style()->lineGrid() == block->style()->lineGrid()) {
- m_lineGrid = currentGrid;
- m_lineGridOffset = currentState->m_lineGridOffset;
- return;
- }
- }
- }
-
- // We didn't find an already-established grid with this identifier. Our render object establishes the grid.
- m_lineGrid = block;
- m_lineGridOffset = m_layoutOffset;
-}
-
-void LayoutState::computeLineGridPaginationOrigin(RenderBox* renderer)
-{
- // We need to cache a line grid pagination origin so that we understand how to reset the line grid
- // at the top of each column.
- // Get the current line grid and offset.
- if (!lineGrid() || lineGrid()->style()->writingMode() != renderer->style()->writingMode())
- return;
-
- // Get the hypothetical line box used to establish the grid.
- RootInlineBox* lineGridBox = lineGrid()->lineGridBox();
- if (!lineGridBox)
- return;
-
- bool isHorizontalWritingMode = lineGrid()->isHorizontalWritingMode();
-
- LayoutUnit lineGridBlockOffset = isHorizontalWritingMode ? lineGridOffset().height() : lineGridOffset().width();
-
- // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple
- // as established by the line box.
- // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume
- // the grid should honor line-box-contain.
- LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading();
- if (!gridLineHeight)
- return;
-
- LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading();
-
- if (isPaginated() && pageLogicalHeight()) {
- LayoutUnit pageLogicalTop = renderer->isHorizontalWritingMode() ? m_pageOffset.height() : m_pageOffset.width();
- if (pageLogicalTop > firstLineTopWithLeading) {
- // Shift to the next highest line grid multiple past the page logical top. Cache the delta
- // between this new value and the page logical top as the pagination origin.
- LayoutUnit remainder = roundToInt(pageLogicalTop - firstLineTopWithLeading) % roundToInt(gridLineHeight);
- LayoutUnit paginationDelta = gridLineHeight - remainder;
- if (isHorizontalWritingMode)
- m_lineGridPaginationOrigin.setHeight(paginationDelta);
- else
- m_lineGridPaginationOrigin.setWidth(paginationDelta);
- }
- }
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LayoutState.h b/chromium/third_party/WebKit/Source/core/rendering/LayoutState.h
index 16aa5b6ef36..8279bd3995b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LayoutState.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/LayoutState.h
@@ -33,89 +33,95 @@
namespace WebCore {
-class RenderBlockFlow;
+class ForceHorriblySlowRectMapping;
class RenderBox;
class RenderObject;
-class RenderFlowThread;
-class ShapeInsideInfo;
+class RenderView;
class LayoutState {
WTF_MAKE_NONCOPYABLE(LayoutState);
public:
- LayoutState()
- : m_clipped(false)
- , m_isPaginated(false)
- , m_pageLogicalHeightChanged(false)
-#if !ASSERT_DISABLED
- , m_layoutDeltaXSaturated(false)
- , m_layoutDeltaYSaturated(false)
-#endif
- , m_columnInfo(0)
- , m_lineGrid(0)
- , m_next(0)
- , m_shapeInsideInfo(0)
- , m_pageLogicalHeight(0)
-#ifndef NDEBUG
- , m_renderer(0)
-#endif
- {
- }
+ // Constructor for root LayoutState created by RenderView
+ LayoutState(LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, RenderView&);
+ // Constructor for sub-tree Layout and RenderTableSections
+ explicit LayoutState(RenderObject& root);
- LayoutState(LayoutState*, RenderBox*, const LayoutSize& offset, LayoutUnit pageHeight, bool pageHeightChanged, ColumnInfo*);
- LayoutState(RenderObject*);
+ LayoutState(RenderBox&, const LayoutSize& offset, LayoutUnit pageLogicalHeight = 0, bool pageHeightLogicalChanged = false, ColumnInfo* = 0);
- // LayoutState is allocated out of the rendering partition.
- void* operator new(size_t);
- void operator delete(void*);
+ ~LayoutState();
void clearPaginationInformation();
- bool isPaginatingColumns() const { return m_columnInfo && m_columnInfo->paginationUnit() == ColumnInfo::Column; }
+ bool isPaginatingColumns() const { return m_columnInfo; }
bool isPaginated() const { return m_isPaginated; }
+ bool isClipped() const { return m_clipped; }
// 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(RenderBox*, LayoutUnit childLogicalOffset) const;
+ LayoutUnit pageLogicalOffset(const RenderBox&, const LayoutUnit& childLogicalOffset) const;
- void addForcedColumnBreak(RenderBox*, LayoutUnit childLogicalOffset);
+ void addForcedColumnBreak(const RenderBox&, const LayoutUnit& childLogicalOffset);
+ void addLayoutDelta(const LayoutSize& delta)
+ {
+ m_layoutDelta += delta;
+#if ASSERT_ENABLED
+ m_layoutDeltaXSaturated |= m_layoutDelta.width() == LayoutUnit::max() || m_layoutDelta.width() == LayoutUnit::min();
+ m_layoutDeltaYSaturated |= m_layoutDelta.height() == LayoutUnit::max() || m_layoutDelta.height() == LayoutUnit::min();
+#endif
+ }
+
+ void setColumnInfo(ColumnInfo* columnInfo) { m_columnInfo = columnInfo; }
+
+ const LayoutSize& layoutOffset() const { return m_layoutOffset; }
+ const LayoutSize& layoutDelta() const { return m_layoutDelta; }
+ const LayoutSize& pageOffset() const { return m_pageOffset; }
LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
- RenderBlockFlow* lineGrid() const { return m_lineGrid; }
- LayoutSize lineGridOffset() const { return m_lineGridOffset; }
- LayoutSize lineGridPaginationOrigin() const { return m_lineGridPaginationOrigin; }
+ LayoutState* next() const { return m_next; }
- LayoutSize layoutOffset() const { return m_layoutOffset; }
+ bool needsBlockDirectionLocationSetBeforeLayout() const { return m_isPaginated && m_pageLogicalHeight; }
- bool needsBlockDirectionLocationSetBeforeLayout() const { return m_lineGrid || (m_isPaginated && m_pageLogicalHeight); }
+ ColumnInfo* columnInfo() const { return m_columnInfo; }
- ShapeInsideInfo* shapeInsideInfo() const { return m_shapeInsideInfo; }
+ bool cachedOffsetsEnabled() const { return m_cachedOffsetsEnabled; }
-#ifndef NDEBUG
- RenderObject* renderer() const { return m_renderer; }
+ const LayoutRect& clipRect() const
+ {
+ ASSERT(m_cachedOffsetsEnabled);
+ return m_clipRect;
+ }
+ const LayoutSize& paintOffset() const
+ {
+ ASSERT(m_cachedOffsetsEnabled);
+ return m_paintOffset;
+ }
+
+
+ RenderObject& renderer() const { return m_renderer; }
+
+#if ASSERT_ENABLED
+ bool layoutDeltaXSaturated() const { return m_layoutDeltaXSaturated; }
+ bool layoutDeltaYSaturated() const { return m_layoutDeltaYSaturated; }
#endif
-private:
- void propagateLineGridInfo(RenderBox*);
- void establishLineGrid(RenderBlockFlow*);
- void computeLineGridPaginationOrigin(RenderBox*);
+private:
+ friend class ForceHorriblySlowRectMapping;
-public:
// Do not add anything apart from bitfields until after m_columnInfo. See https://bugs.webkit.org/show_bug.cgi?id=100173
bool m_clipped:1;
bool m_isPaginated:1;
// If our page height has changed, this will force all blocks to relayout.
bool m_pageLogicalHeightChanged:1;
-#if !ASSERT_DISABLED
+
+ bool m_cachedOffsetsEnabled:1;
+#if ASSERT_ENABLED
bool m_layoutDeltaXSaturated:1;
bool m_layoutDeltaYSaturated:1;
#endif
// If the enclosing pagination model is a column model, then this will store column information for easy retrieval/manipulation.
ColumnInfo* m_columnInfo;
- // The current line grid that we're snapping to and the offset of the start of the grid.
- RenderBlockFlow* m_lineGrid;
LayoutState* m_next;
- ShapeInsideInfo* m_shapeInsideInfo;
// FIXME: Distinguish between the layout clip rect and the paint clip rect which may be larger,
// e.g., because of composited scrolling.
@@ -134,12 +140,8 @@ public:
LayoutUnit m_pageLogicalHeight;
// The offset of the start of the first page in the nearest enclosing pagination model.
LayoutSize m_pageOffset;
- LayoutSize m_lineGridOffset;
- LayoutSize m_lineGridPaginationOrigin;
-#ifndef NDEBUG
- RenderObject* m_renderer;
-#endif
+ RenderObject& m_renderer;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.cpp b/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.cpp
index 20926a576d5..3dfe9b65afc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.cpp
@@ -63,9 +63,9 @@ RenderBox* OrderIterator::next()
m_isReset = false;
}
- m_currentChild = firstChildBox();
+ m_currentChild = m_containerBox->firstChildBox();
} else {
- m_currentChild = nextSiblingBox();
+ m_currentChild = m_currentChild->nextSiblingBox();
}
} while (!m_currentChild || m_currentChild->style()->order() != *m_orderValuesIterator);
@@ -79,38 +79,11 @@ void OrderIterator::reset()
m_isReset = true;
}
-RenderBox* OrderIterator::firstChildBox()
-{
- if (m_children.isEmpty())
- return m_containerBox->firstChildBox();
-
- m_childIndex = 0;
- return m_children[0];
-}
-
-RenderBox* OrderIterator::nextSiblingBox()
-{
- if (m_children.isEmpty())
- return m_currentChild->nextSiblingBox();
-
- if (m_childIndex >= m_children.size() - 1)
- return 0;
-
- return m_children[++m_childIndex];
-}
-
OrderIteratorPopulator::~OrderIteratorPopulator()
{
m_iterator.reset();
}
-void OrderIteratorPopulator::storeChild(RenderBox* child)
-{
- m_iterator.m_children.append(child);
-
- collectChild(child);
-}
-
void OrderIteratorPopulator::collectChild(const RenderBox* child)
{
m_iterator.m_orderValues.insert(child->style()->order());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.h b/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.h
index 2a019150a6b..d0ef6c04c8e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/OrderIterator.h
@@ -53,15 +53,9 @@ public:
void reset();
private:
- RenderBox* firstChildBox();
- RenderBox* nextSiblingBox();
-
- // If |m_children| is not empty, we will use it to iterate over this fixed subset.
const RenderBox* m_containerBox;
- Vector<RenderBox*> m_children;
RenderBox* m_currentChild;
- size_t m_childIndex;
typedef std::set<int> OrderValues;
OrderValues m_orderValues;
@@ -79,7 +73,6 @@ public:
~OrderIteratorPopulator();
- void storeChild(RenderBox*);
void collectChild(const RenderBox*);
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/Pagination.cpp b/chromium/third_party/WebKit/Source/core/rendering/Pagination.cpp
deleted file mode 100644
index 26822b03988..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/Pagination.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * 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"
-#include "core/rendering/Pagination.h"
-
-#include "core/rendering/style/RenderStyle.h"
-
-namespace WebCore {
-
-void Pagination::setStylesForPaginationMode(Mode paginationMode, RenderStyle* style)
-{
- if (paginationMode == Unpaginated)
- return;
-
- switch (paginationMode) {
- case LeftToRightPaginated:
- style->setColumnAxis(HorizontalColumnAxis);
- if (style->isHorizontalWritingMode())
- style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
- else
- style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
- break;
- case RightToLeftPaginated:
- style->setColumnAxis(HorizontalColumnAxis);
- if (style->isHorizontalWritingMode())
- style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
- else
- style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
- break;
- case TopToBottomPaginated:
- style->setColumnAxis(VerticalColumnAxis);
- if (style->isHorizontalWritingMode())
- style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
- else
- style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
- break;
- case BottomToTopPaginated:
- style->setColumnAxis(VerticalColumnAxis);
- if (style->isHorizontalWritingMode())
- style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
- else
- style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
- break;
- case Unpaginated:
- ASSERT_NOT_REACHED();
- break;
- }
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/Pagination.h b/chromium/third_party/WebKit/Source/core/rendering/Pagination.h
deleted file mode 100644
index ce695f7bf14..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/Pagination.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 Pagination_h
-#define Pagination_h
-
-namespace WebCore {
-
-class RenderStyle;
-
-struct Pagination {
- enum Mode { Unpaginated, LeftToRightPaginated, RightToLeftPaginated, TopToBottomPaginated, BottomToTopPaginated };
-
- Pagination()
- : mode(Unpaginated)
- , behavesLikeColumns(false)
- , pageLength(0)
- , gap(0)
- {
- };
-
- bool operator==(const Pagination& other) const
- {
- return mode == other.mode && behavesLikeColumns == other.behavesLikeColumns && pageLength == other.pageLength && gap == other.gap;
- }
-
- bool operator!=(const Pagination& other) const
- {
- return mode != other.mode || behavesLikeColumns != other.behavesLikeColumns || pageLength != other.pageLength || gap != other.gap;
- }
-
- Mode mode;
- bool behavesLikeColumns;
- unsigned pageLength;
- unsigned gap;
-
- static void setStylesForPaginationMode(Mode, RenderStyle*);
-};
-
-} // namespace WebCore
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/PaintInfo.h b/chromium/third_party/WebKit/Source/core/rendering/PaintInfo.h
index be99ec39407..50b6463a1a4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/PaintInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/PaintInfo.h
@@ -40,7 +40,6 @@ namespace WebCore {
class RenderInline;
class RenderLayerModelObject;
class RenderObject;
-class RenderRegion;
class RenderWidget;
typedef HashMap<RenderWidget*, IntRect> OverlapTestRequestMap;
@@ -51,14 +50,13 @@ typedef HashMap<RenderWidget*, IntRect> OverlapTestRequestMap;
*/
struct PaintInfo {
PaintInfo(GraphicsContext* newContext, const IntRect& newRect, PaintPhase newPhase, PaintBehavior newPaintBehavior,
- RenderObject* newPaintingRoot = 0, RenderRegion* region = 0, ListHashSet<RenderInline*>* newOutlineObjects = 0,
+ RenderObject* newPaintingRoot = 0, ListHashSet<RenderInline*>* newOutlineObjects = 0,
OverlapTestRequestMap* overlapTestRequests = 0, const RenderLayerModelObject* newPaintContainer = 0)
: context(newContext)
, rect(newRect)
, phase(newPhase)
, paintBehavior(newPaintBehavior)
, paintingRoot(newPaintingRoot)
- , renderRegion(region)
, overlapTestRequests(overlapTestRequests)
, m_paintContainer(newPaintContainer)
, m_outlineObjects(newOutlineObjects)
@@ -87,9 +85,9 @@ struct PaintInfo {
bool skipRootBackground() const { return paintBehavior & PaintBehaviorSkipRootBackground; }
bool paintRootBackgroundOnly() const { return paintBehavior & PaintBehaviorRootBackgroundOnly; }
- void applyTransform(const AffineTransform& localToAncestorTransform)
+ void applyTransform(const AffineTransform& localToAncestorTransform, bool identityStatusUnknown = true)
{
- if (localToAncestorTransform.isIdentity())
+ if (identityStatusUnknown && localToAncestorTransform.isIdentity())
return;
context->concatCTM(localToAncestorTransform);
@@ -97,7 +95,10 @@ struct PaintInfo {
if (rect == infiniteRect())
return;
- rect = localToAncestorTransform.inverse().mapRect(rect);
+ if (localToAncestorTransform.isInvertible())
+ rect = localToAncestorTransform.inverse().mapRect(rect);
+ else
+ rect.setSize(IntSize(0, 0));
}
static IntRect infiniteRect() { return IntRect(LayoutRect::infiniteRect()); }
@@ -112,7 +113,6 @@ struct PaintInfo {
PaintPhase phase;
PaintBehavior paintBehavior;
RenderObject* paintingRoot; // used to draw just one element and its visual kids
- RenderRegion* renderRegion;
OverlapTestRequestMap* overlapTestRequests;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/PartialLayoutState.h b/chromium/third_party/WebKit/Source/core/rendering/PartialLayoutState.h
deleted file mode 100644
index 1ac7a328f71..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/PartialLayoutState.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 PartialLayoutState_h
-#define PartialLayoutState_h
-
-#include "core/rendering/RenderObject.h"
-
-namespace WebCore {
-
-class PartialLayoutState {
- friend class PartialLayoutDisabler;
-public:
- PartialLayoutState()
- : m_shouldStop(false)
- , m_stopAtRenderer(0)
- , m_disableCount(0)
- {
- }
-
- // True if we plan to do a partial layout, or are in the process of stopping a partial layout.
- bool isPartialLayout() const { return m_stopAtRenderer || m_shouldStop; }
-
- bool isStopping() const { return m_shouldStop; }
- bool checkPartialLayoutComplete(const RenderObject*);
- void setStopAtRenderer(const RenderObject* renderer) { m_stopAtRenderer = renderer; }
- void reset() { m_shouldStop = false; m_stopAtRenderer = 0; }
-
-private:
- void disable() { ASSERT(!m_shouldStop); m_disableCount++; }
- void enable() { ASSERT(m_disableCount > 0); m_disableCount--; }
- const RenderObject* stopAtRenderer() const { return m_disableCount > 0 ? 0 : m_stopAtRenderer; }
-
- bool m_shouldStop;
- const RenderObject* m_stopAtRenderer;
- int m_disableCount;
-};
-
-inline bool PartialLayoutState::checkPartialLayoutComplete(const RenderObject* renderer)
-{
- if (m_shouldStop)
- return true;
-
- if (renderer == stopAtRenderer()) {
- m_shouldStop = true;
- m_stopAtRenderer = 0;
- return true;
- }
-
- return false;
-}
-
-class PartialLayoutDisabler {
- WTF_MAKE_NONCOPYABLE(PartialLayoutDisabler);
-public:
- PartialLayoutDisabler(PartialLayoutState& partialLayout, bool disable = true)
- : m_partialLayout(partialLayout)
- , m_disable(disable)
- {
- if (m_disable)
- m_partialLayout.disable();
- }
-
- ~PartialLayoutDisabler()
- {
- if (m_disable)
- m_partialLayout.enable();
- }
-private:
- PartialLayoutState& m_partialLayout;
- bool m_disable;
-};
-
-} // namespace WebCore
-
-#endif // PartialLayoutState_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.cpp
index be4de73f89d..38d0e4c938f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "core/rendering/RenderApplet.h"
+#include "core/frame/UseCounter.h"
#include "core/html/HTMLAppletElement.h"
namespace WebCore {
@@ -30,6 +31,7 @@ RenderApplet::RenderApplet(HTMLAppletElement* applet)
: RenderEmbeddedObject(applet)
{
setInline(true);
+ UseCounter::count(document(), UseCounter::HTMLAppletElement);
}
RenderApplet::~RenderApplet()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.h b/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.h
index 3a0f7af28b2..9f740f404db 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderApplet.h
@@ -34,7 +34,7 @@ public:
virtual ~RenderApplet();
private:
- virtual const char* renderName() const { return "RenderApplet"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderApplet"; }
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBR.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderBR.cpp
index ea74001d6a7..e928cceceb7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBR.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBR.cpp
@@ -35,7 +35,6 @@ static PassRefPtr<StringImpl> newlineString()
RenderBR::RenderBR(Node* node)
: RenderText(node, newlineString())
- , m_lineHeight(-1)
{
}
@@ -45,22 +44,13 @@ RenderBR::~RenderBR()
int RenderBR::lineHeight(bool firstLine) const
{
- if (firstLine && document().styleEngine()->usesFirstLineRules()) {
- RenderStyle* s = style(firstLine);
- if (s != style())
- return s->computedLineHeight(view());
- }
-
- if (m_lineHeight == -1)
- m_lineHeight = style()->computedLineHeight(view());
-
- return m_lineHeight;
+ RenderStyle* s = style(firstLine && document().styleEngine()->usesFirstLineRules());
+ return s->computedLineHeight();
}
void RenderBR::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderText::styleDidChange(diff, oldStyle);
- m_lineHeight = -1;
}
int RenderBR::caretMinOffset() const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBR.h b/chromium/third_party/WebKit/Source/core/rendering/RenderBR.h
index 62d1a53479e..ff69d3a87a2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBR.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBR.h
@@ -29,35 +29,30 @@
*/
namespace WebCore {
-class Position;
-
class RenderBR FINAL : public RenderText {
public:
explicit RenderBR(Node*);
virtual ~RenderBR();
- virtual const char* renderName() const { return "RenderBR"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderBR"; }
- virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/) OVERRIDE { return LayoutRect(); }
+ virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* /*paintInvalidationContainer*/, bool /*clipToVisibleContent*/) OVERRIDE { return LayoutRect(); }
- virtual float width(unsigned /*from*/, unsigned /*len*/, const Font&, float /*xPos*/, HashSet<const SimpleFontData*>* = 0 /*fallbackFonts*/ , GlyphOverflow* = 0) const { return 0; }
- virtual float width(unsigned /*from*/, unsigned /*len*/, float /*xpos*/, bool = false /*firstLine*/, HashSet<const SimpleFontData*>* = 0 /*fallbackFonts*/, GlyphOverflow* = 0) const { return 0; }
+ virtual float width(unsigned /*from*/, unsigned /*len*/, const Font&, float /*xPos*/, TextDirection, HashSet<const SimpleFontData*>* = 0 /*fallbackFonts*/ , GlyphOverflow* = 0) const OVERRIDE { return 0; }
+ virtual float width(unsigned /*from*/, unsigned /*len*/, float /*xpos*/, TextDirection, bool = false /*firstLine*/, HashSet<const SimpleFontData*>* = 0 /*fallbackFonts*/, GlyphOverflow* = 0) const OVERRIDE { return 0; }
int lineHeight(bool firstLine) const;
// overrides
- virtual bool isBR() const { return true; }
+ virtual bool isBR() const OVERRIDE { return true; }
- virtual int caretMinOffset() const;
- virtual int caretMaxOffset() const;
+ virtual int caretMinOffset() const OVERRIDE;
+ virtual int caretMaxOffset() const OVERRIDE;
virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
-private:
- mutable int m_lineHeight;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderBR, isBR());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.cpp
index 84c790b6ab7..e7cf72c32b3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.cpp
@@ -24,7 +24,7 @@
#include "config.h"
#include "core/rendering/RenderBlock.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
@@ -33,8 +33,8 @@
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
#include "core/fetch/ResourceLoadPriorityOptimizer.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/rendering/FastTextAutosizer.h"
@@ -43,18 +43,19 @@
#include "core/rendering/HitTestResult.h"
#include "core/rendering/InlineIterator.h"
#include "core/rendering/InlineTextBox.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderCombineText.h"
#include "core/rendering/RenderDeprecatedFlexibleBox.h"
#include "core/rendering/RenderFlexibleBox.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderGrid.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderMarquee.h"
-#include "core/rendering/RenderNamedFlowThread.h"
#include "core/rendering/RenderRegion.h"
#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTextControl.h"
#include "core/rendering/RenderTextFragment.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
@@ -63,6 +64,7 @@
#include "core/rendering/style/RenderStyle.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
+#include "platform/graphics/GraphicsContextCullSaver.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "wtf/StdLibExtras.h"
#include "wtf/TemporaryChange.h"
@@ -82,7 +84,14 @@ struct SameSizeAsRenderBlock : public RenderBox {
uint32_t bitfields;
};
+struct SameSizeAsRenderBlockRareData {
+ int paginationStrut;
+ int pageLogicalOffset;
+ uint32_t bitfields;
+};
+
COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
+COMPILE_ASSERT(sizeof(RenderBlock::RenderBlockRareData) == sizeof(SameSizeAsRenderBlockRareData), RenderBlockRareData_should_stay_small);
typedef WTF::HashMap<const RenderBox*, OwnPtr<ColumnInfo> > ColumnInfoMap;
static ColumnInfoMap* gColumnInfoMap = 0;
@@ -108,6 +117,8 @@ class OverflowEventDispatcher {
public:
OverflowEventDispatcher(const RenderBlock* block)
: m_block(block)
+ , m_hadHorizontalLayoutOverflow(false)
+ , m_hadVerticalLayoutOverflow(false)
{
m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowClip() && m_block->document().hasListenerType(Document::OVERFLOWCHANGED_LISTENER);
if (m_shouldDispatchEvent) {
@@ -130,7 +141,7 @@ public:
if (!horizontalLayoutOverflowChanged && !verticalLayoutOverflowChanged)
return;
- RefPtr<OverflowEvent> event = OverflowEvent::create(horizontalLayoutOverflowChanged, hasHorizontalLayoutOverflow, verticalLayoutOverflowChanged, hasVerticalLayoutOverflow);
+ RefPtrWillBeRawPtr<OverflowEvent> event = OverflowEvent::create(horizontalLayoutOverflowChanged, hasHorizontalLayoutOverflow, verticalLayoutOverflowChanged, hasVerticalLayoutOverflow);
event->setTarget(m_block->node());
m_block->document().enqueueAnimationFrameEvent(event.release());
}
@@ -144,12 +155,12 @@ private:
RenderBlock::RenderBlock(ContainerNode* node)
: RenderBox(node)
- , m_lineHeight(-1)
, m_hasMarginBeforeQuirk(false)
, m_hasMarginAfterQuirk(false)
, m_beingDestroyed(false)
, m_hasMarkupTruncation(false)
, m_hasBorderOrPaddingLogicalWidthChanged(false)
+ , m_hasOnlySelfCollapsingChildren(false)
{
setChildrenInline(true);
}
@@ -174,8 +185,11 @@ static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, Tracke
static void appendImageIfNotNull(Vector<ImageResource*>& imageResources, const StyleImage* styleImage)
{
- if (styleImage && styleImage->cachedImage())
- imageResources.append(styleImage->cachedImage());
+ if (styleImage && styleImage->cachedImage()) {
+ ImageResource* imageResource = styleImage->cachedImage();
+ if (imageResource && !imageResource->isLoaded())
+ imageResources.append(styleImage->cachedImage());
+ }
}
static void appendLayers(Vector<ImageResource*>& images, const FillLayer* styleLayer)
@@ -185,6 +199,25 @@ static void appendLayers(Vector<ImageResource*>& images, const FillLayer* styleL
}
}
+static void appendImagesFromStyle(Vector<ImageResource*>& images, RenderStyle& blockStyle)
+{
+ appendLayers(images, blockStyle.backgroundLayers());
+ appendLayers(images, blockStyle.maskLayers());
+
+ const ContentData* contentData = blockStyle.contentData();
+ if (contentData && contentData->isImage()) {
+ const ImageContentData* imageContentData = static_cast<const ImageContentData*>(contentData);
+ appendImageIfNotNull(images, imageContentData->image());
+ }
+ if (blockStyle.boxReflect())
+ appendImageIfNotNull(images, blockStyle.boxReflect()->mask().image());
+ appendImageIfNotNull(images, blockStyle.listStyleImage());
+ appendImageIfNotNull(images, blockStyle.borderImageSource());
+ appendImageIfNotNull(images, blockStyle.maskBoxImageSource());
+ if (blockStyle.shapeOutside())
+ appendImageIfNotNull(images, blockStyle.shapeOutside()->image());
+}
+
RenderBlock::~RenderBlock()
{
if (hasColumns())
@@ -240,25 +273,27 @@ void RenderBlock::willBeDestroyed()
if (UNLIKELY(gDelayedUpdateScrollInfoSet != 0))
gDelayedUpdateScrollInfoSet->remove(this);
- FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
- if (textAutosizer)
+ if (FastTextAutosizer* textAutosizer = document().fastTextAutosizer())
textAutosizer->destroy(this);
RenderBox::willBeDestroyed();
}
-void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
RenderStyle* oldStyle = style();
- setReplaced(newStyle->isDisplayInlineType());
+ setReplaced(newStyle.isDisplayInlineType());
- if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position()) {
- if (newStyle->position() == StaticPosition)
+ if (oldStyle && parent()) {
+ bool oldStyleIsContainer = oldStyle->position() != StaticPosition || oldStyle->hasTransformRelatedProperty();
+ bool newStyleIsContainer = newStyle.position() != StaticPosition || newStyle.hasTransformRelatedProperty();
+
+ if (oldStyleIsContainer && !newStyleIsContainer) {
// Clear our positioned objects list. Our absolutely positioned descendants will be
// inserted into our containing block's positioned objects list during layout.
removePositionedObjects(0, NewContainingBlock);
- else if (oldStyle->position() == StaticPosition) {
+ } else if (!oldStyleIsContainer && newStyleIsContainer) {
// Remove our absolutely positioned descendants from their current containing block.
// They will be inserted into our positioned objects list during layout.
RenderObject* cb = parent();
@@ -298,8 +333,6 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
RenderStyle* newStyle = style();
- updateShapeInsideInfoAfterStyleChange(newStyle->resolvedShapeInside(), oldStyle ? oldStyle->resolvedShapeInside() : RenderStyle::initialShapeInside());
-
if (!isAnonymousBlock()) {
// Ensure that all of our continuation blocks pick up the new style.
for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
@@ -310,16 +343,63 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
}
}
- FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
- if (textAutosizer)
+ if (FastTextAutosizer* textAutosizer = document().fastTextAutosizer())
textAutosizer->record(this);
propagateStyleToAnonymousChildren(true);
- m_lineHeight = -1;
// It's possible for our border/padding to change, but for the overall logical width of the block to
// end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
- m_hasBorderOrPaddingLogicalWidthChanged = oldStyle && diff == StyleDifferenceLayout && needsLayout() && borderOrPaddingLogicalWidthChanged(oldStyle, newStyle);
+ m_hasBorderOrPaddingLogicalWidthChanged = oldStyle && diff.needsFullLayout() && needsLayout() && borderOrPaddingLogicalWidthChanged(oldStyle, newStyle);
+
+ // If the style has unloaded images, want to notify the ResourceLoadPriorityOptimizer so that
+ // network priorities can be set.
+ Vector<ImageResource*> images;
+ appendImagesFromStyle(images, *newStyle);
+ if (images.isEmpty())
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeRenderObject(this);
+ else
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addRenderObject(this);
+}
+
+void RenderBlock::invalidateTreeAfterLayout(const RenderLayerModelObject& invalidationContainer)
+{
+ // Note, we don't want to early out here using shouldCheckForInvalidationAfterLayout as
+ // we have to make sure we go through any positioned objects as they won't be seen in
+ // the normal tree walk.
+
+ if (shouldCheckForPaintInvalidationAfterLayout())
+ RenderBox::invalidateTreeAfterLayout(invalidationContainer);
+
+ // Take care of positioned objects. This is required as LayoutState keeps a single clip rect.
+ if (TrackedRendererListHashSet* positionedObjects = this->positionedObjects()) {
+ TrackedRendererListHashSet::iterator end = positionedObjects->end();
+ LayoutState state(*this, isTableRow() ? LayoutSize() : locationOffset());
+ for (TrackedRendererListHashSet::iterator it = positionedObjects->begin(); it != end; ++it) {
+ RenderBox* box = *it;
+
+ // One of the renderers we're skipping over here may be the child's repaint container,
+ // so we can't pass our own repaint container along.
+ const RenderLayerModelObject& repaintContainerForChild = *box->containerForPaintInvalidation();
+
+ // If the positioned renderer is absolutely positioned and it is inside
+ // a relatively positioend inline element, we need to account for
+ // the inline elements position in LayoutState.
+ if (box->style()->position() == AbsolutePosition) {
+ RenderObject* container = box->container(&repaintContainerForChild, 0);
+ if (container->isInFlowPositioned() && container->isRenderInline()) {
+ // FIXME: We should be able to use layout-state for this.
+ // Currently, we will place absolutly positioned elements inside
+ // relatively positioned inline blocks in the wrong location. crbug.com/371485
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+ box->invalidateTreeAfterLayout(repaintContainerForChild);
+ continue;
+ }
+ }
+
+ box->invalidateTreeAfterLayout(repaintContainerForChild);
+ }
+ }
}
RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
@@ -458,7 +538,7 @@ RenderBlockFlow* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBl
{
RenderBlock* firstChildIgnoringAnonymousWrappers = 0;
for (RenderObject* curr = this; curr; curr = curr->parent()) {
- if (!curr->isRenderBlock() || curr->isFloatingOrOutOfFlowPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
+ if (!curr->isRenderBlock() || curr->isFloatingOrOutOfFlowPositioned() || curr->isTableCell() || curr->isDocumentElement() || curr->isRenderView() || curr->hasOverflowClip()
|| curr->isInlineBlockOrInlineTable())
return 0;
@@ -622,9 +702,9 @@ void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
// Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
// get deleted properly. Because objects moves from the pre block into the post block, we want to
// make new line boxes instead of leaving the old line boxes around.
- pre->setNeedsLayoutAndPrefWidthsRecalc();
- block->setNeedsLayoutAndPrefWidthsRecalc();
- post->setNeedsLayoutAndPrefWidthsRecalc();
+ pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlockFlow* newBlockBox, RenderObject* newChild)
@@ -672,10 +752,10 @@ void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, R
// get deleted properly. Because objects moved from the pre block into the post block, we want to
// make new line boxes instead of leaving the old line boxes around.
if (pre)
- pre->setNeedsLayoutAndPrefWidthsRecalc();
- block->setNeedsLayoutAndPrefWidthsRecalc();
+ pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
if (post)
- post->setNeedsLayoutAndPrefWidthsRecalc();
+ post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
RenderBlockFlow* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
@@ -725,7 +805,7 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
|| beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
) {
// Insert the child into the anonymous block box instead of here.
- if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
+ if (newChild->isInline() || newChild->isFloatingOrOutOfFlowPositioned() || beforeChild->parent()->slowFirstChild() != beforeChild)
beforeChild->parent()->addChild(newChild, beforeChild);
else
addChild(newChild, beforeChild->parent());
@@ -751,7 +831,7 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
}
// Check for a spanning element in columns.
- if (gColumnFlowSplitEnabled) {
+ if (gColumnFlowSplitEnabled && !document().regionBasedColumnsEnabled()) {
RenderBlockFlow* columnsBlockAncestor = columnsBlockForSpanningElement(newChild);
if (columnsBlockAncestor) {
TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false);
@@ -886,19 +966,6 @@ void RenderBlock::deleteLineBoxTree()
cache->recomputeIsIgnored(this);
}
-RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
-{
- RootInlineBox* rootBox = createRootInlineBox();
- m_lineBoxes.appendLineBox(rootBox);
-
- if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && m_lineBoxes.firstLineBox() == rootBox) {
- if (AXObjectCache* cache = document().existingAXObjectCache())
- cache->recomputeIsIgnored(this);
- }
-
- return rootBox;
-}
-
void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
{
// makeChildrenNonInline takes a block whose children are *all* inline and it
@@ -938,7 +1005,7 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
ASSERT(!c->isInline());
#endif
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
@@ -986,6 +1053,10 @@ void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
// Remove all the information in the flow thread associated with the leftover anonymous block.
child->removeFromRenderFlowThread();
+ // RenderGrid keeps track of its children, we must notify it about changes in the tree.
+ if (child->parent()->isRenderGrid())
+ toRenderGrid(child->parent())->dirtyGrid();
+
child->setParent(0);
child->setPreviousSibling(0);
child->setNextSibling(0);
@@ -1021,7 +1092,7 @@ void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock*
// destroyed. See crbug.com/282088
if (child->beingDestroyed())
return;
- parent->setNeedsLayoutAndPrefWidthsRecalc();
+ parent->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
parent->setChildrenInline(child->childrenInline());
RenderObject* nextSibling = child->nextSibling();
@@ -1033,8 +1104,6 @@ void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock*
// Explicitly delete the child's line box tree, or the special anonymous
// block handling in willBeDestroyed will cause problems.
child->deleteLineBoxTree();
- if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
- toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(child);
child->destroy();
}
@@ -1057,9 +1126,9 @@ void RenderBlock::removeChild(RenderObject* oldChild)
RenderObject* next = oldChild->nextSibling();
bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
if (canMergeAnonymousBlocks && prev && next) {
- prev->setNeedsLayoutAndPrefWidthsRecalc();
- RenderBlock* nextBlock = toRenderBlock(next);
- RenderBlock* prevBlock = toRenderBlock(prev);
+ prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ RenderBlockFlow* nextBlock = toRenderBlockFlow(next);
+ RenderBlockFlow* prevBlock = toRenderBlockFlow(prev);
if (prev->childrenInline() != next->childrenInline()) {
RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
@@ -1079,7 +1148,7 @@ void RenderBlock::removeChild(RenderObject* oldChild)
// Now just put the inlineChildrenBlock inside the blockChildrenBlock.
blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
- next->setNeedsLayoutAndPrefWidthsRecalc();
+ next->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
// inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
// of "this". we null out prev or next so that is not used later in the function.
@@ -1128,7 +1197,7 @@ void RenderBlock::removeChild(RenderObject* oldChild)
// we need to remove ourself and fix the continuation chain.
if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->isListMarker()) {
RenderObject* containingBlockIgnoringAnonymous = containingBlock();
- while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock())
+ while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymous())
containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) {
if (curr->virtualContinuation() != this)
@@ -1160,6 +1229,20 @@ bool RenderBlock::isSelfCollapsingBlock() const
// (c) have border/padding,
// (d) have a min-height
// (e) have specified that one of our margins can't collapse using a CSS extension
+ // (f) establish a new block formatting context.
+
+ // The early exit must be done before we check for clean layout.
+ // We should be able to give a quick answer if the box is a relayout boundary.
+ // Being a relayout boundary implies a block formatting context, and also
+ // our internal layout shouldn't affect our container in any way.
+ if (createsBlockFormattingContext())
+ return false;
+
+ // Placeholder elements are not laid out until the dimensions of their parent text control are known, so they
+ // don't get layout until their parent has had layout - this is unique in the layout tree and means
+ // when we call isSelfCollapsingBlock on them we find that they still need layout.
+ ASSERT(!needsLayout() || (node() && node()->isElementNode() && toElement(node())->shadowPseudoId() == "-webkit-input-placeholder"));
+
if (logicalHeight() > 0
|| isTable() || borderAndPaddingLogicalHeight()
|| style()->logicalMinHeight().isPositive()
@@ -1186,6 +1269,8 @@ bool RenderBlock::isSelfCollapsingBlock() const
// Whether or not we collapse is dependent on whether all our normal flow children
// are also self-collapsing.
+ if (m_hasOnlySelfCollapsingChildren)
+ return true;
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
if (child->isFloatingOrOutOfFlowPositioned())
continue;
@@ -1248,7 +1333,6 @@ void RenderBlock::updateScrollInfoAfterLayout()
void RenderBlock::layout()
{
OverflowEventDispatcher dispatcher(this);
- LayoutRectRecorder recorder(*this);
// Update our first letter info now.
updateFirstLetter();
@@ -1257,9 +1341,6 @@ void RenderBlock::layout()
// layoutBlock().
layoutBlock(false);
- if (frameView()->partialLayout().isStopping())
- return;
-
// It's safe to check for control clip here, since controls can never be table cells.
// If we have a lightweight clip, there can never be any overflow from children.
if (hasControlClip() && m_overflow)
@@ -1268,42 +1349,13 @@ void RenderBlock::layout()
invalidateBackgroundObscurationStatus();
}
-void RenderBlock::didLayout(ResourceLoadPriorityOptimizer& optimizer)
-{
- RenderBox::didLayout(optimizer);
- updateStyleImageLoadingPriorities(optimizer);
-}
-
-void RenderBlock::didScroll(ResourceLoadPriorityOptimizer& optimizer)
-{
- RenderBox::didScroll(optimizer);
- updateStyleImageLoadingPriorities(optimizer);
-}
-
-void RenderBlock::updateStyleImageLoadingPriorities(ResourceLoadPriorityOptimizer& optimizer)
+bool RenderBlock::updateImageLoadingPriorities()
{
- RenderStyle* blockStyle = style();
- if (!blockStyle)
- return;
-
Vector<ImageResource*> images;
-
- appendLayers(images, blockStyle->backgroundLayers());
- appendLayers(images, blockStyle->maskLayers());
-
- const ContentData* contentData = blockStyle->contentData();
- if (contentData && contentData->isImage()) {
- const ImageContentData* imageContentData = static_cast<const ImageContentData*>(contentData);
- appendImageIfNotNull(images, imageContentData->image());
- }
- if (blockStyle->boxReflect())
- appendImageIfNotNull(images, blockStyle->boxReflect()->mask().image());
- appendImageIfNotNull(images, blockStyle->listStyleImage());
- appendImageIfNotNull(images, blockStyle->borderImageSource());
- appendImageIfNotNull(images, blockStyle->maskBoxImageSource());
+ appendImagesFromStyle(images, *style());
if (images.isEmpty())
- return;
+ return false;
LayoutRect viewBounds = viewRect();
LayoutRect objectBounds = absoluteContentBox();
@@ -1318,165 +1370,16 @@ void RenderBlock::updateStyleImageLoadingPriorities(ResourceLoadPriorityOptimize
ResourceLoadPriorityOptimizer::VisibilityStatus status = isVisible ?
ResourceLoadPriorityOptimizer::Visible : ResourceLoadPriorityOptimizer::NotVisible;
- for (Vector<ImageResource*>::iterator it = images.begin(), end = images.end(); it != end; ++it)
- optimizer.notifyImageResourceVisibility(*it, status);
-}
-
-void RenderBlock::relayoutShapeDescendantIfMoved(RenderBlock* child, LayoutSize offset)
-{
- LayoutUnit left = isHorizontalWritingMode() ? offset.width() : offset.height();
- if (!left || !child || child->shapeInsideInfo() || !layoutShapeInsideInfo())
- return;
- // Propagate layout markers only up to the child, as we are still in the middle
- // of a layout pass
- child->setNormalChildNeedsLayout(true);
- child->markShapeInsideDescendantsForLayout();
- child->layoutIfNeeded();
-}
-
-ShapeInsideInfo* RenderBlock::layoutShapeInsideInfo() const
-{
- if (ShapeInsideInfo* shapeInsideInfo = view()->layoutState()->shapeInsideInfo())
- return shapeInsideInfo;
-
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (allowsShapeInsideInfoSharing(flowThread)) {
- LayoutUnit lineHeight = this->lineHeight(false, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
- // regionAtBlockOffset returns regions like an array first={0,N-1}, second={N,M-1}, ...
- LayoutUnit offset = logicalHeight() + lineHeight - LayoutUnit(1);
- RenderRegion* region = regionAtBlockOffset(offset);
- if (region && region->logicalHeight())
- return region->shapeInsideInfo();
- }
-
- return 0;
-}
-
-LayoutSize RenderBlock::logicalOffsetFromShapeAncestorContainer(const RenderBlock* container) const
-{
- const RenderBlock* currentBlock = this;
- LayoutRect blockRect(currentBlock->borderBoxRect());
- while (currentBlock && !currentBlock->isRenderFlowThread() && currentBlock != container) {
- RenderBlock* containerBlock = currentBlock->containingBlock();
- ASSERT(containerBlock);
- if (!containerBlock)
- return LayoutSize();
-
- if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
- // We have to put the block rect in container coordinates
- // and we have to take into account both the container and current block flipping modes
- // Bug: Flipping inline and block directions at the same time will not work,
- // as one of the flipped dimensions will not yet have been set to its final size
- if (containerBlock->style()->isFlippedBlocksWritingMode()) {
- if (containerBlock->isHorizontalWritingMode())
- blockRect.setY(currentBlock->height() - blockRect.maxY());
- else
- blockRect.setX(currentBlock->width() - blockRect.maxX());
- }
- currentBlock->flipForWritingMode(blockRect);
- }
-
- blockRect.moveBy(currentBlock->location());
- currentBlock = containerBlock;
- }
-
- LayoutSize result = isHorizontalWritingMode() ? LayoutSize(blockRect.x(), blockRect.y()) : LayoutSize(blockRect.y(), blockRect.x());
- return result;
-}
-
-void RenderBlock::imageChanged(WrappedImagePtr image, const IntRect*)
-{
- RenderBox::imageChanged(image);
-
- if (!parent() || !everHadLayout())
- return;
-
- ShapeValue* shapeValue = style()->shapeInside();
- if (shapeValue && shapeValue->image() && shapeValue->image()->data() == image) {
- ShapeInsideInfo* shapeInsideInfo = ensureShapeInsideInfo();
- shapeInsideInfo->dirtyShapeSize();
- markShapeInsideDescendantsForLayout();
- }
-
- ShapeValue* shapeOutsideValue = style()->shapeOutside();
- if (isFloating() && shapeOutsideValue && shapeOutsideValue->image() && shapeOutsideValue->image()->data() == image)
- parent()->setNeedsLayoutAndPrefWidthsRecalc();
-}
-
-void RenderBlock::updateShapeInsideInfoAfterStyleChange(const ShapeValue* shapeInside, const ShapeValue* oldShapeInside)
-{
- // FIXME: A future optimization would do a deep comparison for equality.
- if (shapeInside == oldShapeInside)
- return;
-
- if (shapeInside) {
- ShapeInsideInfo* shapeInsideInfo = ensureShapeInsideInfo();
- shapeInsideInfo->dirtyShapeSize();
- } else {
- setShapeInsideInfo(nullptr);
- markShapeInsideDescendantsForLayout();
- }
-}
-
-static inline bool shapeInfoRequiresRelayout(const RenderBlock* block)
-{
- ShapeInsideInfo* info = block->shapeInsideInfo();
- if (info)
- info->setNeedsLayout(info->shapeSizeDirty());
- else
- info = block->layoutShapeInsideInfo();
- return info && info->needsLayout();
-}
-
-bool RenderBlock::updateRegionsAndShapesLogicalSize(RenderFlowThread* flowThread)
-{
- if (!flowThread && !shapeInsideInfo())
- return shapeInfoRequiresRelayout(this);
-
- LayoutUnit oldHeight = logicalHeight();
- LayoutUnit oldTop = logicalTop();
-
- // Compute the maximum logical height content may cause this block to expand to
- // FIXME: These should eventually use the const computeLogicalHeight rather than updateLogicalHeight
- setLogicalHeight(RenderFlowThread::maxLogicalHeight());
- updateLogicalHeight();
-
- computeShapeSize();
-
- // Set our start and end regions. No regions above or below us will be considered by our children. They are
- // effectively clamped to our region range.
- computeRegionRangeForBlock(flowThread);
-
- setLogicalHeight(oldHeight);
- setLogicalTop(oldTop);
-
- return shapeInfoRequiresRelayout(this);
-}
-
-void RenderBlock::computeShapeSize()
-{
- ShapeInsideInfo* shapeInsideInfo = this->shapeInsideInfo();
- if (!shapeInsideInfo)
- return;
-
- if (isRenderNamedFlowFragment()) {
- ShapeInsideInfo* parentShapeInsideInfo = toRenderBlock(parent())->shapeInsideInfo();
- ASSERT(parentShapeInsideInfo);
- shapeInsideInfo->setShapeSize(parentShapeInsideInfo->shapeSize().width(), parentShapeInsideInfo->shapeSize().height());
- } else {
- bool percentageLogicalHeightResolvable = percentageLogicalHeightIsResolvableFromBlock(this, false);
- shapeInsideInfo->setShapeSize(logicalWidth(), percentageLogicalHeightResolvable ? logicalHeight() : LayoutUnit());
+ LayoutRect screenArea;
+ if (!objectBounds.isEmpty()) {
+ screenArea = viewBounds;
+ screenArea.intersect(objectBounds);
}
-}
-void RenderBlock::updateRegionsAndShapesAfterChildLayout(RenderFlowThread* flowThread, bool heightChanged)
-{
- // A previous sibling has changed dimension, so we need to relayout the shape with the content
- ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
- if (heightChanged && shapeInsideInfo)
- shapeInsideInfo->dirtyShapeSize();
+ for (Vector<ImageResource*>::iterator it = images.begin(), end = images.end(); it != end; ++it)
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->notifyImageResourceVisibility(*it, status, screenArea);
- computeRegionRangeForBlock(flowThread);
+ return true;
}
void RenderBlock::computeRegionRangeForBlock(RenderFlowThread* flowThread)
@@ -1499,37 +1402,7 @@ bool RenderBlock::updateLogicalWidthAndColumnWidth()
return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth() || hasBorderOrPaddingLogicalWidthChanged;
}
-void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
-{
- ColumnInfo* colInfo = columnInfo();
- if (hasColumns()) {
- if (!pageLogicalHeight) {
- // We need to go ahead and set our explicit page height if one exists, so that we can
- // avoid doing two layout passes.
- updateLogicalHeight();
- LayoutUnit columnHeight = contentLogicalHeight();
- if (columnHeight > 0) {
- pageLogicalHeight = columnHeight;
- hasSpecifiedPageLogicalHeight = true;
- }
- setLogicalHeight(0);
- }
- if (colInfo->columnHeight() != pageLogicalHeight && everHadLayout()) {
- colInfo->setColumnHeight(pageLogicalHeight);
- pageLogicalHeightChanged = true;
- }
-
- if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
- colInfo->clearForcedBreaks();
-
- colInfo->setPaginationUnit(paginationUnit());
- } else if (isRenderFlowThread()) {
- pageLogicalHeight = 1; // This is just a hack to always make sure we have a page logical height.
- pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalSizeChanged();
- }
-}
-
-void RenderBlock::layoutBlock(bool, LayoutUnit)
+void RenderBlock::layoutBlock(bool)
{
ASSERT_NOT_REACHED();
clearNeedsLayout();
@@ -1577,14 +1450,9 @@ void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool)
m_overflow->setLayoutClientAfterEdge(oldClientAfterEdge);
}
- // Add visual overflow from box-shadow and border-image-outset.
addVisualEffectOverflow();
- // Add visual overflow from theme.
addVisualOverflowFromTheme();
-
- if (isRenderNamedFlowThread())
- toRenderNamedFlowThread(this)->computeOversetStateForRegions(oldClientAfterEdge);
}
void RenderBlock::addOverflowFromBlockChildren()
@@ -1622,79 +1490,10 @@ void RenderBlock::addVisualOverflowFromTheme()
addVisualOverflow(inflatedRect);
}
-bool RenderBlock::expandsToEncloseOverhangingFloats() const
+bool RenderBlock::createsBlockFormattingContext() const
{
- return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBoxIncludingDeprecated())
- || hasColumns() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isRoot();
-}
-
-LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* region)
-{
- LayoutUnit startPosition = startOffsetForContent(region);
-
- // Add in our start margin.
- LayoutUnit oldPosition = startPosition + childMarginStart;
- LayoutUnit newPosition = oldPosition;
-
- LayoutUnit blockOffset = logicalTopForChild(child);
- if (region)
- blockOffset = max(blockOffset, blockOffset + (region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage()));
-
- LayoutUnit startOff = startOffsetForLineInRegion(blockOffset, false, region, logicalHeightForChild(child));
-
- if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
- 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)
- newPosition = startOff + childMarginStart;
-
- return newPosition - oldPosition;
-}
-
-void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode applyDelta)
-{
- LayoutUnit startPosition = borderStart() + paddingStart();
- if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
- startPosition -= verticalScrollbarWidth();
- LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
-
- // Add in our start margin.
- LayoutUnit childMarginStart = marginStartForChild(child);
- LayoutUnit newPosition = startPosition + childMarginStart;
-
- // 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() && !flowThreadContainingBlock())
- newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child));
-
- setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), applyDelta);
-}
-
-void RenderBlock::setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
-{
- if (isHorizontalWritingMode()) {
- if (applyDelta == ApplyLayoutDelta)
- view()->addLayoutDelta(LayoutSize(child->x() - logicalLeft, 0));
- child->setX(logicalLeft);
- } else {
- if (applyDelta == ApplyLayoutDelta)
- view()->addLayoutDelta(LayoutSize(0, child->y() - logicalLeft));
- child->setY(logicalLeft);
- }
-}
-
-void RenderBlock::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
-{
- if (isHorizontalWritingMode()) {
- if (applyDelta == ApplyLayoutDelta)
- view()->addLayoutDelta(LayoutSize(0, child->y() - logicalTop));
- child->setY(logicalTop);
- } else {
- if (applyDelta == ApplyLayoutDelta)
- view()->addLayoutDelta(LayoutSize(child->x() - logicalTop, 0));
- child->setX(logicalTop);
- }
+ return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || isFlexItemIncludingDeprecated()
+ || style()->specifiesColumns() || isRenderFlowThread() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isDocumentElement() || style()->columnSpan();
}
void RenderBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox* child)
@@ -1718,8 +1517,8 @@ void RenderBlock::simplifiedNormalFlowLayout()
if (!o->isOutOfFlowPositioned() && (o->isReplaced() || o->isFloating())) {
o->layoutIfNeeded();
if (toRenderBox(o)->inlineBoxWrapper()) {
- RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root();
- lineBoxes.add(box);
+ RootInlineBox& box = toRenderBox(o)->inlineBoxWrapper()->root();
+ lineBoxes.add(&box);
}
} else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline())) {
o->clearNeedsLayout();
@@ -1742,45 +1541,49 @@ void RenderBlock::simplifiedNormalFlowLayout()
bool RenderBlock::simplifiedLayout()
{
- if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
+ // Check if we need to do a full layout.
+ if (normalChildNeedsLayout() || selfNeedsLayout())
return false;
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
-
- if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
+ // Check that we actually need to do a simplified layout.
+ if (!posChildNeedsLayout() && !(needsSimplifiedNormalFlowLayout() || needsPositionedMovementLayout()))
return false;
- // Lay out positioned descendants or objects that just need to recompute overflow.
- if (needsSimplifiedNormalFlowLayout())
- simplifiedNormalFlowLayout();
-
- // Make sure a forced break is applied after the content if we are a flow thread in a simplified layout.
- // This ensures the size information is correctly computed for the last auto-height region receiving content.
- if (isRenderFlowThread())
- toRenderFlowThread(this)->applyBreakAfterContent(clientLogicalBottom());
-
- // Lay out our positioned objects if our positioned child bit is set.
- // Also, if an absolute position element inside a relative positioned container moves, and the absolute element has a fixed position
- // child, neither the fixed element nor its container learn of the movement since posChildNeedsLayout() is only marked as far as the
- // relative positioned container. So if we can have fixed pos objects in our positioned objects list check if any of them
- // are statically positioned and thus need to move with their absolute ancestors.
- bool canContainFixedPosObjects = canContainFixedPositionObjects();
- if (posChildNeedsLayout() || canContainFixedPosObjects)
- layoutPositionedObjects(false, !posChildNeedsLayout() && canContainFixedPosObjects);
-
- // Recompute our overflow information.
- // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
- // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
- // For now just always recompute overflow. This is no worse performance-wise than the old code that called rightmostPosition and
- // lowestPosition on every relayout so it's not a regression.
- // computeOverflow expects the bottom edge before we clamp our height. Since this information isn't available during
- // simplifiedLayout, we cache the value in m_overflow.
- LayoutUnit oldClientAfterEdge = hasRenderOverflow() ? m_overflow->layoutClientAfterEdge() : clientLogicalBottom();
- computeOverflow(oldClientAfterEdge, true);
- statePusher.pop();
+ {
+ // LayoutState needs this deliberate scope to pop before repaint
+ LayoutState state(*this, locationOffset());
+
+ if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
+ return false;
+
+ FastTextAutosizer::LayoutScope fastTextAutosizerLayoutScope(this);
- updateLayerTransform();
+ // Lay out positioned descendants or objects that just need to recompute overflow.
+ if (needsSimplifiedNormalFlowLayout())
+ simplifiedNormalFlowLayout();
+
+ // Lay out our positioned objects if our positioned child bit is set.
+ // Also, if an absolute position element inside a relative positioned container moves, and the absolute element has a fixed position
+ // child, neither the fixed element nor its container learn of the movement since posChildNeedsLayout() is only marked as far as the
+ // relative positioned container. So if we can have fixed pos objects in our positioned objects list check if any of them
+ // are statically positioned and thus need to move with their absolute ancestors.
+ bool canContainFixedPosObjects = canContainFixedPositionObjects();
+ if (posChildNeedsLayout() || needsPositionedMovementLayout() || canContainFixedPosObjects)
+ layoutPositionedObjects(false, needsPositionedMovementLayout() ? ForcedLayoutAfterContainingBlockMoved : (!posChildNeedsLayout() && canContainFixedPosObjects ? LayoutOnlyFixedPositionedObjects : DefaultLayout));
+
+ // Recompute our overflow information.
+ // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
+ // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
+ // For now just always recompute overflow. This is no worse performance-wise than the old code that called rightmostPosition and
+ // lowestPosition on every relayout so it's not a regression.
+ // computeOverflow expects the bottom edge before we clamp our height. Since this information isn't available during
+ // simplifiedLayout, we cache the value in m_overflow.
+ LayoutUnit oldClientAfterEdge = hasRenderOverflow() ? m_overflow->layoutClientAfterEdge() : clientLogicalBottom();
+ computeOverflow(oldClientAfterEdge, true);
+ }
+
+ updateLayerTransformAfterLayout();
updateScrollInfoAfterLayout();
@@ -1806,9 +1609,10 @@ void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderObject* child,
RenderBox* box = toRenderBox(child);
if (hasStaticInlinePosition) {
- LayoutUnit oldLeft = box->logicalLeft();
- box->updateLogicalWidth();
- if (box->logicalLeft() != oldLeft)
+ LogicalExtentComputedValues computedValues;
+ box->computeLogicalWidth(computedValues);
+ LayoutUnit newLeft = computedValues.m_position;
+ if (newLeft != box->logicalLeft())
layoutScope.setChildNeedsLayout(child);
} else if (hasStaticBlockPosition) {
LayoutUnit oldTop = box->logicalTop();
@@ -1833,7 +1637,7 @@ LayoutUnit RenderBlock::marginIntrinsicLogicalWidthForChild(RenderBox* child) co
return margin;
}
-void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly)
+void RenderBlock::layoutPositionedObjects(bool relayoutChildren, PositionedLayoutBehavior info)
{
TrackedRendererListHashSet* positionedDescendants = positionedObjects();
if (!positionedDescendants)
@@ -1847,12 +1651,15 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPosit
for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
r = *it;
- SubtreeLayoutScope layoutScope(r);
+ // FIXME: this should only be set from clearNeedsLayout crbug.com/361250
+ r->setLayoutDidGetCalled(true);
+
+ SubtreeLayoutScope layoutScope(*r);
// A fixed position element with an absolute positioned ancestor has no way of knowing if the latter has changed position. So
// if this is a fixed position element, mark it for layout if it has an abspos ancestor and needs to move with that ancestor, i.e.
// it has static position.
markFixedPositionObjectForLayoutIfNeeded(r, layoutScope);
- if (fixedPositionObjectsOnly) {
+ if (info == LayoutOnlyFixedPositionedObjects) {
r->layoutIfNeeded();
continue;
}
@@ -1871,11 +1678,6 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPosit
if (!r->needsLayout())
r->markForPaginationRelayoutIfNeeded(layoutScope);
- // 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())
- r->clearNeedsLayout();
-
// If we are paginated or in a line grid, go ahead and compute a vertical position for our object now.
// If it's wrong we'll lay out again.
LayoutUnit oldLogicalTop = 0;
@@ -1888,6 +1690,11 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPosit
oldLogicalTop = logicalTopForChild(r);
}
+ // FIXME: We should be able to do a r->setNeedsPositionedMovementLayout() here instead of a full layout. Need
+ // to investigate why it does not trigger the correct invalidations in that case. crbug.com/350756
+ if (info == ForcedLayoutAfterContainingBlockMoved)
+ r->setNeedsLayoutAndFullPaintInvalidation();
+
r->layoutIfNeeded();
// Lay out again if our estimate was wrong.
@@ -1896,7 +1703,7 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPosit
}
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.
+ view()->layoutState()->setColumnInfo(columnInfo()); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
}
void RenderBlock::markPositionedObjectsForLayout()
@@ -1918,7 +1725,7 @@ void RenderBlock::markForPaginationRelayoutIfNeeded(SubtreeLayoutScope& layoutSc
if (needsLayout())
return;
- if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
+ if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(*this, logicalTop()) != pageLogicalOffset()))
layoutScope.setChildNeedsLayout(this);
}
@@ -1930,13 +1737,13 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
PaintPhase phase = paintInfo.phase;
+ LayoutRect overflowBox;
// Check if we need to do anything at all.
- // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
+ // FIXME: Could eliminate the isDocumentElement() check if we fix background painting so that the RenderView
// paints the root's background.
- if (!isRoot()) {
- LayoutRect overflowBox = overflowRectForPaintRejection();
+ if (!isDocumentElement()) {
+ overflowBox = overflowRectForPaintRejection();
flipForWritingMode(overflowBox);
- overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
overflowBox.moveBy(adjustedPaintOffset);
if (!overflowBox.intersects(paintInfo.rect))
return;
@@ -1949,7 +1756,16 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
contentsClipBehavior = SkipContentsClipIfPossible;
bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset, contentsClipBehavior);
- paintObject(paintInfo, adjustedPaintOffset);
+ {
+ GraphicsContextCullSaver cullSaver(*paintInfo.context);
+ // Cull if we have more than one child and we didn't already clip.
+ bool shouldCull = document().settings()->containerCullingEnabled() && !pushedClip && !isDocumentElement()
+ && firstChild() && lastChild() && firstChild() != lastChild();
+ if (shouldCull)
+ cullSaver.cull(overflowBox);
+
+ paintObject(paintInfo, adjustedPaintOffset);
+ }
if (pushedClip)
popContentsClip(paintInfo, phase, adjustedPaintOffset);
@@ -1980,7 +1796,7 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
bool antialias = shouldAntialiasLines(paintInfo.context);
if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
- bool leftToRight = style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed();
+ bool leftToRight = style()->isLeftToRightDirection();
LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
LayoutUnit ruleAdd = logicalLeftOffsetForContent();
LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
@@ -2012,13 +1828,13 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
ruleLogicalLeft = currLogicalLeftOffset;
}
} else {
- bool topToBottom = !style()->isFlippedBlocksWritingMode() ^ colInfo->progressionIsReversed();
+ bool topToBottom = !style()->isFlippedBlocksWritingMode();
LayoutUnit ruleLeft = isHorizontalWritingMode()
? borderLeft() + paddingLeft()
- : colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter());
+ : colGap / 2 - colGap - ruleThickness / 2 + borderBefore() + paddingBefore();
LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness;
LayoutUnit ruleTop = isHorizontalWritingMode()
- ? colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter())
+ ? colGap / 2 - colGap - ruleThickness / 2 + borderBefore() + paddingBefore()
: borderStart() + paddingStart();
LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight();
LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight);
@@ -2072,7 +1888,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p
}
colRect.moveBy(paintOffset);
PaintInfo info(paintInfo);
- info.rect.intersect(pixelSnappedIntRect(colRect));
+ info.rect.intersect(enclosingIntRect(colRect));
if (!info.rect.isEmpty()) {
GraphicsContextStateSaver stateSaver(*context);
@@ -2088,7 +1904,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p
// like overflow:hidden.
// FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element
// are clipped according to the 'overflow' property.
- context->clip(pixelSnappedIntRect(clipRect));
+ context->clip(enclosingIntRect(clipRect));
// Adjust our x and y when painting.
LayoutPoint adjustedPaintOffset = paintOffset + offset;
@@ -2173,31 +1989,42 @@ void RenderBlock::paintAsInlineBlock(RenderObject* renderer, PaintInfo& paintInf
}
}
-bool RenderBlock::hasCaret(CaretType type) const
+static inline bool caretBrowsingEnabled(const Frame* frame)
{
- // Paint the caret if the FrameSelection says so or if caret browsing is enabled
- bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled();
- RenderObject* caretPainter;
- bool isContentEditable;
- if (type == CursorCaret) {
- caretPainter = frame()->selection().caretRenderer();
- isContentEditable = frame()->selection().rendererIsEditable();
- } else {
- caretPainter = frame()->page()->dragCaretController().caretRenderer();
- isContentEditable = frame()->page()->dragCaretController().isContentEditable();
- }
- return caretPainter == this && (isContentEditable || caretBrowsing);
+ Settings* settings = frame->settings();
+ return settings && settings->caretBrowsingEnabled();
}
-void RenderBlock::paintCaret(PaintInfo& paintInfo, const LayoutPoint& paintOffset, CaretType type)
+static inline bool hasCursorCaret(const FrameSelection& selection, const RenderBlock* block, bool caretBrowsing)
{
- if (!hasCaret(type))
- return;
+ return selection.caretRenderer() == block && (selection.rendererIsEditable() || caretBrowsing);
+}
- if (type == CursorCaret)
- frame()->selection().paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
- else
- frame()->page()->dragCaretController().paintDragCaret(frame(), paintInfo.context, paintOffset, paintInfo.rect);
+static inline bool hasDragCaret(const DragCaretController& dragCaretController, const RenderBlock* block, bool caretBrowsing)
+{
+ return dragCaretController.caretRenderer() == block && (dragCaretController.isContentEditable() || caretBrowsing);
+}
+
+bool RenderBlock::hasCaret() const
+{
+ bool caretBrowsing = caretBrowsingEnabled(frame());
+ return hasCursorCaret(frame()->selection(), this, caretBrowsing)
+ || hasDragCaret(frame()->page()->dragCaretController(), this, caretBrowsing);
+}
+
+void RenderBlock::paintCarets(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+ bool caretBrowsing = caretBrowsingEnabled(frame());
+
+ FrameSelection& selection = frame()->selection();
+ if (hasCursorCaret(selection, this, caretBrowsing)) {
+ selection.paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
+ }
+
+ DragCaretController& dragCaretController = frame()->page()->dragCaretController();
+ if (hasDragCaret(dragCaretController, this, caretBrowsing)) {
+ dragCaretController.paintDragCaret(frame(), paintInfo.context, paintOffset, paintInfo.rect);
+ }
}
void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -2287,8 +2114,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
// then paint the caret.
if (paintPhase == PaintPhaseForeground) {
- paintCaret(paintInfo, paintOffset, CursorCaret);
- paintCaret(paintInfo, paintOffset, DragCaret);
+ paintCarets(paintInfo, paintOffset);
}
}
@@ -2383,11 +2209,11 @@ bool RenderBlock::isSelectionRoot() const
if (isTable())
return false;
- if (isBody() || isRoot() || hasOverflowClip()
+ if (isBody() || isDocumentElement() || hasOverflowClip()
|| isPositioned() || isFloating()
|| isTableCell() || isInlineBlockOrInlineTable()
|| hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
- || isRenderFlowThread())
+ || isRenderFlowThread() || isFlexItemIncludingDeprecated())
return true;
if (view() && view()->selectionStart()) {
@@ -2430,17 +2256,16 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintO
LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
if (!gapRectsBounds.isEmpty()) {
- if (RenderLayer* layer = enclosingLayer()) {
- gapRectsBounds.moveBy(-paintOffset);
- if (!hasLayer()) {
- LayoutRect localBounds(gapRectsBounds);
- flipForWritingMode(localBounds);
- gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
- if (layer->renderer()->hasOverflowClip())
- gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
- }
- layer->addBlockSelectionGapsBounds(gapRectsBounds);
+ RenderLayer* layer = enclosingLayer();
+ gapRectsBounds.moveBy(-paintOffset);
+ if (!hasLayer()) {
+ LayoutRect localBounds(gapRectsBounds);
+ flipForWritingMode(localBounds);
+ gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
+ if (layer->renderer()->hasOverflowClip())
+ gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
}
+ layer->addBlockSelectionGapsBounds(gapRectsBounds);
}
}
}
@@ -2490,7 +2315,7 @@ GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& r
rootBlock->flipForWritingMode(flippedBlockRect);
flippedBlockRect.moveBy(rootBlockPhysicalPosition);
clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), positionedObjects());
- if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
+ if (isBody() || isDocumentElement()) // The <body> must make sure to examine its containingBlock's positioned objects.
for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes.
clipOutFloatingObjects(rootBlock, paintInfo, rootBlockPhysicalPosition, offsetFromRootBlock);
@@ -2650,38 +2475,18 @@ void RenderBlock::getSelectionGapInfo(SelectionState state, bool& leftGap, bool&
LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
{
- LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
- if (logicalLeft == logicalLeftOffsetForContent()) {
- if (rootBlock != this)
- // The border can potentially be further extended by our containingBlock().
- return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
- return logicalLeft;
- } else {
- RenderBlock* cb = this;
- while (cb != rootBlock) {
- logicalLeft += cb->logicalLeft();
- cb = cb->containingBlock();
- }
- }
- return logicalLeft;
+ // The border can potentially be further extended by our containingBlock().
+ if (rootBlock != this)
+ return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
+ return logicalLeftOffsetForContent();
}
LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
{
- LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
- if (logicalRight == logicalRightOffsetForContent()) {
- if (rootBlock != this)
- // The border can potentially be further extended by our containingBlock().
- return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
- return logicalRight;
- } else {
- RenderBlock* cb = this;
- while (cb != rootBlock) {
- logicalRight += cb->logicalLeft();
- cb = cb->containingBlock();
- }
- }
- return logicalRight;
+ // The border can potentially be further extended by our containingBlock().
+ if (rootBlock != this)
+ return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
+ return logicalRightOffsetForContent();
}
RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
@@ -2900,7 +2705,7 @@ void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox* descendant)
void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox* parent)
{
ASSERT(gPercentHeightContainerMap);
- for (RenderObject* curr = parent->firstChild(); curr; curr = curr->nextInPreOrder(parent)) {
+ for (RenderObject* curr = parent->slowFirstChild(); curr; curr = curr->nextInPreOrder(parent)) {
if (!curr->isBox())
continue;
@@ -2915,107 +2720,9 @@ void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox* parent)
LayoutUnit RenderBlock::textIndentOffset() const
{
LayoutUnit cw = 0;
- RenderView* renderView = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableLogicalWidth();
- else if (style()->textIndent().isViewportPercentage())
- renderView = view();
- return minimumValueForLength(style()->textIndent(), cw, renderView);
-}
-
-LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region) const
-{
- LayoutUnit logicalLeftOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
- if (!region)
- return logicalLeftOffset;
- LayoutRect boxRect = borderBoxRectInRegion(region);
- return logicalLeftOffset + (isHorizontalWritingMode() ? boxRect.x() : boxRect.y());
-}
-
-LayoutUnit RenderBlock::logicalRightOffsetForContent(RenderRegion* region) const
-{
- LayoutUnit logicalRightOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
- logicalRightOffset += availableLogicalWidth();
- if (!region)
- return logicalRightOffset;
- LayoutRect boxRect = borderBoxRectInRegion(region);
- return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
-}
-
-LayoutUnit RenderBlock::adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
-{
- LayoutUnit left = offsetFromFloats;
-
- if (applyTextIndent && style()->isLeftToRightDirection())
- left += textIndentOffset();
-
- if (style()->lineAlign() == LineAlignNone)
- return left;
-
- // Push in our left offset so that it is aligned with the character grid.
- LayoutState* layoutState = view()->layoutState();
- if (!layoutState)
- return left;
-
- RenderBlock* lineGrid = layoutState->lineGrid();
- if (!lineGrid || lineGrid->style()->writingMode() != style()->writingMode())
- return left;
-
- // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
- float maxCharWidth = lineGrid->style()->font().primaryFont()->maxCharWidth();
- if (!maxCharWidth)
- return left;
-
- LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
- LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
-
- // Push in to the nearest character width.
- // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
- // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
- // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
- // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
- // (https://bugs.webkit.org/show_bug.cgi?id=79944)
- float remainder = fmodf(maxCharWidth - fmodf(left + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
- left += remainder;
- return left;
-}
-
-LayoutUnit RenderBlock::adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
-{
- LayoutUnit right = offsetFromFloats;
-
- if (applyTextIndent && !style()->isLeftToRightDirection())
- right -= textIndentOffset();
-
- if (style()->lineAlign() == LineAlignNone)
- return right;
-
- // Push in our right offset so that it is aligned with the character grid.
- LayoutState* layoutState = view()->layoutState();
- if (!layoutState)
- return right;
-
- RenderBlock* lineGrid = layoutState->lineGrid();
- if (!lineGrid || lineGrid->style()->writingMode() != style()->writingMode())
- return right;
-
- // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
- float maxCharWidth = lineGrid->style()->font().primaryFont()->maxCharWidth();
- if (!maxCharWidth)
- return right;
-
- LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
- LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
-
- // Push in to the nearest character width.
- // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
- // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
- // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
- // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
- // (https://bugs.webkit.org/show_bug.cgi?id=79944)
- float remainder = fmodf(fmodf(right + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
- right -= LayoutUnit::fromFloatCeil(remainder);
- return right;
+ return minimumValueForLength(style()->textIndent(), cw);
}
void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest)
@@ -3042,22 +2749,6 @@ bool RenderBlock::avoidsFloats() const
return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
}
-void RenderBlock::markShapeInsideDescendantsForLayout()
-{
- if (!everHadLayout())
- return;
- if (childrenInline()) {
- setNeedsLayout();
- return;
- }
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->isRenderBlock())
- continue;
- RenderBlock* childBlock = toRenderBlock(child);
- childBlock->markShapeInsideDescendantsForLayout();
- }
-}
-
bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
{
if (!scrollsOverflow())
@@ -3081,24 +2772,53 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
if (!isRenderView()) {
// Check if we need to do anything at all.
- LayoutRect overflowBox = visualOverflowRect();
+ // If we have clipping, then we can't have any spillout.
+ LayoutRect overflowBox = hasOverflowClip() ? borderBoxRect() : visualOverflowRect();
flipForWritingMode(overflowBox);
overflowBox.moveBy(adjustedLocation);
if (!locationInContainer.intersects(overflowBox))
return false;
}
- if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, locationInContainer.point(), adjustedLocation)) {
+ if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)
+ && visibleToHitTestRequest(request)
+ && isPointInOverflowControl(result, locationInContainer.point(), adjustedLocation)) {
updateHitTestResult(result, locationInContainer.point() - localOffset);
// FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer))
return true;
}
+ if (style()->clipPath()) {
+ switch (style()->clipPath()->type()) {
+ case ClipPathOperation::SHAPE: {
+ ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style()->clipPath());
+ // FIXME: handle marginBox etc.
+ if (!clipPath->path(borderBoxRect()).contains(locationInContainer.point() - localOffset, clipPath->windRule()))
+ return false;
+ break;
+ }
+ case ClipPathOperation::REFERENCE:
+ // FIXME: handle REFERENCE
+ break;
+ }
+ }
+
// If we have clipping, then we can't have any spillout.
bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
bool useClip = (hasControlClip() || useOverflowClip);
- bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.intersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region(), IncludeOverlayScrollbarSize)));
+ bool checkChildren = !useClip;
+ if (!checkChildren) {
+ if (hasControlClip()) {
+ checkChildren = locationInContainer.intersects(controlClipRect(adjustedLocation));
+ } else {
+ LayoutRect clipRect = overflowClipRect(adjustedLocation, IncludeOverlayScrollbarSize);
+ if (style()->hasBorderRadius())
+ checkChildren = locationInContainer.intersects(style()->getRoundedBorderFor(clipRect));
+ else
+ checkChildren = locationInContainer.intersects(clipRect);
+ }
+ }
if (checkChildren) {
// Hit test descendants first.
LayoutSize scrolledOffset(localOffset);
@@ -3120,10 +2840,10 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
}
// Check if the point is outside radii.
- if (!isRenderView() && style()->hasBorderRadius()) {
+ if (style()->hasBorderRadius()) {
LayoutRect borderRect = borderBoxRect();
borderRect.moveBy(adjustedLocation);
- RoundedRect border = style()->getRoundedBorderFor(borderRect, view());
+ RoundedRect border = style()->getRoundedBorderFor(borderRect);
if (!locationInContainer.intersects(border))
return false;
}
@@ -3239,9 +2959,6 @@ void RenderBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& loc
bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- if (isRenderRegion())
- return toRenderRegion(this)->hitTestFlowThreadContents(request, result, locationInContainer, accumulatedOffset, hitTestAction);
-
if (childrenInline() && !isTable()) {
// We have to hit-test our line boxes.
if (m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction))
@@ -3266,14 +2983,14 @@ Position RenderBlock::positionForBox(InlineBox *box, bool start) const
if (!box)
return Position();
- if (!box->renderer()->nonPseudoNode())
+ if (!box->renderer().nonPseudoNode())
return createLegacyEditingPosition(nonPseudoNode(), start ? caretMinOffset() : caretMaxOffset());
if (!box->isInlineTextBox())
- return createLegacyEditingPosition(box->renderer()->nonPseudoNode(), start ? box->renderer()->caretMinOffset() : box->renderer()->caretMaxOffset());
+ return createLegacyEditingPosition(box->renderer().nonPseudoNode(), start ? box->renderer().caretMinOffset() : box->renderer().caretMaxOffset());
InlineTextBox* textBox = toInlineTextBox(box);
- return createLegacyEditingPosition(box->renderer()->nonPseudoNode(), start ? textBox->start() : textBox->start() + textBox->len());
+ return createLegacyEditingPosition(box->renderer().nonPseudoNode(), start ? textBox->start() : textBox->start() + textBox->len());
}
static inline bool isEditingBoundary(RenderObject* ancestor, RenderObject* child)
@@ -3385,12 +3102,12 @@ PositionWithAffinity RenderBlock::positionForPointWithInlineChildren(const Layou
}
// pass the box a top position that is inside it
- LayoutPoint point(pointInLogicalContents.x(), closestBox->root()->blockDirectionPointInLine());
+ LayoutPoint point(pointInLogicalContents.x(), closestBox->root().blockDirectionPointInLine());
if (!isHorizontalWritingMode())
point = point.transposedPoint();
- if (closestBox->renderer()->isReplaced())
- return positionForPointRespectingEditingBoundaries(this, toRenderBox(closestBox->renderer()), point);
- return closestBox->renderer()->positionForPoint(point);
+ if (closestBox->renderer().isReplaced())
+ return positionForPointRespectingEditingBoundaries(this, &toRenderBox(closestBox->renderer()), point);
+ return closestBox->renderer().positionForPoint(point);
}
if (lastRootBoxWithChildren) {
@@ -3505,7 +3222,7 @@ void RenderBlock::calcColumnWidth()
LayoutUnit desiredColumnWidth = contentLogicalWidth();
// For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination.
- if (document().paginated() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth()) || !style()->hasInlineColumnAxis()) {
+ if (document().paginated() || !style()->specifiesColumns()) {
setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
return;
}
@@ -3530,12 +3247,12 @@ void RenderBlock::calcColumnWidth()
bool RenderBlock::requiresColumns(int desiredColumnCount) const
{
- // If overflow-y is set to paged-x or paged-y on the body or html element, we'll handle the paginating
- // in the RenderView instead.
- bool isPaginated = (style()->overflowY() == OPAGEDX || style()->overflowY() == OPAGEDY) && !(isRoot() || isBody());
+ // Paged overflow is treated as multicol here, unless this element was the one that got its
+ // overflow propagated to the viewport.
+ bool isPaginated = style()->isOverflowPaged() && node() != document().viewportDefiningElement();
return firstChild()
- && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || !style()->hasInlineColumnAxis() || isPaginated)
+ && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || isPaginated)
&& !firstChild()->isAnonymousColumnsBlock()
&& !firstChild()->isAnonymousColumnSpanBlock();
}
@@ -3559,37 +3276,15 @@ void RenderBlock::setDesiredColumnCountAndWidth(int count, LayoutUnit width)
gColumnInfoMap->add(this, adoptPtr(info));
setHasColumns(true);
}
- info->setDesiredColumnCount(count);
info->setDesiredColumnWidth(width);
- info->setProgressionAxis(style()->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis);
- info->setProgressionIsReversed(style()->columnProgression() == ReverseColumnProgression);
- }
-}
-
-void RenderBlock::updateColumnInfoFromStyle(RenderStyle* style)
-{
- if (!hasColumns())
- return;
-
- ColumnInfo* info = gColumnInfoMap->get(this);
-
- bool needsLayout = false;
- ColumnInfo::Axis oldAxis = info->progressionAxis();
- ColumnInfo::Axis newAxis = style->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis;
- if (oldAxis != newAxis) {
- info->setProgressionAxis(newAxis);
- needsLayout = true;
- }
-
- bool oldProgressionIsReversed = info->progressionIsReversed();
- bool newProgressionIsReversed = style->columnProgression() == ReverseColumnProgression;
- if (oldProgressionIsReversed != newProgressionIsReversed) {
- info->setProgressionIsReversed(newProgressionIsReversed);
- needsLayout = true;
+ if (style()->isOverflowPaged()) {
+ info->setDesiredColumnCount(1);
+ info->setProgressionAxis(style()->hasInlinePaginationAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis);
+ } else {
+ info->setDesiredColumnCount(count);
+ info->setProgressionAxis(ColumnInfo::InlineAxis);
+ }
}
-
- if (needsLayout)
- setNeedsLayoutAndPrefWidthsRecalc();
}
LayoutUnit RenderBlock::desiredColumnWidth() const
@@ -3624,15 +3319,12 @@ LayoutRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const
LayoutUnit colLogicalLeft = logicalLeftOffsetForContent();
LayoutUnit colGap = columnGap();
if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
- if (style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed())
+ if (style()->isLeftToRightDirection())
colLogicalLeft += index * (colLogicalWidth + colGap);
else
colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
} else {
- if (!colInfo->progressionIsReversed())
- colLogicalTop += index * (colLogicalHeight + colGap);
- else
- colLogicalTop += contentLogicalHeight() - colLogicalHeight - index * (colLogicalHeight + colGap);
+ colLogicalTop += index * (colLogicalHeight + colGap);
}
if (isHorizontalWritingMode())
@@ -3640,17 +3332,6 @@ LayoutRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const
return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
}
-bool RenderBlock::relayoutToAvoidWidows(LayoutStateMaintainer& statePusher)
-{
- if (!shouldBreakAtLineToAvoidWidow())
- return false;
-
- statePusher.pop();
- setEverHadLayout(true);
- layoutBlock(false);
- return true;
-}
-
void RenderBlock::adjustPointToColumnContents(LayoutPoint& point) const
{
// Just bail if we have no columns.
@@ -3826,10 +3507,10 @@ void RenderBlock::adjustStartEdgeForWritingModeIncludingColumns(LayoutRect& rect
rect.setX(expandedLogicalHeight - rect.maxX());
}
-void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point) const
+LayoutSize RenderBlock::columnOffset(const LayoutPoint& point) const
{
if (!hasColumns())
- return;
+ return LayoutSize();
ColumnInfo* colInfo = columnInfo();
@@ -3850,30 +3531,29 @@ void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point)
if (isHorizontalWritingMode()) {
if (point.y() >= sliceRect.y() && point.y() < sliceRect.maxY()) {
if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
- offset.expand(columnRectAt(colInfo, i).x() - logicalLeft, -logicalOffset);
- else
- offset.expand(0, columnRectAt(colInfo, i).y() - logicalOffset - borderBefore() - paddingBefore());
- return;
+ return LayoutSize(columnRectAt(colInfo, i).x() - logicalLeft, -logicalOffset);
+ return LayoutSize(0, columnRectAt(colInfo, i).y() - logicalOffset - borderBefore() - paddingBefore());
}
} else {
if (point.x() >= sliceRect.x() && point.x() < sliceRect.maxX()) {
if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
- offset.expand(-logicalOffset, columnRectAt(colInfo, i).y() - logicalLeft);
- else
- offset.expand(columnRectAt(colInfo, i).x() - logicalOffset - borderBefore() - paddingBefore(), 0);
- return;
+ return LayoutSize(-logicalOffset, columnRectAt(colInfo, i).y() - logicalLeft);
+ return LayoutSize(columnRectAt(colInfo, i).x() - logicalOffset - borderBefore() - paddingBefore(), 0);
}
}
}
+
+ return LayoutSize();
}
void RenderBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
if (childrenInline()) {
// FIXME: Remove this const_cast.
- const_cast<RenderBlock*>(this)->computeInlinePreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
- } else
+ toRenderBlockFlow(const_cast<RenderBlock*>(this))->computeInlinePreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
+ } else {
computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
+ }
maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth);
@@ -3937,9 +3617,6 @@ void RenderBlock::computePreferredLogicalWidths()
void RenderBlock::adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
- // FIXME: make this method virtual and move the code to RenderMultiColumnBlock once the old
- // multicol code is gone.
-
if (!style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth()) {
// The min/max intrinsic widths calculated really tell how much space elements need when
// laid out inside the columns. In order to eventually end up with the desired column width,
@@ -3962,429 +3639,6 @@ void RenderBlock::adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalW
}
}
-struct InlineMinMaxIterator {
-/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
- inline min/max width calculations. Note the following about the way it walks:
- (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
- (2) We do not drill into the children of floats or replaced elements, since you can't break
- in the middle of such an element.
- (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
- distinct borders/margin/padding that contribute to the min/max width.
-*/
- RenderObject* parent;
- RenderObject* current;
- bool endOfInline;
-
- InlineMinMaxIterator(RenderObject* p, bool end = false)
- :parent(p), current(p), endOfInline(end) {}
-
- RenderObject* next();
-};
-
-RenderObject* InlineMinMaxIterator::next()
-{
- RenderObject* result = 0;
- bool oldEndOfInline = endOfInline;
- endOfInline = false;
- while (current || current == parent) {
- if (!oldEndOfInline &&
- (current == parent ||
- (!current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned())))
- result = current->firstChild();
- if (!result) {
- // We hit the end of our inline. (It was empty, e.g., <span></span>.)
- if (!oldEndOfInline && current->isRenderInline()) {
- result = current;
- endOfInline = true;
- break;
- }
-
- while (current && current != parent) {
- result = current->nextSibling();
- if (result) break;
- current = current->parent();
- if (current && current != parent && current->isRenderInline()) {
- result = current;
- endOfInline = true;
- break;
- }
- }
- }
-
- if (!result)
- break;
-
- if (!result->isOutOfFlowPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
- break;
-
- current = result;
- result = 0;
- }
-
- // Update our position.
- current = result;
- return current;
-}
-
-static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
-{
- if (cssUnit.type() != Auto)
- return (cssUnit.isFixed() ? static_cast<LayoutUnit>(cssUnit.value()) : childValue);
- return 0;
-}
-
-static LayoutUnit getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
-{
- RenderStyle* childStyle = child->style();
- if (endOfInline)
- return getBPMWidth(child->marginEnd(), childStyle->marginEnd()) +
- getBPMWidth(child->paddingEnd(), childStyle->paddingEnd()) +
- child->borderEnd();
- return getBPMWidth(child->marginStart(), childStyle->marginStart()) +
- getBPMWidth(child->paddingStart(), childStyle->paddingStart()) +
- child->borderStart();
-}
-
-static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
- RenderObject* trailingSpaceChild)
-{
- if (trailingSpaceChild && trailingSpaceChild->isText()) {
- // Collapse away the trailing space at the end of a block.
- RenderText* t = toRenderText(trailingSpaceChild);
- const UChar space = ' ';
- const Font& font = t->style()->font(); // FIXME: This ignores first-line.
- float spaceWidth = font.width(RenderBlockFlow::constructTextRun(t, font, &space, 1, t->style()));
- inlineMax -= spaceWidth + font.wordSpacing();
- if (inlineMin > inlineMax)
- inlineMin = inlineMax;
- }
-}
-
-static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
-{
- LayoutUnit snappedResult = LayoutUnit::fromFloatCeil(result);
- preferredWidth = max(snappedResult, preferredWidth);
-}
-
-// When converting between floating point and LayoutUnits we risk losing precision
-// with each conversion. When this occurs while accumulating our preferred widths,
-// we can wind up with a line width that's larger than our maxPreferredWidth due to
-// pure float accumulation.
-static inline LayoutUnit adjustFloatForSubPixelLayout(float value)
-{
- return LayoutUnit::fromFloatCeil(value);
-}
-
-
-void RenderBlock::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth)
-{
- float inlineMax = 0;
- float inlineMin = 0;
-
- RenderStyle* styleToUse = style();
- RenderBlock* containingBlock = this->containingBlock();
- LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
-
- // 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.
- bool stripFrontSpaces = true;
- RenderObject* trailingSpaceChild = 0;
-
- // Firefox and Opera will allow a table cell to grow to fit an image inside it under
- // very specific cirucumstances (in order to match common WinIE renderings).
- // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
- bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || !styleToUse->logicalWidth().isIntrinsicOrAuto();
-
- bool autoWrap, oldAutoWrap;
- autoWrap = oldAutoWrap = styleToUse->autoWrap();
-
- InlineMinMaxIterator childIterator(this);
-
- // Only gets added to the max preffered width once.
- bool addedTextIndent = false;
- // Signals the text indent was more negative than the min preferred width
- bool hasRemainingNegativeTextIndent = false;
-
- LayoutUnit textIndent = minimumValueForLength(styleToUse->textIndent(), cw, view());
- RenderObject* prevFloat = 0;
- bool isPrevChildInlineFlow = false;
- bool shouldBreakLineAfterText = false;
- while (RenderObject* child = childIterator.next()) {
- autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() :
- child->style()->autoWrap();
-
- if (!child->isBR()) {
- // Step One: determine whether or not we need to go ahead and
- // terminate our current line. Each discrete chunk can become
- // the new min-width, if it is the widest chunk seen so far, and
- // it can also become the max-width.
-
- // Children fall into three categories:
- // (1) An inline flow object. These objects always have a min/max of 0,
- // and are included in the iteration solely so that their margins can
- // be added in.
- //
- // (2) An inline non-text non-flow object, e.g., an inline replaced element.
- // These objects can always be on a line by themselves, so in this situation
- // we need to go ahead and break the current line, and then add in our own
- // margins and min/max width on its own line, and then terminate the line.
- //
- // (3) A text object. Text runs can have breakable characters at the start,
- // the middle or the end. They may also lose whitespace off the front if
- // we're already ignoring whitespace. In order to compute accurate min-width
- // information, we need three pieces of information.
- // (a) the min-width of the first non-breakable run. Should be 0 if the text string
- // starts with whitespace.
- // (b) the min-width of the last non-breakable run. Should be 0 if the text string
- // ends with whitespace.
- // (c) the min/max width of the string (trimmed for whitespace).
- //
- // If the text string starts with whitespace, then we need to go ahead and
- // terminate our current line (unless we're already in a whitespace stripping
- // mode.
- //
- // If the text string has a breakable character in the middle, but didn't start
- // with whitespace, then we add the width of the first non-breakable run and
- // then end the current line. We then need to use the intermediate min/max width
- // values (if any of them are larger than our current min/max). We then look at
- // the width of the last non-breakable run and use that to start a new line
- // (unless we end in whitespace).
- RenderStyle* childStyle = child->style();
- float childMin = 0;
- float childMax = 0;
-
- if (!child->isText()) {
- // Case (1) and (2). Inline replaced and inline flow elements.
- if (child->isRenderInline()) {
- // Add in padding/border/margin from the appropriate side of
- // the element.
- float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
- childMin += bpm;
- childMax += bpm;
-
- inlineMin += childMin;
- inlineMax += childMax;
-
- child->clearPreferredLogicalWidthsDirty();
- } else {
- // Inline replaced elts add in their margins to their min/max values.
- LayoutUnit margins = 0;
- Length startMargin = childStyle->marginStart();
- Length endMargin = childStyle->marginEnd();
- if (startMargin.isFixed())
- margins += adjustFloatForSubPixelLayout(startMargin.value());
- if (endMargin.isFixed())
- margins += adjustFloatForSubPixelLayout(endMargin.value());
- childMin += margins.ceilToFloat();
- childMax += margins.ceilToFloat();
- }
- }
-
- if (!child->isRenderInline() && !child->isText()) {
- // Case (2). Inline replaced elements and floats.
- // Go ahead and terminate the current line as far as
- // minwidth is concerned.
- LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
- if (child->isBox() && child->isHorizontalWritingMode() != isHorizontalWritingMode()) {
- RenderBox* childBox = toRenderBox(child);
- LogicalExtentComputedValues computedValues;
- childBox->computeLogicalHeight(childBox->borderAndPaddingLogicalHeight(), 0, computedValues);
- childMinPreferredLogicalWidth = childMaxPreferredLogicalWidth = computedValues.m_extent;
- } else {
- childMinPreferredLogicalWidth = child->minPreferredLogicalWidth();
- childMaxPreferredLogicalWidth = child->maxPreferredLogicalWidth();
- }
- childMin += childMinPreferredLogicalWidth.ceilToFloat();
- childMax += childMaxPreferredLogicalWidth.ceilToFloat();
-
- bool clearPreviousFloat;
- if (child->isFloating()) {
- clearPreviousFloat = (prevFloat
- && ((prevFloat->style()->floating() == LeftFloat && (childStyle->clear() & CLEFT))
- || (prevFloat->style()->floating() == RightFloat && (childStyle->clear() & CRIGHT))));
- prevFloat = child;
- } else
- clearPreviousFloat = false;
-
- bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
- if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- }
-
- // If we're supposed to clear the previous float, then terminate maxwidth as well.
- if (clearPreviousFloat) {
- updatePreferredWidth(maxLogicalWidth, inlineMax);
- inlineMax = 0;
- }
-
- // Add in text-indent. This is added in only once.
- if (!addedTextIndent && !child->isFloating()) {
- float ceiledTextIndent = textIndent.ceilToFloat();
- childMin += ceiledTextIndent;
- childMax += ceiledTextIndent;
-
- if (childMin < 0)
- textIndent = adjustFloatForSubPixelLayout(childMin);
- else
- addedTextIndent = true;
- }
-
- // Add our width to the max.
- inlineMax += max<float>(0, childMax);
-
- if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
- if (child->isFloating())
- updatePreferredWidth(minLogicalWidth, childMin);
- else
- inlineMin += childMin;
- } else {
- // Now check our line.
- updatePreferredWidth(minLogicalWidth, childMin);
-
- // Now start a new line.
- inlineMin = 0;
- }
-
- if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- }
-
- // We are no longer stripping whitespace at the start of
- // a line.
- if (!child->isFloating()) {
- stripFrontSpaces = false;
- trailingSpaceChild = 0;
- }
- } else if (child->isText()) {
- // Case (3). Text.
- RenderText* t = toRenderText(child);
-
- if (t->isWordBreak()) {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- continue;
- }
-
- if (t->style()->hasTextCombine() && t->isCombineText())
- toRenderCombineText(t)->combineText();
-
- // Determine if we have a breakable character. Pass in
- // whether or not we should ignore any spaces at the front
- // of the string. If those are going to be stripped out,
- // then they shouldn't be considered in the breakable char
- // check.
- bool hasBreakableChar, hasBreak;
- float firstLineMinWidth, lastLineMinWidth;
- bool hasBreakableStart, hasBreakableEnd;
- float firstLineMaxWidth, lastLineMaxWidth;
- t->trimmedPrefWidths(inlineMax,
- firstLineMinWidth, hasBreakableStart, lastLineMinWidth, hasBreakableEnd,
- hasBreakableChar, hasBreak, firstLineMaxWidth, lastLineMaxWidth,
- childMin, childMax, stripFrontSpaces);
-
- // This text object will not be rendered, but it may still provide a breaking opportunity.
- if (!hasBreak && childMax == 0) {
- if (autoWrap && (hasBreakableStart || hasBreakableEnd)) {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- }
- continue;
- }
-
- if (stripFrontSpaces)
- trailingSpaceChild = child;
- else
- trailingSpaceChild = 0;
-
- // Add in text-indent. This is added in only once.
- float ti = 0;
- if (!addedTextIndent || hasRemainingNegativeTextIndent) {
- ti = textIndent.ceilToFloat();
- childMin += ti;
- firstLineMinWidth += ti;
-
- // It the text indent negative and larger than the child minimum, we re-use the remainder
- // in future minimum calculations, but using the negative value again on the maximum
- // will lead to under-counting the max pref width.
- if (!addedTextIndent) {
- childMax += ti;
- firstLineMaxWidth += ti;
- addedTextIndent = true;
- }
-
- if (childMin < 0) {
- textIndent = childMin;
- hasRemainingNegativeTextIndent = true;
- }
- }
-
- // If we have no breakable characters at all,
- // then this is the easy case. We add ourselves to the current
- // min and max and continue.
- if (!hasBreakableChar) {
- inlineMin += childMin;
- } else {
- if (hasBreakableStart) {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- } else {
- inlineMin += firstLineMinWidth;
- updatePreferredWidth(minLogicalWidth, inlineMin);
- childMin -= ti;
- }
-
- inlineMin = childMin;
-
- if (hasBreakableEnd) {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- inlineMin = 0;
- shouldBreakLineAfterText = false;
- } else {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- inlineMin = lastLineMinWidth;
- shouldBreakLineAfterText = true;
- }
- }
-
- if (hasBreak) {
- inlineMax += firstLineMaxWidth;
- updatePreferredWidth(maxLogicalWidth, inlineMax);
- updatePreferredWidth(maxLogicalWidth, childMax);
- inlineMax = lastLineMaxWidth;
- addedTextIndent = true;
- } else {
- inlineMax += max<float>(0, childMax);
- }
- }
-
- // Ignore spaces after a list marker.
- if (child->isListMarker())
- stripFrontSpaces = true;
- } else {
- updatePreferredWidth(minLogicalWidth, inlineMin);
- updatePreferredWidth(maxLogicalWidth, inlineMax);
- inlineMin = inlineMax = 0;
- stripFrontSpaces = true;
- trailingSpaceChild = 0;
- addedTextIndent = true;
- }
-
- if (!child->isText() && child->isRenderInline())
- isPrevChildInlineFlow = true;
- else
- isPrevChildInlineFlow = false;
-
- oldAutoWrap = autoWrap;
- }
-
- if (styleToUse->collapseWhiteSpace())
- stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
-
- updatePreferredWidth(minLogicalWidth, inlineMin);
- updatePreferredWidth(maxLogicalWidth, inlineMax);
-}
-
void RenderBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
RenderStyle* styleToUse = style();
@@ -4491,7 +3745,7 @@ bool RenderBlock::hasLineIfEmpty() const
if (node()->isRootEditableElement())
return true;
- if (node()->isShadowRoot() && toShadowRoot(node())->host()->hasTagName(inputTag))
+ if (node()->isShadowRoot() && isHTMLInputElement(*toShadowRoot(node())->host()))
return true;
return false;
@@ -4506,16 +3760,13 @@ LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction,
if (isReplaced() && linePositionMode == PositionOnContainingLine)
return RenderBox::lineHeight(firstLine, direction, linePositionMode);
- if (firstLine && document().styleEngine()->usesFirstLineRules()) {
- RenderStyle* s = style(firstLine);
- if (s != style())
- return s->computedLineHeight(view());
- }
-
- if (m_lineHeight == -1)
- m_lineHeight = style()->computedLineHeight(view());
+ RenderStyle* s = style(firstLine && document().styleEngine()->usesFirstLineRules());
+ return s->computedLineHeight();
+}
- return m_lineHeight;
+int RenderBlock::beforeMarginInLineDirection(LineDirectionMode direction) const
+{
+ return direction == HorizontalLine ? marginTop() : marginRight();
}
int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
@@ -4524,7 +3775,7 @@ int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, Lin
// the base class. If we're being queried as though we're the root line
// box, then the fact that we're an inline-block is irrelevant, and we behave
// just like a block.
- if (isReplaced() && linePositionMode == PositionOnContainingLine) {
+ if (isInline() && linePositionMode == PositionOnContainingLine) {
// For "leaf" theme objects, let the theme decide what the baseline position is.
// FIXME: Might be better to have a custom CSS property instead, so that if the theme
// is turned off, checkboxes/radios will still have decent baselines.
@@ -4553,7 +3804,7 @@ int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, Lin
baselinePos = -1;
}
if (baselinePos != -1)
- return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
+ return beforeMarginInLineDirection(direction) + baselinePos;
return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
}
@@ -4603,7 +3854,7 @@ int RenderBlock::firstLineBoxBaseline() const
int RenderBlock::inlineBlockBaseline(LineDirectionMode direction) const
{
- if (style()->overflowY() != OVISIBLE) {
+ if (!style()->isOverflowVisible()) {
// We are not calling RenderBox::baselinePosition here because the caller should add the margin-top/margin-right, not us.
return direction == HorizontalLine ? height() + m_marginBox.bottom() : width() + m_marginBox.left();
}
@@ -4663,10 +3914,12 @@ RenderBlock* RenderBlock::firstLineBlock() const
// FIXME: Remove when buttons are implemented with align-items instead
// of flexbox.
if (firstLineBlock->isReplaced() || firstLineBlock->isFloating()
- || !parentBlock || parentBlock->firstChild() != firstLineBlock
+ || !parentBlock
|| (!parentBlock->isRenderBlockFlow() && !parentBlock->isRenderButton()))
break;
ASSERT_WITH_SECURITY_IMPLICATION(parentBlock->isRenderBlock());
+ if (toRenderBlock(parentBlock)->firstChild() != firstLineBlock)
+ break;
firstLineBlock = toRenderBlock(parentBlock);
}
@@ -4699,9 +3952,9 @@ static inline bool isPunctuationForFirstLetter(UChar c)
|| charCategory == Punctuation_Other;
}
-static inline bool shouldSkipForFirstLetter(UChar c)
+static inline bool isSpaceForFirstLetter(UChar c)
{
- return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
+ return isSpaceOrNewline(c) || c == noBreakSpace;
}
static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
@@ -4721,8 +3974,12 @@ static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
return firstLetterBlock;
RenderObject* parentBlock = firstLetterBlock->parent();
- if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||
- (!parentBlock->isRenderBlockFlow() && !parentBlock->isRenderButton()))
+ if (firstLetterBlock->isReplaced() || !parentBlock
+ || (!parentBlock->isRenderBlockFlow() && !parentBlock->isRenderButton())) {
+ return 0;
+ }
+ ASSERT(parentBlock->isRenderBlock());
+ if (toRenderBlock(parentBlock)->firstChild() != firstLetterBlock)
return 0;
firstLetterBlock = parentBlock;
}
@@ -4737,7 +3994,9 @@ void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderO
RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
ASSERT(firstLetter->isFloating() || firstLetter->isInline());
- if (RenderStyle::compare(firstLetter->style(), pseudoStyle) == Reattach) {
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+
+ if (RenderStyle::stylePropagationDiff(firstLetter->style(), pseudoStyle) == Reattach) {
// The first-letter renderer needs to be replaced. Create a new renderer of the right type.
RenderBoxModelObject* newFirstLetter;
if (pseudoStyle->display() == INLINE)
@@ -4747,8 +4006,7 @@ void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderO
newFirstLetter->setStyle(pseudoStyle);
// Move the first letter into the new renderer.
- LayoutStateDisabler layoutStateDisabler(view());
- while (RenderObject* child = firstLetter->firstChild()) {
+ while (RenderObject* child = firstLetter->slowFirstChild()) {
if (child->isText())
toRenderText(child)->removeAndDestroyTextBoxes();
firstLetter->removeChild(child);
@@ -4771,7 +4029,7 @@ void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderO
} else
firstLetter->setStyle(pseudoStyle);
- for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
+ for (RenderObject* genChild = firstLetter->slowFirstChild(); genChild; genChild = genChild->nextSibling()) {
if (genChild->isText())
genChild->setStyle(pseudoStyle);
}
@@ -4780,38 +4038,34 @@ void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderO
static inline unsigned firstLetterLength(const String& text)
{
unsigned length = 0;
- bool punctuationOpen = false;
+ unsigned textLength = text.length();
- // Account for leading spaces and punctuation.
- while (length < text.length() && shouldSkipForFirstLetter((text)[length])) {
- if (isPunctuationForFirstLetter((text)[length]))
- punctuationOpen = true;
+ // Account for leading spaces first.
+ while (length < textLength && isSpaceForFirstLetter(text[length]))
+ length++;
+ // Now account for leading punctuation.
+ while (length < textLength && isPunctuationForFirstLetter(text[length]))
length++;
- }
- // Bail if we didn't find a letter
- if (text.length() && length == text.length())
+ // Bail if we didn't find a letter before the end of the text or before a space.
+ if (isSpaceForFirstLetter(text[length]) || (textLength && length == textLength))
return 0;
- // Account for first letter.
+ // Account the next character for first letter.
length++;
- if (!punctuationOpen)
- return length;
-
- // Keep looking for whitespace and allowed punctuation, but avoid
- // accumulating just whitespace into the :first-letter.
- for (unsigned scanLength = length; scanLength < text.length(); ++scanLength) {
- UChar c = (text)[scanLength];
+ // Keep looking allowed punctuation for the :first-letter.
+ for (unsigned scanLength = length; scanLength < textLength; ++scanLength) {
+ UChar c = text[scanLength];
- if (!shouldSkipForFirstLetter(c))
+ if (!isPunctuationForFirstLetter(c))
break;
- if (isPunctuationForFirstLetter(c))
- length = scanLength + 1;
+ length = scanLength + 1;
}
+ // FIXME: If textLength is 0, length may still be 1!
return length;
}
@@ -4821,14 +4075,18 @@ void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend
RenderObject* firstLetterContainer = currentChild->parent();
RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
- RenderObject* firstLetter = 0;
+ RenderBoxModelObject* firstLetter = 0;
if (pseudoStyle->display() == INLINE)
firstLetter = RenderInline::createAnonymous(&document());
else
firstLetter = RenderBlockFlow::createAnonymous(&document());
firstLetter->setStyle(pseudoStyle);
- firstLetterContainer->addChild(firstLetter, currentChild);
+ // FIXME: The first letter code should not modify the render tree during
+ // layout. crbug.com/370458
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
+
+ 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
@@ -4848,7 +4106,7 @@ void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend
firstLetterContainer->addChild(remainingText, textObj);
firstLetterContainer->removeChild(textObj);
remainingText->setFirstLetter(firstLetter);
- toRenderBoxModelObject(firstLetter)->setFirstLetterRemainingText(remainingText);
+ firstLetter->setFirstLetterRemainingText(remainingText);
// construct text fragment for the first letter
RenderTextFragment* letter =
@@ -4874,7 +4132,7 @@ void RenderBlock::updateFirstLetter()
return;
// Drill into inlines looking for our first text child.
- RenderObject* currChild = firstLetterBlock->firstChild();
+ RenderObject* currChild = firstLetterBlock->slowFirstChild();
unsigned length = 0;
while (currChild) {
if (currChild->isText()) {
@@ -4888,18 +4146,19 @@ void RenderBlock::updateFirstLetter()
currChild = currChild->nextSibling();
} else if (currChild->isFloatingOrOutOfFlowPositioned()) {
if (currChild->style()->styleType() == FIRST_LETTER) {
- currChild = currChild->firstChild();
+ currChild = currChild->slowFirstChild();
break;
}
currChild = currChild->nextSibling();
- } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList())
+ } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList()) {
break;
- else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild->canHaveGeneratedChildren()) {
+ } else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild->canHaveGeneratedChildren()) {
// We found a lower-level node with first-letter, which supersedes the higher-level style
firstLetterBlock = currChild;
- currChild = currChild->firstChild();
- } else
- currChild = currChild->firstChild();
+ currChild = currChild->slowFirstChild();
+ } else {
+ currChild = currChild->slowFirstChild();
+ }
}
if (!currChild)
@@ -4912,12 +4171,14 @@ void RenderBlock::updateFirstLetter()
return;
}
- if (!currChild->isText() || currChild->isBR())
+ // FIXME: This black-list of disallowed RenderText subclasses is fragile.
+ // Should counter be on this list? What about RenderTextFragment?
+ if (!currChild->isText() || currChild->isBR() || toRenderText(currChild)->isWordBreak())
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());
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
createFirstLetterRenderer(firstLetterBlock, currChild, length);
}
@@ -5059,7 +4320,7 @@ void RenderBlock::fitBorderToLinesIfNeeded()
LayoutUnit leftEdge = borderLeft() + paddingLeft();
LayoutUnit rightEdge = leftEdge + oldWidth;
left = min(rightEdge, max(leftEdge, left));
- right = max(leftEdge, min(rightEdge, right));
+ right = max(left, min(rightEdge, right));
LayoutUnit newContentWidth = right - left;
if (newContentWidth == oldWidth)
@@ -5168,17 +4429,18 @@ void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
if (isAnonymousBlockContinuation()) {
// FIXME: This is wrong for block-flows that are horizontal.
// https://bugs.webkit.org/show_bug.cgi?id=46781
- FloatRect localRect(0, -collapsedMarginBefore(),
- width(), height() + collapsedMarginBefore() + collapsedMarginAfter());
+ FloatRect localRect(0, -collapsedMarginBefore().toFloat(),
+ width().toFloat(), (height() + collapsedMarginBefore() + collapsedMarginAfter()).toFloat());
quads.append(localToAbsoluteQuad(localRect, 0 /* mode */, wasFixed));
continuation()->absoluteQuads(quads, wasFixed);
- } else
- quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
+ } else {
+ quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width().toFloat(), height().toFloat()), 0 /* mode */, wasFixed));
+ }
}
-LayoutRect RenderBlock::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
+LayoutRect RenderBlock::rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth) const
{
- LayoutRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+ LayoutRect r(RenderBox::rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineWidth));
if (isAnonymousBlockContinuation())
r.inflateY(collapsedMarginBefore()); // FIXME: This is wrong for block-flows that are horizontal.
return r;
@@ -5196,7 +4458,7 @@ void RenderBlock::updateDragState(bool dragOn)
continuation()->updateDragState(dragOn);
}
-RenderStyle* RenderBlock::outlineStyleForRepaint() const
+RenderStyle* RenderBlock::outlineStyleForPaintInvalidation() const
{
return isAnonymousBlockContinuation() ? continuation()->style() : style();
}
@@ -5240,10 +4502,10 @@ LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, La
LayoutUnit myRight = caretRect.maxX();
// FIXME: why call localToAbsoluteForContent() twice here, too?
- FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
+ FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight.toFloat(), 0));
LayoutUnit containerRight = containingBlock()->x() + containingBlockLogicalWidthForContent();
- FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
+ FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight.toFloat(), 0));
*extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
}
@@ -5264,8 +4526,8 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& a
// FIXME: This is wrong for block-flows that are horizontal.
// https://bugs.webkit.org/show_bug.cgi?id=46781
bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->node()->renderer())->firstLineBox();
- float topMargin = prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit();
- float bottomMargin = nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit();
+ LayoutUnit topMargin = prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit();
+ LayoutUnit bottomMargin = nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit();
LayoutRect rect(additionalOffset.x(), additionalOffset.y() - topMargin, width(), height() + topMargin + bottomMargin);
if (!rect.isEmpty())
rects.append(pixelSnappedIntRect(rect));
@@ -5281,18 +4543,7 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& a
rects.append(pixelSnappedIntRect(rect));
}
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
- RenderBox* box = toRenderBox(curr);
- FloatPoint pos;
- // FIXME: This doesn't work correctly with transforms.
- if (box->layer())
- pos = curr->localToContainerPoint(FloatPoint(), paintContainer);
- else
- pos = FloatPoint(additionalOffset.x() + box->x(), additionalOffset.y() + box->y());
- box->addFocusRingRects(rects, flooredLayoutPoint(pos), paintContainer);
- }
- }
+ addChildFocusRingRects(rects, additionalOffset, paintContainer);
}
if (inlineElementContinuation())
@@ -5324,25 +4575,6 @@ RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* par
return createAnonymousWithParentRendererAndDisplay(parent, style()->display());
}
-bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
-{
- ASSERT(view()->layoutState() && view()->layoutState()->isPaginated());
-
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (!flowThread)
- return true; // Printing and multi-column both make new pages to accommodate content.
-
- // See if we're in the last region.
- LayoutUnit pageOffset = offsetFromLogicalTopOfFirstPage() + logicalOffset;
- RenderRegion* region = flowThread->regionAtBlockOffset(pageOffset, this);
- if (!region)
- return false;
- if (region->isLastRegion())
- return region->isRenderRegionSet() || region->style()->regionFragment() == BreakRegionFragment
- || (pageBoundaryRule == IncludePageBoundary && pageOffset == region->logicalTopForFlowThreadContent());
- return true;
-}
-
LayoutUnit RenderBlock::nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
{
LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
@@ -5356,16 +4588,11 @@ LayoutUnit RenderBlock::nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundar
return logicalOffset + remainingLogicalHeight;
}
-ColumnInfo::PaginationUnit RenderBlock::paginationUnit() const
-{
- return ColumnInfo::Column;
-}
-
LayoutUnit RenderBlock::pageLogicalTopForOffset(LayoutUnit offset) const
{
RenderView* renderView = view();
- LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->m_pageOffset.height() : renderView->layoutState()->m_pageOffset.width();
- LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->m_layoutOffset.height() : renderView->layoutState()->m_layoutOffset.width();
+ LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->pageOffset().height() : renderView->layoutState()->pageOffset().width();
+ LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->layoutOffset().height() : renderView->layoutState()->layoutOffset().width();
LayoutUnit cumulativeOffset = offset + blockLogicalTop;
RenderFlowThread* flowThread = flowThreadContainingBlock();
@@ -5383,7 +4610,7 @@ LayoutUnit RenderBlock::pageLogicalHeightForOffset(LayoutUnit offset) const
RenderView* renderView = view();
RenderFlowThread* flowThread = flowThreadContainingBlock();
if (!flowThread)
- return renderView->layoutState()->m_pageLogicalHeight;
+ return renderView->layoutState()->pageLogicalHeight();
return flowThread->pageLogicalHeightForOffset(offset + offsetFromLogicalTopOfFirstPage());
}
@@ -5394,7 +4621,7 @@ LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, P
RenderFlowThread* flowThread = flowThreadContainingBlock();
if (!flowThread) {
- LayoutUnit pageLogicalHeight = renderView->layoutState()->m_pageLogicalHeight;
+ LayoutUnit pageLogicalHeight = renderView->layoutState()->pageLogicalHeight();
LayoutUnit remainingHeight = pageLogicalHeight - intMod(offset, pageLogicalHeight);
if (pageBoundaryRule == IncludePageBoundary) {
// If includeBoundaryPoint is true the line exactly on the top edge of a
@@ -5409,46 +4636,23 @@ LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, P
LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins)
{
- bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
- bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight;
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
+ bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns() || flowThreadContainingBlock();
+ bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight();
bool isUnsplittable = child->isUnsplittableForPagination() || (checkColumnBreaks && child->style()->columnBreakInside() == PBAVOID)
- || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID)
- || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID);
+ || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID);
if (!isUnsplittable)
return logicalOffset;
LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : LayoutUnit());
LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
- bool hasUniformPageLogicalHeight = !flowThread || flowThread->regionsHaveUniformLogicalHeight();
updateMinimumPageHeight(logicalOffset, childLogicalHeight);
- if (!pageLogicalHeight || (hasUniformPageLogicalHeight && childLogicalHeight > pageLogicalHeight)
- || !hasNextPage(logicalOffset))
+ if (!pageLogicalHeight || childLogicalHeight > pageLogicalHeight)
return logicalOffset;
LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
- if (remainingLogicalHeight < childLogicalHeight) {
- if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, childLogicalHeight))
- return logicalOffset;
+ if (remainingLogicalHeight < childLogicalHeight)
return logicalOffset + remainingLogicalHeight;
- }
return logicalOffset;
}
-bool RenderBlock::pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const
-{
- bool checkRegion = false;
- for (LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset + adjustment); pageLogicalHeight;
- pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset + adjustment)) {
- if (minimumLogicalHeight <= pageLogicalHeight)
- return true;
- if (!hasNextPage(logicalOffset + adjustment))
- return false;
- adjustment += pageLogicalHeight;
- checkRegion = true;
- }
- return !checkRegion;
-}
-
void RenderBlock::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage)
{
if (RenderFlowThread* flowThread = flowThreadContainingBlock())
@@ -5459,7 +4663,7 @@ void RenderBlock::updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeigh
{
if (RenderFlowThread* flowThread = flowThreadContainingBlock())
flowThread->updateMinimumPageHeight(offsetFromLogicalTopOfFirstPage() + offset, minHeight);
- else if (ColumnInfo* colInfo = view()->layoutState()->m_columnInfo)
+ else if (ColumnInfo* colInfo = view()->layoutState()->columnInfo())
colInfo->updateMinimumColumnHeight(minHeight);
}
@@ -5514,8 +4718,7 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, Layout
bool hasUniformPageLogicalHeight = !flowThread || flowThread->regionsHaveUniformLogicalHeight();
// If lineHeight is greater than pageLogicalHeight, but logicalVisualOverflow.height() still fits, we are
// still going to add a strut, so that the visible overflow fits on a single page.
- if (!pageLogicalHeight || (hasUniformPageLogicalHeight && logicalVisualOverflow.height() > pageLogicalHeight)
- || !hasNextPage(logicalOffset))
+ if (!pageLogicalHeight || (hasUniformPageLogicalHeight && logicalVisualOverflow.height() > pageLogicalHeight))
// FIXME: In case the line aligns with the top of the page (or it's slightly shifted downwards) it will not be marked as the first line in the page.
// From here, the fix is not straightforward because it's not easy to always determine when the current line is the first in the page.
return;
@@ -5527,9 +4730,6 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, Layout
clearShouldBreakAtLineToAvoidWidow();
setDidBreakAtLineToAvoidWidow();
}
- // If we have a non-uniform page height, then we have to shift further possibly.
- if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
- return;
if (lineHeight > pageLogicalHeight) {
// Split the top margin in order to avoid splitting the visible part of the line.
remainingLogicalHeight -= min(lineHeight - pageLogicalHeight, max<LayoutUnit>(0, logicalVisualOverflow.y() - lineBox->lineTopWithLeading()));
@@ -5554,34 +4754,6 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, Layout
}
}
-void RenderBlock::updateRegionForLine(RootInlineBox* lineBox) const
-{
- ASSERT(lineBox);
- lineBox->setContainingRegion(regionAtBlockOffset(lineBox->lineTopWithLeading()));
-
- RootInlineBox* prevLineBox = lineBox->prevRootBox();
- if (!prevLineBox)
- return;
-
- // This check is more accurate than the one in |adjustLinePositionForPagination| because it takes into
- // account just the container changes between lines. The before mentioned function doesn't set the flag
- // correctly if the line is positioned at the top of the last fragment container.
- if (lineBox->containingRegion() != prevLineBox->containingRegion())
- lineBox->setIsFirstAfterPageBreak(true);
-}
-
-bool RenderBlock::lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta, RenderFlowThread* flowThread) const
-{
- if (!flowThread)
- return false;
-
- RenderRegion* currentRegion = regionAtBlockOffset(rootBox->lineTopWithLeading() + lineDelta);
- // Just bail if the region didn't change.
- if (rootBox->containingRegion() == currentRegion)
- return false;
- return rootBox->paginatedLineWidth() != availableLogicalWidthForContent(currentRegion);
-}
-
LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
{
LayoutState* layoutState = view()->layoutState();
@@ -5595,7 +4767,7 @@ LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
if (layoutState) {
ASSERT(layoutState->renderer() == this);
- LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
+ LayoutSize offsetDelta = layoutState->layoutOffset() - layoutState->pageOffset();
return isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
}
@@ -5603,47 +4775,6 @@ LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
return 0;
}
-RenderRegion* RenderBlock::regionAtBlockOffset(LayoutUnit blockOffset) const
-{
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (!flowThread || !flowThread->hasValidRegionInfo())
- return 0;
-
- return flowThread->regionAtBlockOffset(offsetFromLogicalTopOfFirstPage() + blockOffset, true);
-}
-
-bool RenderBlock::logicalWidthChangedInRegions(RenderFlowThread* flowThread) const
-{
- if (!flowThread || !flowThread->hasValidRegionInfo())
- return false;
-
- return flowThread->logicalWidthChangedInRegionsForBlock(this);
-}
-
-RenderRegion* RenderBlock::clampToStartAndEndRegions(RenderRegion* region) const
-{
- RenderFlowThread* flowThread = flowThreadContainingBlock();
-
- ASSERT(isRenderView() || (region && flowThread));
- if (isRenderView())
- return region;
-
- // We need to clamp to the block, since we want any lines or blocks that overflow out of the
- // logical top or logical bottom of the block to size as though the border box in the first and
- // last regions extended infinitely. Otherwise the lines are going to size according to the regions
- // they overflow into, which makes no sense when this block doesn't exist in |region| at all.
- RenderRegion* startRegion;
- RenderRegion* endRegion;
- flowThread->getRegionRangeForBox(this, startRegion, endRegion);
-
- if (startRegion && region->logicalTopForFlowThreadContent() < startRegion->logicalTopForFlowThreadContent())
- return startRegion;
- if (endRegion && region->logicalTopForFlowThreadContent() > endRegion->logicalTopForFlowThreadContent())
- return endRegion;
-
- return region;
-}
-
LayoutUnit RenderBlock::collapsedMarginBeforeForChild(const RenderBox* child) const
{
// If the child has the same directionality as we do, then we can just return its
@@ -5781,6 +4912,91 @@ RenderBlockFlow* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const
return newBox;
}
+static bool recalcNormalFlowChildOverflowIfNeeded(RenderObject* renderer)
+{
+ if (renderer->isOutOfFlowPositioned() || !renderer->needsOverflowRecalcAfterStyleChange())
+ return false;
+
+ ASSERT(renderer->isRenderBlock());
+ return toRenderBlock(renderer)->recalcOverflowAfterStyleChange();
+}
+
+bool RenderBlock::recalcChildOverflowAfterStyleChange()
+{
+ ASSERT(childNeedsOverflowRecalcAfterStyleChange());
+ setChildNeedsOverflowRecalcAfterStyleChange(false);
+
+ bool childrenOverflowChanged = false;
+
+ if (childrenInline()) {
+ ListHashSet<RootInlineBox*> lineBoxes;
+ for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
+ RenderObject* renderer = walker.current();
+ if (recalcNormalFlowChildOverflowIfNeeded(renderer)) {
+ childrenOverflowChanged = true;
+ if (InlineBox* inlineBoxWrapper = toRenderBlock(renderer)->inlineBoxWrapper())
+ lineBoxes.add(&inlineBoxWrapper->root());
+ }
+ }
+
+ // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
+ GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+ for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
+ RootInlineBox* box = *it;
+ box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
+ }
+ } else {
+ for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
+ if (recalcNormalFlowChildOverflowIfNeeded(box))
+ childrenOverflowChanged = true;
+ }
+ }
+
+ TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+ if (!positionedDescendants)
+ return childrenOverflowChanged;
+
+ TrackedRendererListHashSet::iterator end = positionedDescendants->end();
+ for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
+ RenderBox* box = *it;
+
+ if (!box->needsOverflowRecalcAfterStyleChange())
+ continue;
+ RenderBlock* block = toRenderBlock(box);
+ if (!block->recalcOverflowAfterStyleChange() || box->style()->position() == FixedPosition)
+ continue;
+
+ childrenOverflowChanged = true;
+ }
+ return childrenOverflowChanged;
+}
+
+bool RenderBlock::recalcOverflowAfterStyleChange()
+{
+ ASSERT(needsOverflowRecalcAfterStyleChange());
+
+ bool childrenOverflowChanged = false;
+ if (childNeedsOverflowRecalcAfterStyleChange())
+ childrenOverflowChanged = recalcChildOverflowAfterStyleChange();
+
+ if (!selfNeedsOverflowRecalcAfterStyleChange() && !childrenOverflowChanged)
+ return false;
+
+ setSelfNeedsOverflowRecalcAfterStyleChange(false);
+ // If the current block needs layout, overflow will be recalculated during
+ // layout time anyway. We can safely exit here.
+ if (needsLayout())
+ return false;
+
+ LayoutUnit oldClientAfterEdge = hasRenderOverflow() ? m_overflow->layoutClientAfterEdge() : clientLogicalBottom();
+ computeOverflow(oldClientAfterEdge, true);
+
+ if (hasOverflowClip())
+ layer()->scrollableArea()->updateAfterOverflowRecalc();
+
+ return !hasOverflowClip();
+}
+
#ifndef NDEBUG
void RenderBlock::checkPositionedObjectsNeedLayout()
{
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.h b/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.h
index cd090231993..c3ce2fb32a9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBlock.h
@@ -29,7 +29,6 @@
#include "core/rendering/RenderBox.h"
#include "core/rendering/RenderLineBoxList.h"
#include "core/rendering/RootInlineBox.h"
-#include "core/rendering/shapes/ShapeInsideInfo.h"
#include "core/rendering/style/ShapeValue.h"
#include "platform/text/TextBreakIterator.h"
#include "platform/text/TextRun.h"
@@ -38,32 +37,21 @@
namespace WebCore {
-class BasicShape;
-class BidiContext;
-class InlineIterator;
-class LayoutStateMaintainer;
class LineLayoutState;
class RenderInline;
-class RenderText;
-struct BidiRun;
struct PaintInfo;
+class WordMeasurement;
+
class LineInfo;
class RenderRubyRun;
-class TextLayout;
-class WordMeasurement;
-template <class Iterator, class Run> class BidiResolver;
template <class Run> class BidiRunList;
-template <class Iterator> struct MidpointState;
-typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
-typedef MidpointState<InlineIterator> LineMidpointState;
typedef WTF::ListHashSet<RenderBox*, 16> TrackedRendererListHashSet;
typedef WTF::HashMap<const RenderBlock*, OwnPtr<TrackedRendererListHashSet> > TrackedDescendantsMap;
typedef WTF::HashMap<const RenderBox*, OwnPtr<HashSet<RenderBlock*> > > TrackedContainerMap;
typedef Vector<WordMeasurement, 64> WordMeasurements;
-enum CaretType { CursorCaret, DragCaret };
enum ContainingBlockState { NewContainingBlock, SameContainingBlock };
enum TextRunFlag {
@@ -86,6 +74,10 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderBlock, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
@@ -93,7 +85,7 @@ public:
// These two functions are overridden for inline-block.
virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE FINAL;
- virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+ virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
LayoutUnit minLineHeightForReplacedRenderer(bool isFirstLine, LayoutUnit replacedHeight) const;
@@ -105,10 +97,10 @@ public:
// FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
virtual void deleteLineBoxTree();
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject*);
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject*) OVERRIDE;
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
+ virtual void layoutBlock(bool relayoutChildren);
void insertPositionedObject(RenderBox*);
static void removePositionedObject(RenderBox*);
@@ -123,12 +115,18 @@ public:
void addPercentHeightDescendant(RenderBox*);
static void removePercentHeightDescendant(RenderBox*);
- TrackedRendererListHashSet* percentHeightDescendants() const;
static bool hasPercentHeightContainerMap();
static bool hasPercentHeightDescendant(RenderBox*);
static void clearPercentHeightDescendantsFrom(RenderBox*);
static void removePercentHeightDescendantIfNeeded(RenderBox*);
+ TrackedRendererListHashSet* percentHeightDescendants() const;
+ bool hasPercentHeightDescendants() const
+ {
+ TrackedRendererListHashSet* descendants = percentHeightDescendants();
+ return descendants && !descendants->isEmpty();
+ }
+
void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; }
bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
@@ -141,9 +139,6 @@ public:
bool hasMarginBeforeQuirk(const RenderBox* child) const;
bool hasMarginAfterQuirk(const RenderBox* child) const;
- RootInlineBox* createAndAppendRootInlineBox();
-
- void markShapeInsideDescendantsForLayout();
void markPositionedObjectsForLayout();
// FIXME: Do we really need this to be virtual? It's just so we can call this on
// RenderBoxes without needed to check whether they're RenderBlocks first.
@@ -152,67 +147,6 @@ public:
// FIXME-BLOCKFLOW: Remove virtualizaion when all of the line layout code has been moved out of RenderBlock
virtual bool containsFloats() const { return false; }
- // Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to
- // compute the region all over again when you already know it.
- LayoutUnit availableLogicalWidthForLineInRegion(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
- {
- return max<LayoutUnit>(0, logicalRightOffsetForLineInRegion(position, shouldIndentText, region, logicalHeight)
- - logicalLeftOffsetForLineInRegion(position, shouldIndentText, region, logicalHeight));
- }
- LayoutUnit logicalRightOffsetForLineInRegion(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
- {
- return logicalRightOffsetForLine(position, logicalRightOffsetForContent(region), shouldIndentText, logicalHeight);
- }
- LayoutUnit logicalLeftOffsetForLineInRegion(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
- {
- return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(region), shouldIndentText, logicalHeight);
- }
- LayoutUnit startOffsetForLineInRegion(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
- {
- return style()->isLeftToRightDirection() ? logicalLeftOffsetForLineInRegion(position, shouldIndentText, region, logicalHeight)
- : logicalWidth() - logicalRightOffsetForLineInRegion(position, shouldIndentText, region, logicalHeight);
- }
- LayoutUnit endOffsetForLineInRegion(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
- {
- return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLineInRegion(position, shouldIndentText, region, logicalHeight)
- : logicalWidth() - logicalRightOffsetForLineInRegion(position, shouldIndentText, region, logicalHeight);
- }
-
- LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
- {
- return availableLogicalWidthForLineInRegion(position, shouldIndentText, regionAtBlockOffset(position), logicalHeight);
- }
- LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
- {
- return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), shouldIndentText, logicalHeight);
- }
- LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
- {
- return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), shouldIndentText, logicalHeight);
- }
- LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
- {
- return roundToInt(logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
- }
- LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) 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.
- // https://bugs.webkit.org/show_bug.cgi?id=105461
- return floorToInt(logicalRightOffsetForLine(position, shouldIndentText, logicalHeight));
- }
- LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
- {
- return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
- : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
- }
- LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
- {
- return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
- : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
- }
-
LayoutUnit textIndentOffset() const;
virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
@@ -229,6 +163,7 @@ public:
RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
+ virtual bool shouldPaintSelectionGaps() const OVERRIDE FINAL;
GapRects selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer);
LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
@@ -246,7 +181,7 @@ public:
void clearTruncation();
void adjustRectForColumns(LayoutRect&) const;
- virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const OVERRIDE FINAL;
+ virtual LayoutSize columnOffset(const LayoutPoint&) const OVERRIDE;
void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const;
void addContinuationWithOutline(RenderInline*);
@@ -272,8 +207,6 @@ public:
ColumnInfo* columnInfo() const;
int columnGap() const;
- void updateColumnInfoFromStyle(RenderStyle*);
-
// These two functions take the ColumnInfo* to avoid repeated lookups of the info in the global HashMap.
unsigned columnCount(ColumnInfo*) const;
LayoutRect columnRectAt(ColumnInfo*, unsigned) const;
@@ -295,12 +228,10 @@ public:
void setPageLogicalOffset(LayoutUnit);
// Accessors for logical width/height and margins in the containing block's block-flow direction.
- enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
LayoutUnit logicalWidthForChild(const RenderBox* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); }
LayoutUnit logicalHeightForChild(const RenderBox* child) const { return isHorizontalWritingMode() ? child->height() : child->width(); }
+ LayoutSize logicalSizeForChild(const RenderBox* child) const { return isHorizontalWritingMode() ? child->size() : child->size().transposedSize(); }
LayoutUnit logicalTopForChild(const RenderBox* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); }
- void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
- void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const { return child->marginBefore(style()); }
LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const { return child->marginAfter(style()); }
LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const { return child->marginStart(style()); }
@@ -313,125 +244,67 @@ public:
LayoutUnit collapsedMarginAfterForChild(const RenderBox* child) const;
virtual void updateFirstLetter();
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { };
+ virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { }
- LayoutUnit logicalLeftOffsetForContent(RenderRegion*) const;
- LayoutUnit logicalRightOffsetForContent(RenderRegion*) const;
- LayoutUnit availableLogicalWidthForContent(RenderRegion* region) const
- {
- return max<LayoutUnit>(0, logicalRightOffsetForContent(region) - logicalLeftOffsetForContent(region));
- }
- LayoutUnit startOffsetForContent(RenderRegion* region) const
- {
- return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region) : logicalWidth() - logicalRightOffsetForContent(region);
- }
- LayoutUnit endOffsetForContent(RenderRegion* region) const
- {
- return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region) : logicalWidth() - logicalRightOffsetForContent(region);
- }
- LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const
- {
- return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset));
- }
- LayoutUnit logicalRightOffsetForContent(LayoutUnit blockOffset) const
- {
- return logicalRightOffsetForContent(regionAtBlockOffset(blockOffset));
- }
- LayoutUnit availableLogicalWidthForContent(LayoutUnit blockOffset) const
- {
- return availableLogicalWidthForContent(regionAtBlockOffset(blockOffset));
- }
- LayoutUnit startOffsetForContent(LayoutUnit blockOffset) const
- {
- return startOffsetForContent(regionAtBlockOffset(blockOffset));
- }
- LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const
- {
- return endOffsetForContent(regionAtBlockOffset(blockOffset));
- }
+ LayoutUnit availableLogicalWidthForContent() const { return max<LayoutUnit>(0, logicalRightOffsetForContent() - logicalLeftOffsetForContent()); }
LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); }
LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
- LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0);
-
#ifndef NDEBUG
void checkPositionedObjectsNeedLayout();
void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
#endif
- ShapeInsideInfo* ensureShapeInsideInfo()
- {
- if (!m_rareData || !m_rareData->m_shapeInsideInfo)
- setShapeInsideInfo(ShapeInsideInfo::createInfo(this));
- return m_rareData->m_shapeInsideInfo.get();
- }
- ShapeInsideInfo* shapeInsideInfo() const
- {
- return m_rareData && m_rareData->m_shapeInsideInfo && ShapeInsideInfo::isEnabledFor(this) ? m_rareData->m_shapeInsideInfo.get() : 0;
- }
- void setShapeInsideInfo(PassOwnPtr<ShapeInsideInfo> value)
- {
- if (!m_rareData)
- m_rareData = adoptPtr(new RenderBlockRareData());
- m_rareData->m_shapeInsideInfo = value;
- }
- ShapeInsideInfo* layoutShapeInsideInfo() const;
- bool allowsShapeInsideInfoSharing(const RenderBlock* other) const;
- LayoutSize logicalOffsetFromShapeAncestorContainer(const RenderBlock* container) const;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
-
// inline-block elements paint all phases atomically. This function ensures that. Certain other elements
// (grid items, flex items) require this behavior as well, and this function exists as a helper for them.
// It is expected that the caller will call this function independent of the value of paintInfo.phase.
static void paintAsInlineBlock(RenderObject*, PaintInfo&, const LayoutPoint&);
+
+ bool recalcChildOverflowAfterStyleChange();
+ bool recalcOverflowAfterStyleChange();
+
protected:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
void dirtyForLayoutFromPercentageHeightDescendants(SubtreeLayoutScope&);
- virtual void layout();
- virtual void didLayout(ResourceLoadPriorityOptimizer&);
- virtual void didScroll(ResourceLoadPriorityOptimizer&);
- void updateStyleImageLoadingPriorities(ResourceLoadPriorityOptimizer&);
+ virtual void layout() OVERRIDE;
+ virtual bool updateImageLoadingPriorities() OVERRIDE FINAL;
+
+ enum PositionedLayoutBehavior {
+ DefaultLayout,
+ LayoutOnlyFixedPositionedObjects,
+ ForcedLayoutAfterContainingBlockMoved
+ };
- void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false);
+ void layoutPositionedObjects(bool relayoutChildren, PositionedLayoutBehavior = DefaultLayout);
void markFixedPositionObjectForLayoutIfNeeded(RenderObject* child, SubtreeLayoutScope&);
LayoutUnit marginIntrinsicLogicalWidthForChild(RenderBox* child) const;
- virtual bool supportsPartialLayout() const OVERRIDE { return true; };
+ int beforeMarginInLineDirection(LineDirectionMode) const;
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual void paintObject(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual void paintChildren(PaintInfo&, const LayoutPoint&);
void paintChild(RenderBox*, PaintInfo&, const LayoutPoint&);
void paintChildAsInlineBlock(RenderBox*, PaintInfo&, const LayoutPoint&);
- LayoutUnit logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
- {
- return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
- }
- LayoutUnit logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
- {
- return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
- }
-
- virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
-
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual void adjustInlineDirectionLineBounds(unsigned /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE;
void adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
- virtual int firstLineBoxBaseline() const;
+ virtual int firstLineBoxBaseline() const OVERRIDE;
virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE;
int lastLineBoxBaseline(LineDirectionMode) const;
- virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
+ virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) OVERRIDE;
// Delay update scrollbar until finishDelayRepaint() will be
// called. This function is used when a flexbox is laying out its
@@ -443,8 +316,8 @@ protected:
void updateScrollInfoAfterLayout();
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
virtual bool hasLineIfEmpty() const;
@@ -465,32 +338,19 @@ protected:
virtual void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const OVERRIDE;
- bool updateRegionsAndShapesLogicalSize(RenderFlowThread*);
void computeRegionRangeForBlock(RenderFlowThread*);
void updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox*);
- virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
-
virtual bool isInlineBlockOrInlineTable() const OVERRIDE FINAL { return isInline() && isReplaced(); }
-private:
- // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
- virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit, LayoutUnit fixedOffset, LayoutUnit) const { return fixedOffset; }
- // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
- virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit, LayoutUnit fixedOffset, LayoutUnit) const { return fixedOffset; }
- LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
- LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
-
- void computeShapeSize();
- void updateRegionsAndShapesAfterChildLayout(RenderFlowThread*, bool);
- void updateShapeInsideInfoAfterStyleChange(const ShapeValue*, const ShapeValue* oldShape);
- void relayoutShapeDescendantIfMoved(RenderBlock* child, LayoutSize offset);
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE;
+private:
virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
- virtual const char* renderName() const;
+ virtual const char* renderName() const OVERRIDE;
virtual bool isRenderBlock() const OVERRIDE FINAL { return true; }
@@ -498,27 +358,20 @@ private:
virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
static void collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock* child);
- // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
- virtual void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) { moveAllChildrenTo(toBlock, fullRemoveInsert); }
virtual void dirtyLinesFromChangedChild(RenderObject* child) OVERRIDE FINAL { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
- void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild);
+ virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild) OVERRIDE;
void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild);
void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual bool isSelfCollapsingBlock() const OVERRIDE FINAL;
+ virtual bool isSelfCollapsingBlock() const OVERRIDE;
void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
- virtual RootInlineBox* createRootInlineBox() { return 0; } // Subclassed by RenderBlockFlow, SVG and Ruby.
-
- // Called to lay out the legend for a fieldset or the ruby text of a ruby run.
- virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/, SubtreeLayoutScope&) { return 0; }
-
void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild, unsigned length);
void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
@@ -530,12 +383,11 @@ private:
void paintColumnContents(PaintInfo&, const LayoutPoint&, bool paintFloats = false);
void paintColumnRules(PaintInfo&, const LayoutPoint&);
void paintSelection(PaintInfo&, const LayoutPoint&);
- void paintCaret(PaintInfo&, const LayoutPoint&, CaretType);
+ void paintCarets(PaintInfo&, const LayoutPoint&);
- bool hasCaret() const { return hasCaret(CursorCaret) || hasCaret(DragCaret); }
- bool hasCaret(CaretType) const;
+ bool hasCaret() const;
- virtual bool avoidsFloats() const;
+ virtual bool avoidsFloats() const OVERRIDE;
bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
@@ -544,26 +396,23 @@ private:
virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
- // FIXME: Make this method const so we can remove the const_cast in computeIntrinsicLogicalWidths.
- void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
void computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
// Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
// children.
- virtual RenderBlock* firstLineBlock() const;
+ virtual RenderBlock* firstLineBlock() const OVERRIDE;
- virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL;
- virtual RenderStyle* outlineStyleForRepaint() const OVERRIDE FINAL;
+ virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL;
+ virtual RenderStyle* outlineStyleForPaintInvalidation() const OVERRIDE FINAL;
virtual RenderObject* hoverAncestor() const OVERRIDE FINAL;
virtual void updateDragState(bool dragOn) OVERRIDE FINAL;
virtual void childBecameNonInline(RenderObject* child) OVERRIDE FINAL;
- virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool /*clipToVisibleContent*/) OVERRIDE FINAL
+ virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool /*clipToVisibleContent*/) OVERRIDE FINAL
{
- return selectionGapRectsForRepaint(repaintContainer);
+ return selectionGapRectsForRepaint(paintInvalidationContainer);
}
- virtual bool shouldPaintSelectionGaps() const OVERRIDE FINAL;
bool isSelectionRoot() const;
GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* = 0);
@@ -571,14 +420,14 @@ private:
LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*);
- LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
- LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
+ virtual LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
+ virtual LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
// FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
virtual void clipOutFloatingObjects(RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) { };
- virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
LayoutUnit desiredColumnWidth() const;
@@ -596,11 +445,9 @@ private:
Position positionForBox(InlineBox*, bool start = true) const;
PositionWithAffinity positionForPointWithInlineChildren(const LayoutPoint&);
- virtual void calcColumnWidth();
+ void calcColumnWidth();
void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlockFlow* newBlockBox, RenderObject* newChild);
- bool expandsToEncloseOverhangingFloats() const;
-
void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont);
void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
@@ -613,11 +460,6 @@ private:
// End helper functions and structs used by layoutBlockChildren.
protected:
- void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
-
- // Pagination routines.
- bool relayoutToAvoidWidows(LayoutStateMaintainer&);
-
// Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page,
// then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with
// IncludePageBoundary set will not.
@@ -625,9 +467,8 @@ protected:
// For a page height of 800px, the first rule will return 800 if the value passed in is 0. The second rule will simply return 0.
enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
- bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
- virtual ColumnInfo::PaginationUnit paginationUnit() const;
+ bool createsBlockFormattingContext() const;
public:
LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
@@ -635,8 +476,6 @@ public:
LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
protected:
- bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
-
// A page break is required at some offset due to space shortage in the current fragmentainer.
void setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage);
@@ -647,19 +486,11 @@ protected:
LayoutUnit adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins = false); // If the child is unsplittable and can't fit on the current page, return the top of the next page/column.
void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page.
- void updateRegionForLine(RootInlineBox*) const;
// Adjust from painting offsets to the local coords of this renderer
void offsetForContents(LayoutPoint&) const;
- // This function is called to test a line box that has moved in the block direction to see if it has ended up in a new
- // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a
- // line, i.e., that it can't be re-used.
- bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const;
-
- bool logicalWidthChangedInRegions(RenderFlowThread*) const;
-
- virtual bool requiresColumns(int desiredColumnCount) const;
+ bool requiresColumns(int desiredColumnCount) const;
virtual bool updateLogicalWidthAndColumnWidth();
@@ -667,8 +498,6 @@ protected:
public:
virtual LayoutUnit offsetFromLogicalTopOfFirstPage() const OVERRIDE FINAL;
- RenderRegion* regionAtBlockOffset(LayoutUnit) const;
- RenderRegion* clampToStartAndEndRegions(RenderRegion*) const;
public:
@@ -687,9 +516,8 @@ public:
LayoutUnit m_paginationStrut;
LayoutUnit m_pageLogicalOffset;
- int m_lineBreakToAvoidWidow;
- OwnPtr<ShapeInsideInfo> m_shapeInsideInfo;
- bool m_didBreakAtLineToAvoidWidow : 1;
+ int m_lineBreakToAvoidWidow : 31;
+ unsigned m_didBreakAtLineToAvoidWidow : 1;
};
protected:
@@ -698,12 +526,13 @@ 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 : 27;
+ // WARNING: Don't add any bits here until we are comfortable that removing m_lineHeight has not regressed performance. See http://crrev.com/260073005 for more information.
unsigned m_hasMarginBeforeQuirk : 1; // Note these quirk values can't be put in RenderBlockRareData since they are set too frequently.
unsigned m_hasMarginAfterQuirk : 1;
unsigned m_beingDestroyed : 1;
unsigned m_hasMarkupTruncation : 1;
unsigned m_hasBorderOrPaddingLogicalWidthChanged : 1;
+ mutable unsigned m_hasOnlySelfCollapsingChildren : 1;
// RenderRubyBase objects need to be able to split and merge, moving their children around
// (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
@@ -716,20 +545,6 @@ protected:
friend class RenderBlockFlow;
};
-
-inline bool RenderBlock::allowsShapeInsideInfoSharing(const RenderBlock* other) const
-{
- if (!other)
- return false;
- for (const RenderBlock* current = this; current && current != other && !current->isRenderFlowThread(); current = current->containingBlock()) {
- if (current->isInline() || current->isFloating())
- return false;
- if (current->parent() != current->containingBlock())
- return false;
- }
- return true;
-}
-
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderBlock, isRenderBlock());
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.cpp
index 96725842afd..0a731d49857 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.cpp
@@ -31,19 +31,19 @@
#include "config.h"
#include "core/rendering/RenderBlockFlow.h"
+#include "core/accessibility/AXObjectCache.h"
#include "core/frame/FrameView.h"
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/HitTestLocation.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
-#include "core/rendering/LineWidth.h"
+#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderNamedFlowFragment.h"
-#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderMultiColumnFlowThread.h"
#include "core/rendering/RenderText.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/line/LineWidth.h"
#include "core/rendering/svg/SVGTextRunRenderingContext.h"
-#include "platform/text/BidiResolver.h"
-#include "platform/text/TextRunIterator.h"
+#include "platform/text/BidiTextRun.h"
using namespace std;
@@ -63,6 +63,7 @@ class MarginInfo {
bool m_canCollapseWithChildren : 1;
bool m_canCollapseMarginBeforeWithChildren : 1;
bool m_canCollapseMarginAfterWithChildren : 1;
+ bool m_canCollapseMarginAfterWithLastChild: 1;
// Whether or not we are a quirky container, i.e., do we collapse away top and bottom
// margins in our container. Table cells and the body are the common examples. We
@@ -120,6 +121,7 @@ public:
void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; }
void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
+ void setCanCollapseMarginAfterWithLastChild(bool collapse) { m_canCollapseMarginAfterWithLastChild = collapse; }
void setDiscardMargin(bool value) { m_discardMargin = value; }
bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
@@ -127,6 +129,7 @@ public:
bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
+ bool canCollapseMarginAfterWithLastChild() const { return m_canCollapseMarginAfterWithLastChild; }
bool quirkContainer() const { return m_quirkContainer; }
bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
@@ -136,7 +139,6 @@ public:
bool discardMargin() const { return m_discardMargin; }
LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
};
-
static bool inNormalFlow(RenderBox* child)
{
RenderBlock* curr = child->containingBlock();
@@ -168,113 +170,187 @@ RenderBlockFlow* RenderBlockFlow::createAnonymous(Document* document)
return renderer;
}
-RenderBlockFlow* RenderBlockFlow::createAnonymousBlockFlow() const
+RenderObject* RenderBlockFlow::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope& layoutScope)
{
- return toRenderBlockFlow(createAnonymousWithParentRendererAndDisplay(this, BLOCK));
+ RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread();
+ if (!flowThread)
+ return 0;
+ setLogicalTopForChild(flowThread, borderBefore() + paddingBefore());
+ flowThread->layoutColumns(relayoutChildren, layoutScope);
+ determineLogicalLeftPositionForChild(flowThread);
+ return flowThread;
}
-void RenderBlockFlow::willBeDestroyed()
+bool RenderBlockFlow::updateLogicalWidthAndColumnWidth()
{
- if (lineGridBox())
- lineGridBox()->destroy();
+ bool relayoutChildren = RenderBlock::updateLogicalWidthAndColumnWidth();
+ if (RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread()) {
+ if (flowThread->needsNewWidth())
+ return true;
+ }
+ return relayoutChildren;
+}
+
+void RenderBlockFlow::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
+{
+ if (RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread()) {
+ LogicalExtentComputedValues computedValues;
+ computeLogicalHeight(LayoutUnit(), logicalTop(), computedValues);
+ LayoutUnit columnHeight = computedValues.m_extent - borderAndPaddingLogicalHeight() - scrollbarLogicalHeight();
+ pageLogicalHeightChanged = columnHeight != flowThread->columnHeightAvailable();
+ flowThread->setColumnHeightAvailable(std::max<LayoutUnit>(columnHeight, 0));
+ } else if (hasColumns()) {
+ ColumnInfo* colInfo = columnInfo();
+
+ if (!pageLogicalHeight) {
+ LayoutUnit oldLogicalHeight = logicalHeight();
+ setLogicalHeight(0);
+ // We need to go ahead and set our explicit page height if one exists, so that we can
+ // avoid doing two layout passes.
+ updateLogicalHeight();
+ LayoutUnit columnHeight = contentLogicalHeight();
+ if (columnHeight > 0) {
+ pageLogicalHeight = columnHeight;
+ hasSpecifiedPageLogicalHeight = true;
+ }
+ setLogicalHeight(oldLogicalHeight);
+ }
+ if (colInfo->columnHeight() != pageLogicalHeight && everHadLayout()) {
+ colInfo->setColumnHeight(pageLogicalHeight);
+ pageLogicalHeightChanged = true;
+ }
- if (renderNamedFlowFragment())
- setRenderNamedFlowFragment(0);
+ if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
+ colInfo->clearForcedBreaks();
+ } else if (isRenderFlowThread()) {
+ RenderFlowThread* flowThread = toRenderFlowThread(this);
- RenderBlock::willBeDestroyed();
+ // FIXME: This is a hack to always make sure we have a page logical height, if said height
+ // is known. The page logical height thing in LayoutState is meaningless for flow
+ // thread-based pagination (page height isn't necessarily uniform throughout the flow
+ // thread), but as long as it is used universally as a means to determine whether page
+ // height is known or not, we need this. Page height is unknown when column balancing is
+ // enabled and flow thread height is still unknown (i.e. during the first layout pass). When
+ // it's unknown, we need to prevent the pagination code from assuming page breaks everywhere
+ // and thereby eating every top margin. It should be trivial to clean up and get rid of this
+ // hack once the old multicol implementation is gone.
+ pageLogicalHeight = flowThread->isPageLogicalHeightKnown() ? LayoutUnit(1) : LayoutUnit(0);
+
+ pageLogicalHeightChanged = flowThread->pageLogicalSizeChanged();
+ }
}
-bool RenderBlockFlow::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer& statePusher)
+bool RenderBlockFlow::shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const
{
- if (!hasColumns())
- return false;
-
- OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
- if (childrenInline())
- addOverflowFromInlineChildren();
- else
- addOverflowFromBlockChildren();
- LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore();
-
// FIXME: We don't balance properly at all in the presence of forced page breaks. We need to understand what
// the distance between forced page breaks is so that we can avoid making the minimum column height too tall.
ColumnInfo* colInfo = columnInfo();
- if (!hasSpecifiedPageLogicalHeight) {
- LayoutUnit columnHeight = pageLogicalHeight;
- int minColumnCount = colInfo->forcedBreaks() + 1;
- int desiredColumnCount = colInfo->desiredColumnCount();
- if (minColumnCount >= desiredColumnCount) {
- // The forced page breaks are in control of the balancing. Just set the column height to the
- // maximum page break distance.
- if (!pageLogicalHeight) {
- LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(),
- view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset());
- columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
- }
- } else if (layoutOverflowLogicalBottom > 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)layoutOverflowLogicalBottom / desiredColumnCount));
+ LayoutUnit columnHeight = pageLogicalHeight;
+ const int minColumnCount = colInfo->forcedBreaks() + 1;
+ const int desiredColumnCount = colInfo->desiredColumnCount();
+ if (minColumnCount >= desiredColumnCount) {
+ // The forced page breaks are in control of the balancing. Just set the column height to the
+ // maximum page break distance.
+ if (!pageLogicalHeight) {
+ LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(),
+ view()->layoutState()->pageLogicalOffset(*this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset());
+ columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
}
+ } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
+ // Now that we know the intrinsic height of the columns, we have to rebalance them.
+ columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf(layoutOverflowLogicalBottom.toFloat() / desiredColumnCount));
+ }
- if (columnHeight && columnHeight != pageLogicalHeight) {
- statePusher.pop();
- setEverHadLayout(true);
- layoutBlock(false, columnHeight);
- return true;
- }
+ if (columnHeight && columnHeight != pageLogicalHeight) {
+ pageLogicalHeight = columnHeight;
+ return true;
}
+ return false;
+}
+
+void RenderBlockFlow::setColumnCountAndHeight(unsigned count, LayoutUnit pageLogicalHeight)
+{
+ ColumnInfo* colInfo = columnInfo();
if (pageLogicalHeight)
- colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight);
+ colInfo->setColumnCountAndHeight(count, pageLogicalHeight);
if (columnCount(colInfo)) {
setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
m_overflow.clear();
- } else {
- m_overflow = savedOverflow.release();
}
+}
- return false;
+bool RenderBlockFlow::isSelfCollapsingBlock() const
+{
+ m_hasOnlySelfCollapsingChildren = RenderBlock::isSelfCollapsingBlock();
+ return m_hasOnlySelfCollapsingChildren;
}
-void RenderBlockFlow::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
+void RenderBlockFlow::layoutBlock(bool relayoutChildren)
{
ASSERT(needsLayout());
+ ASSERT(isInlineBlockOrInlineTable() || !isInline());
- if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can cause us to come in here. Bail.
- return;
+ // If we are self-collapsing with self-collapsing descendants this will get set to save us burrowing through our
+ // descendants every time in |isSelfCollapsingBlock|. We reset it here so that |isSelfCollapsingBlock| attempts to burrow
+ // at least once and so that it always gives a reliable result reflecting the latest layout.
+ m_hasOnlySelfCollapsingChildren = false;
if (!relayoutChildren && simplifiedLayout())
return;
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ SubtreeLayoutScope layoutScope(*this);
+
+ // Multiple passes might be required for column and pagination based layout
+ // In the case of the old column code the number of passes will only be two
+ // however, in the newer column code the number of passes could equal the
+ // number of columns.
+ bool done = false;
+ LayoutUnit pageLogicalHeight = 0;
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout());
+ while (!done)
+ done = layoutBlockFlow(relayoutChildren, pageLogicalHeight, layoutScope);
+
+ fitBorderToLinesIfNeeded();
+
+ RenderView* renderView = view();
+ if (renderView->layoutState()->pageLogicalHeight())
+ setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(*this, logicalTop()));
+
+ updateLayerTransformAfterLayout();
+
+ // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
+ // we overflow or not.
+ updateScrollInfoAfterLayout();
+
+ // Repaint with our new bounds if they are different from our old bounds.
+ bool didFullRepaint = repainter.repaintAfterLayout();
+ if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ setShouldInvalidateOverflowForPaint(true);
+ else
+ invalidatePaintForOverflow();
+ }
+ clearNeedsLayout();
+}
+inline bool RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit &pageLogicalHeight, SubtreeLayoutScope& layoutScope)
+{
+ LayoutUnit oldLeft = logicalLeft();
if (updateLogicalWidthAndColumnWidth())
relayoutChildren = true;
rebuildFloatsFromIntruding();
- LayoutUnit previousHeight = logicalHeight();
- // FIXME: should this start out as borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(),
- // for consistency with other render classes?
- setLogicalHeight(0);
-
bool pageLogicalHeightChanged = false;
bool hasSpecifiedPageLogicalHeight = false;
checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightChanged, hasSpecifiedPageLogicalHeight);
-
- RenderView* renderView = view();
- LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo());
-
- // Regions changing widths can force us to relayout our children.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (logicalWidthChangedInRegions(flowThread))
- relayoutChildren = true;
- if (updateRegionsAndShapesLogicalSize(flowThread))
- relayoutChildren = true;
- if (!relayoutChildren && isRenderNamedFlowFragmentContainer())
+ if (pageLogicalHeightChanged)
relayoutChildren = true;
+ LayoutState state(*this, locationOffset(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo());
+
// We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
// our current maximal positive and negative margins. These values are used when we
// are collapsed with adjacent blocks, so for example, if you have block A and B
@@ -285,62 +361,75 @@ void RenderBlockFlow::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalH
//
// Start out by setting our margin values to our current margins. Table cells have
// no margins, so we don't fill in the values for table cells.
- bool isCell = isTableCell();
- if (!isCell) {
+ if (!isTableCell()) {
initMaxMarginValues();
-
setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk());
setHasMarginAfterQuirk(style()->hasMarginAfterQuirk());
setPaginationStrut(0);
}
- SubtreeLayoutScope layoutScope(this);
+ LayoutUnit beforeEdge = borderBefore() + paddingBefore();
+ LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+ LayoutUnit previousHeight = logicalHeight();
+ setLogicalHeight(beforeEdge);
m_repaintLogicalTop = 0;
m_repaintLogicalBottom = 0;
- LayoutUnit maxFloatLogicalBottom = 0;
if (!firstChild() && !isAnonymousBlock())
setChildrenInline(true);
+
+ FastTextAutosizer::LayoutScope fastTextAutosizerLayoutScope(this);
+
if (childrenInline())
- layoutInlineChildren(relayoutChildren, m_repaintLogicalTop, m_repaintLogicalBottom);
+ layoutInlineChildren(relayoutChildren, m_repaintLogicalTop, m_repaintLogicalBottom, afterEdge);
else
- layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom, layoutScope);
-
- if (frameView()->partialLayout().isStopping()) {
- statePusher.pop();
- return;
- }
+ layoutBlockChildren(relayoutChildren, layoutScope, beforeEdge, afterEdge);
// Expand our intrinsic height to encompass floats.
- LayoutUnit toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
- if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
- setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
+ if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && createsBlockFormattingContext())
+ setLogicalHeight(lowestFloatLogicalBottom() + afterEdge);
- if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher) || relayoutToAvoidWidows(statePusher)) {
- ASSERT(!shouldBreakAtLineToAvoidWidow());
- return;
+ if (RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread()) {
+ if (flowThread->recalculateColumnHeights()) {
+ setChildNeedsLayout(MarkOnlyThis);
+ return false;
+ }
+ } else if (hasColumns()) {
+ OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
+ if (childrenInline())
+ addOverflowFromInlineChildren();
+ else
+ addOverflowFromBlockChildren();
+ LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore();
+ m_overflow = savedOverflow.release();
+
+ if (!hasSpecifiedPageLogicalHeight && shouldRelayoutForPagination(pageLogicalHeight, layoutOverflowLogicalBottom)) {
+ setEverHadLayout(true);
+ return false;
+ }
+
+ setColumnCountAndHeight(ceilf(layoutOverflowLogicalBottom.toFloat() / pageLogicalHeight.toFloat()), pageLogicalHeight.toFloat());
+ }
+
+ if (shouldBreakAtLineToAvoidWidow()) {
+ setEverHadLayout(true);
+ return false;
}
// Calculate our new height.
LayoutUnit oldHeight = logicalHeight();
LayoutUnit oldClientAfterEdge = clientLogicalBottom();
- // Before updating the final size of the flow thread make sure a forced break is applied after the content.
- // This ensures the size information is correctly computed for the last auto-height region receiving content.
- if (isRenderFlowThread())
- toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge);
-
updateLogicalHeight();
LayoutUnit newHeight = logicalHeight();
- if (oldHeight != newHeight) {
- if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) {
- // One of our children's floats may have become an overhanging float for us. We need to look for it.
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isRenderBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) {
- RenderBlockFlow* block = toRenderBlockFlow(child);
- if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
- addOverhangingFloats(block, false);
- }
+ if (oldHeight > newHeight && !childrenInline()) {
+ // One of our children's floats may have become an overhanging float for us.
+ for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+ if (child->isRenderBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) {
+ RenderBlockFlow* block = toRenderBlockFlow(child);
+ if (block->lowestFloatLogicalBottom() + block->logicalTop() <= newHeight)
+ break;
+ addOverhangingFloats(block, false);
}
}
}
@@ -349,42 +438,62 @@ void RenderBlockFlow::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalH
if (heightChanged)
relayoutChildren = true;
- layoutPositionedObjects(relayoutChildren || isRoot());
+ layoutPositionedObjects(relayoutChildren || isDocumentElement(), oldLeft != logicalLeft() ? ForcedLayoutAfterContainingBlockMoved : DefaultLayout);
- updateRegionsAndShapesAfterChildLayout(flowThread, heightChanged);
+ computeRegionRangeForBlock(flowThreadContainingBlock());
// Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
computeOverflow(oldClientAfterEdge);
- statePusher.pop();
-
- fitBorderToLinesIfNeeded();
+ return true;
+}
- if (frameView()->partialLayout().isStopping())
- return;
+void RenderBlockFlow::determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode applyDelta)
+{
+ LayoutUnit startPosition = borderStart() + paddingStart();
+ if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ startPosition -= verticalScrollbarWidth();
+ LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
- if (renderView->layoutState()->m_pageLogicalHeight)
- setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop()));
+ // Add in our start margin.
+ LayoutUnit childMarginStart = marginStartForChild(child);
+ LayoutUnit newPosition = startPosition + childMarginStart;
- updateLayerTransform();
+ // 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() && !flowThreadContainingBlock())
+ newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child));
- // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
- // we overflow or not.
- updateScrollInfoAfterLayout();
+ setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), applyDelta);
+}
- // Repaint with our new bounds if they are different from our old bounds.
- bool didFullRepaint = repainter.repaintAfterLayout();
- if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
- if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
- setShouldRepaintOverflowIfNeeded(true);
- else
- repaintOverflow();
+void RenderBlockFlow::setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
+{
+ if (isHorizontalWritingMode()) {
+ if (applyDelta == ApplyLayoutDelta && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(LayoutSize(child->x() - logicalLeft, 0));
+ child->setX(logicalLeft);
+ } else {
+ if (applyDelta == ApplyLayoutDelta && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(LayoutSize(0, child->y() - logicalLeft));
+ child->setY(logicalLeft);
}
+}
- clearNeedsLayout();
+void RenderBlockFlow::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
+{
+ if (isHorizontalWritingMode()) {
+ if (applyDelta == ApplyLayoutDelta && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(LayoutSize(0, child->y() - logicalTop));
+ child->setY(logicalTop);
+ } else {
+ if (applyDelta == ApplyLayoutDelta && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(LayoutSize(child->x() - logicalTop, 0));
+ child->setX(logicalTop);
+ }
}
-void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
+void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom)
{
LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
@@ -402,8 +511,8 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
LayoutRect oldRect = child->frameRect();
LayoutUnit oldLogicalTop = logicalTopForChild(child);
-#if !ASSERT_DISABLED
- LayoutSize oldLayoutDelta = view()->layoutDelta();
+#if ASSERT_ENABLED
+ LayoutSize oldLayoutDelta = RuntimeEnabledFeatures::repaintAfterLayoutEnabled() ? LayoutSize() : view()->layoutDelta();
#endif
// Go ahead and position the child as though it didn't collapse with the top.
setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
@@ -434,7 +543,7 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlockFlow->lowestFloatLogicalBottom());
}
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
if (!child->needsLayout())
child->markForPaginationRelayoutIfNeeded(layoutScope);
@@ -443,18 +552,16 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
if (childNeededLayout)
child->layout();
- if (frameView()->partialLayout().isStopping())
- return;
-
// Cache if we are at the top of the block right now.
bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
+ bool childIsSelfCollapsing = child->isSelfCollapsingBlock();
// Now determine the correct ypos based off examination of collapsing margin
// values.
- LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo);
+ LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo, childIsSelfCollapsing);
// Now check for clear.
- LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
+ LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear, childIsSelfCollapsing);
bool paginated = view()->layoutState()->isPaginated();
if (paginated) {
@@ -468,7 +575,7 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
// clearFloatsIfNeeded can also mark the child as needing a layout even though we didn't move. This happens
// when collapseMargins dynamically adds overhanging floats because of a child with negative margins.
if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout() || (paginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWidow())) {
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
if (child->shrinkToAvoidFloats()) {
// The child's width depends on the line width.
// When the child shifts to clear an item, its width can
@@ -488,16 +595,22 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
child->layoutIfNeeded();
}
+ // If we previously encountered a self-collapsing sibling of this child that had clearance then
+ // we set this bit to ensure we would not collapse the child's margins, and those of any subsequent
+ // self-collapsing siblings, with our parent. If this child is not self-collapsing then it can
+ // collapse its margins with the parent so reset the bit.
+ if (!marginInfo.canCollapseMarginAfterWithLastChild() && !childIsSelfCollapsing)
+ marginInfo.setCanCollapseMarginAfterWithLastChild(true);
+
// We are no longer at the top of the block if we encounter a non-empty child.
// This has to be done after checking for clear, so that margins can be reset if a clear occurred.
- if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
+ if (marginInfo.atBeforeSideOfBlock() && !childIsSelfCollapsing)
marginInfo.setAtBeforeSideOfBlock(false);
// Now place the child in the correct left position
determineLogicalLeftPositionForChild(child, ApplyLayoutDelta);
LayoutSize childOffset = child->location() - oldRect.location();
- relayoutShapeDescendantIfMoved(childRenderBlock, childOffset);
// Update our height now that the child has been placed in the correct position.
setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
@@ -507,24 +620,25 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
}
// If the child has overhanging floats that intrude into following siblings (or possibly out
// of this block), then the parent gets notified of the floats now.
- if (childRenderBlockFlow && childRenderBlockFlow->containsFloats())
- maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(childRenderBlockFlow, !childNeededLayout));
+ if (childRenderBlockFlow)
+ addOverhangingFloats(childRenderBlockFlow, !childNeededLayout);
if (childOffset.width() || childOffset.height()) {
- view()->addLayoutDelta(childOffset);
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(childOffset);
// If the child moved, we have to repaint it as well as any floating/positioned
// descendants. An exception is if we need a layout. In this case, we know we're going to
// repaint ourselves (and the child) anyway.
if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && childHadLayout && !selfNeedsLayout())
child->repaintOverhangingFloats(true);
- else if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ else if (childHadLayout && !selfNeedsLayout() && child->checkForPaintInvalidationDuringLayout())
child->repaintDuringLayoutIfMoved(oldRect);
}
- if (!childHadLayout && child->checkForRepaintDuringLayout()) {
+ if (!childHadLayout && child->checkForPaintInvalidation()) {
if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
- child->repaint();
+ child->paintInvalidationForWholeRenderer();
child->repaintOverhangingFloats(true);
}
@@ -535,7 +649,9 @@ void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo,
setLogicalHeight(newHeight);
}
- ASSERT(view()->layoutDeltaMatches(oldLayoutDelta));
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ ASSERT(view()->layoutDeltaMatches(oldLayoutDelta));
+ }
}
LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock)
@@ -556,7 +672,7 @@ LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopA
child->setChildNeedsLayout(MarkOnlyThis);
}
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
if (childRenderBlock) {
if (!child->avoidsFloats() && childRenderBlock->containsFloats())
@@ -574,31 +690,19 @@ LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopA
// If the object has a page or column break value of "before", then we should shift to the top of the next page.
LayoutUnit result = applyBeforeBreak(child, logicalTopAfterClear);
- if (pageLogicalHeightForOffset(result)) {
- LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(result, ExcludePageBoundary);
- LayoutUnit spaceShortage = child->logicalHeight() - remainingLogicalHeight;
- if (spaceShortage > 0) {
- // If the child crosses a column boundary, report a break, in case nothing inside it has already
- // done so. The column balancer needs to know how much it has to stretch the columns to make more
- // content fit. If no breaks are reported (but do occur), the balancer will have no clue. FIXME:
- // This should be improved, though, because here we just pretend that the child is
- // unsplittable. A splittable child, on the other hand, has break opportunities at every position
- // where there's no child content, border or padding. In other words, we risk stretching more
- // than necessary.
- setPageBreak(result, spaceShortage);
- }
- }
-
// For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
LayoutUnit logicalTopBeforeUnsplittableAdjustment = result;
LayoutUnit logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, result);
LayoutUnit paginationStrut = 0;
LayoutUnit unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustment - logicalTopBeforeUnsplittableAdjustment;
- if (unsplittableAdjustmentDelta)
+ LayoutUnit childLogicalHeight = child->logicalHeight();
+ if (unsplittableAdjustmentDelta) {
+ setPageBreak(result, childLogicalHeight - unsplittableAdjustmentDelta);
paginationStrut = unsplittableAdjustmentDelta;
- else if (childRenderBlock && childRenderBlock->paginationStrut())
+ } else if (childRenderBlock && childRenderBlock->paginationStrut()) {
paginationStrut = childRenderBlock->paginationStrut();
+ }
if (paginationStrut) {
// We are willing to propagate out to our parent block as long as we were at the top of the block prior
@@ -615,6 +719,27 @@ LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopA
}
}
+ if (!unsplittableAdjustmentDelta) {
+ if (LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(result)) {
+ LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(result, ExcludePageBoundary);
+ LayoutUnit spaceShortage = childLogicalHeight - remainingLogicalHeight;
+ if (spaceShortage > 0) {
+ // If the child crosses a column boundary, report a break, in case nothing inside it
+ // has already done so. The column balancer needs to know how much it has to stretch
+ // the columns to make more content fit. If no breaks are reported (but do occur),
+ // the balancer will have no clue. Only measure the space after the last column
+ // boundary, in case it crosses more than one.
+ LayoutUnit spaceShortageInLastColumn = intMod(spaceShortage, pageLogicalHeight);
+ setPageBreak(result, spaceShortageInLastColumn ? spaceShortageInLastColumn : spaceShortage);
+ } else if (remainingLogicalHeight == pageLogicalHeight && offsetFromLogicalTopOfFirstPage() + child->logicalTop()) {
+ // We're at the very top of a page or column, and it's not the first one. This child
+ // may turn out to be the smallest piece of content that causes a page break, so we
+ // need to report it.
+ setPageBreak(result, childLogicalHeight);
+ }
+ }
+ }
+
// Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child.
setLogicalHeight(logicalHeight() + (result - oldTop));
@@ -632,14 +757,14 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (!floatingObject->isDescendant())
oldIntrudingFloatSet.add(floatingObject->renderer());
}
}
// Inline blocks are covered by the isReplaced() check in the avoidFloats method.
- if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrOutOfFlowPositioned() || isTableCell()) {
+ if (avoidsFloats() || isDocumentElement() || isRenderView() || isFloatingOrOutOfFlowPositioned() || isTableCell()) {
if (m_floatingObjects) {
m_floatingObjects->clear();
}
@@ -663,13 +788,13 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
if (!parent() || !parent()->isRenderBlockFlow())
return;
- // Attempt to locate a previous sibling with overhanging floats. We skip any elements that are
- // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
- // to avoid floats.
+ // Attempt to locate a previous sibling with overhanging floats. We skip any elements that
+ // may have shifted to avoid floats, and any objects whose floats cannot interact with objects
+ // outside it (i.e. objects that create a new block formatting context).
RenderBlockFlow* parentBlockFlow = toRenderBlockFlow(parent());
bool parentHasFloats = false;
RenderObject* prev = previousSibling();
- while (prev && (prev->isFloatingOrOutOfFlowPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
+ while (prev && (!prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats() || toRenderBlock(prev)->createsBlockFormattingContext())) {
if (prev->isFloating())
parentHasFloats = true;
prev = prev->previousSibling();
@@ -678,22 +803,18 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
// First add in floats from the parent. Self-collapsing blocks let their parent track any floats that intrude into
// them (as opposed to floats they contain themselves) so check for those here too.
LayoutUnit logicalTopOffset = logicalTop();
- if (parentHasFloats || (prev && toRenderBlockFlow(prev)->isSelfCollapsingBlock() && parentBlockFlow->lowestFloatLogicalBottom() > logicalTopOffset))
+ bool parentHasIntrudingFloats = !parentHasFloats && (!prev || toRenderBlockFlow(prev)->isSelfCollapsingBlock()) && parentBlockFlow->lowestFloatLogicalBottom() > logicalTopOffset;
+ if (parentHasFloats || parentHasIntrudingFloats)
addIntrudingFloats(parentBlockFlow, parentBlockFlow->logicalLeftOffsetForContent(), logicalTopOffset);
- LayoutUnit logicalLeftOffset = 0;
+ // Add overhanging floats from the previous RenderBlockFlow, but only if it has a float that intrudes into our space.
if (prev) {
- logicalTopOffset -= toRenderBox(prev)->logicalTop();
- } else {
- prev = parentBlockFlow;
- logicalLeftOffset += parentBlockFlow->logicalLeftOffsetForContent();
+ RenderBlockFlow* blockFlow = toRenderBlockFlow(prev);
+ logicalTopOffset -= blockFlow->logicalTop();
+ if (blockFlow->lowestFloatLogicalBottom() > logicalTopOffset)
+ addIntrudingFloats(blockFlow, 0, logicalTopOffset);
}
- // Add overhanging floats from the previous RenderBlockFlow, but only if it has a float that intrudes into our space.
- RenderBlockFlow* blockFlow = toRenderBlockFlow(prev);
- if (blockFlow->m_floatingObjects && blockFlow->lowestFloatLogicalBottom() > logicalTopOffset)
- addIntrudingFloats(blockFlow, logicalLeftOffset, logicalTopOffset);
-
if (childrenInline()) {
LayoutUnit changeLogicalTop = LayoutUnit::max();
LayoutUnit changeLogicalBottom = LayoutUnit::min();
@@ -701,7 +822,7 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
FloatingObject* oldFloatingObject = floatMap.get(floatingObject->renderer());
LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject);
if (oldFloatingObject) {
@@ -722,12 +843,12 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
}
}
- floatMap.remove(floatingObject->renderer());
if (oldFloatingObject->originatingLine() && !selfNeedsLayout()) {
ASSERT(oldFloatingObject->originatingLine()->renderer() == this);
oldFloatingObject->originatingLine()->markDirty();
}
- delete oldFloatingObject;
+
+ floatMap.remove(floatingObject->renderer());
} else {
changeLogicalTop = 0;
changeLogicalBottom = max(changeLogicalBottom, logicalBottom);
@@ -737,13 +858,12 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
RendererToFloatInfoMap::iterator end = floatMap.end();
for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
- FloatingObject* floatingObject = (*it).value;
+ OwnPtr<FloatingObject>& floatingObject = it->value;
if (!floatingObject->isDescendant()) {
changeLogicalTop = 0;
- changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject));
+ changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject.get()));
}
}
- deleteAllValues(floatMap);
markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom);
} else if (!oldIntrudingFloatSet.isEmpty()) {
@@ -762,19 +882,10 @@ void RenderBlockFlow::rebuildFloatsFromIntruding()
}
}
-void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom, SubtreeLayoutScope& layoutScope)
+void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, SubtreeLayoutScope& layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge)
{
dirtyForLayoutFromPercentageHeightDescendants(layoutScope);
- LayoutUnit beforeEdge = borderBefore() + paddingBefore();
- LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
-
- setLogicalHeight(beforeEdge);
-
- // Lay out our hypothetical grid line as though it occurs at the top of the block.
- if (view()->layoutState()->lineGrid() == this)
- layoutLineGridBox();
-
// The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
MarginInfo marginInfo(this, beforeEdge, afterEdge);
@@ -784,15 +895,16 @@ void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max
RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren, layoutScope);
LayoutUnit previousFloatLogicalBottom = 0;
- maxFloatLogicalBottom = 0;
RenderBox* next = firstChildBox();
+ RenderBox* lastNormalFlowChild = 0;
while (next) {
RenderBox* child = next;
next = child->nextSiblingBox();
- LayoutRectRecorder recorder(*child);
+ // FIXME: this should only be set from clearNeedsLayout crbug.com/361250
+ child->setLayoutDidGetCalled(true);
if (childToExclude == child)
continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
@@ -811,21 +923,19 @@ void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max
}
// Lay out the child.
- layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
-
- // If doing a partial layout and the child was the target renderer, early exit here.
- if (frameView()->partialLayout().checkPartialLayoutComplete(child))
- break;
+ layoutBlockChild(child, marginInfo, previousFloatLogicalBottom);
+ lastNormalFlowChild = child;
}
// Now do the handling of the bottom of the block, adding in our bottom border/padding and
// determining the correct collapsed bottom margin information.
- handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
+ handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, marginInfo);
}
// Our MarginInfo state used when laying out block children.
MarginInfo::MarginInfo(RenderBlockFlow* blockFlow, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding)
- : m_atBeforeSideOfBlock(true)
+ : m_canCollapseMarginAfterWithLastChild(true)
+ , m_atBeforeSideOfBlock(true)
, m_atAfterSideOfBlock(false)
, m_hasMarginBeforeQuirk(false)
, m_hasMarginAfterQuirk(false)
@@ -834,10 +944,7 @@ MarginInfo::MarginInfo(RenderBlockFlow* blockFlow, LayoutUnit beforeBorderPaddin
{
RenderStyle* blockStyle = blockFlow->style();
ASSERT(blockFlow->isRenderView() || blockFlow->parent());
- m_canCollapseWithChildren = !blockFlow->isRenderView() && !blockFlow->isRoot() && !blockFlow->isOutOfFlowPositioned()
- && !blockFlow->isFloating() && !blockFlow->isTableCell() && !blockFlow->hasOverflowClip() && !blockFlow->isInlineBlockOrInlineTable()
- && !blockFlow->isRenderFlowThread() && !blockFlow->isWritingModeRoot() && !blockFlow->parent()->isFlexibleBox()
- && blockStyle->hasAutoColumnCount() && blockStyle->hasAutoColumnWidth() && !blockStyle->columnSpan();
+ m_canCollapseWithChildren = !blockFlow->createsBlockFormattingContext() && !blockFlow->isRenderFlowThread() && !blockFlow->isRenderView();
m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && !beforeBorderPadding && blockStyle->marginBeforeCollapse() != MSEPARATE;
@@ -916,11 +1023,10 @@ RenderBlockFlow::MarginValues RenderBlockFlow::marginValuesForChild(RenderBox* c
return RenderBlockFlow::MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative);
}
-LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
+LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& marginInfo, bool childIsSelfCollapsing)
{
bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child);
bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child);
- bool childIsSelfCollapsing = child->isSelfCollapsingBlock();
// The child discards the before margin when the the after margin has discard in the case of a self collapsing block.
childDiscardMarginBefore = childDiscardMarginBefore || (childDiscardMarginAfter && childIsSelfCollapsing);
@@ -988,11 +1094,12 @@ LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& margin
LayoutUnit clearanceForSelfCollapsingBlock;
RenderObject* prev = child->previousSibling();
+ RenderBlockFlow* previousBlockFlow = prev && prev->isRenderBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned() ? toRenderBlockFlow(prev) : 0;
// If the child's previous sibling is a self-collapsing block that cleared a float then its top border edge has been set at the bottom border edge
// of the float. Since we want to collapse the child's top margin with the self-collapsing block's top and bottom margins we need to adjust our parent's height to match the
// margin top of the self-collapsing block. If the resulting collapsed margin leaves the child still intruding into the float then we will want to clear it.
- if (!marginInfo.canCollapseWithMarginBefore() && prev && prev->isRenderBlockFlow() && toRenderBlockFlow(prev)->isSelfCollapsingBlock()) {
- clearanceForSelfCollapsingBlock = toRenderBlockFlow(prev)->marginOffsetForSelfCollapsingBlock();
+ if (!marginInfo.canCollapseWithMarginBefore() && previousBlockFlow && previousBlockFlow->isSelfCollapsingBlock()) {
+ clearanceForSelfCollapsingBlock = previousBlockFlow->marginOffsetForSelfCollapsingBlock();
setLogicalHeight(logicalHeight() - clearanceForSelfCollapsingBlock);
}
@@ -1054,21 +1161,19 @@ LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& margin
// If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
// collapsed into the page edge.
LayoutState* layoutState = view()->layoutState();
- if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop
- && hasNextPage(beforeCollapseLogicalTop)) {
+ if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop) {
LayoutUnit oldLogicalTop = logicalTop;
logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
}
- if (prev && prev->isRenderBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
+ if (previousBlockFlow) {
// If |child| is a self-collapsing block it may have collapsed into a previous sibling and although it hasn't reduced the height of the parent yet
// any floats from the parent will now overhang.
- RenderBlockFlow* blockFlow = toRenderBlockFlow(prev);
LayoutUnit oldLogicalHeight = logicalHeight();
setLogicalHeight(logicalTop);
- if (blockFlow->containsFloats() && !blockFlow->avoidsFloats() && (blockFlow->logicalTop() + blockFlow->lowestFloatLogicalBottom()) > logicalTop)
- addOverhangingFloats(blockFlow, false);
+ if (!previousBlockFlow->avoidsFloats() && (previousBlockFlow->logicalTop() + previousBlockFlow->lowestFloatLogicalBottom()) > logicalTop)
+ addOverhangingFloats(previousBlockFlow, false);
setLogicalHeight(oldLogicalHeight);
// If |child|'s previous sibling is a self-collapsing block that cleared a float and margin collapsing resulted in |child| moving up
@@ -1076,7 +1181,7 @@ LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& margin
// floats in the parent that overhang |child|'s new logical top.
bool logicalTopIntrudesIntoFloat = clearanceForSelfCollapsingBlock > 0 && logicalTop < beforeCollapseLogicalTop;
if (logicalTopIntrudesIntoFloat && containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
- child->setNeedsLayout();
+ child->setNeedsLayoutAndFullPaintInvalidation();
}
return logicalTop;
@@ -1106,13 +1211,35 @@ void RenderBlockFlow::adjustPositionedBlock(RenderBox* child, const MarginInfo&
}
}
-LayoutUnit RenderBlockFlow::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos)
+LayoutUnit RenderBlockFlow::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart)
+{
+ LayoutUnit startPosition = startOffsetForContent();
+
+ // Add in our start margin.
+ LayoutUnit oldPosition = startPosition + childMarginStart;
+ LayoutUnit newPosition = oldPosition;
+
+ LayoutUnit blockOffset = logicalTopForChild(child);
+ LayoutUnit startOff = startOffsetForLine(blockOffset, false, logicalHeightForChild(child));
+
+ if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
+ 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) {
+ newPosition = startOff + childMarginStart;
+ }
+
+ return newPosition - oldPosition;
+}
+
+LayoutUnit RenderBlockFlow::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos, bool childIsSelfCollapsing)
{
LayoutUnit heightIncrease = getClearDelta(child, yPos);
if (!heightIncrease)
return yPos;
- if (child->isSelfCollapsingBlock()) {
+ if (childIsSelfCollapsing) {
bool childDiscardMargin = mustDiscardMarginBeforeForChild(child) || mustDiscardMarginAfterForChild(child);
// For self-collapsing blocks that clear, they can still collapse their
@@ -1131,15 +1258,9 @@ LayoutUnit RenderBlockFlow::clearFloatsIfNeeded(RenderBox* child, MarginInfo& ma
// CSS2.1 states:
// "If the top and bottom margins of an element with clearance are adjoining, its margins collapse with
// the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block."
- // So the parent's bottom margin cannot collapse through this block or any subsequent self-collapsing blocks. Check subsequent siblings
- // for a block with height - if none is found then don't allow the margins to collapse with the parent.
- bool wouldCollapseMarginsWithParent = marginInfo.canCollapseMarginAfterWithChildren();
- for (RenderBox* curr = child->nextSiblingBox(); curr && wouldCollapseMarginsWithParent; curr = curr->nextSiblingBox()) {
- if (!curr->isFloatingOrOutOfFlowPositioned() && !curr->isSelfCollapsingBlock())
- wouldCollapseMarginsWithParent = false;
- }
- if (wouldCollapseMarginsWithParent)
- marginInfo.setCanCollapseMarginAfterWithChildren(false);
+ // So the parent's bottom margin cannot collapse through this block or any subsequent self-collapsing blocks. Set a bit to ensure
+ // this happens; it will get reset if we encounter an in-flow sibling that is not self-collapsing.
+ marginInfo.setCanCollapseMarginAfterWithLastChild(false);
// For now set the border-top of |child| flush with the bottom border-edge of the float so it can layout any floating or positioned children of
// its own at the correct vertical position. If subsequent siblings attempt to collapse with |child|'s margins in |collapseMargins| we will
@@ -1157,9 +1278,6 @@ LayoutUnit RenderBlockFlow::clearFloatsIfNeeded(RenderBox* child, MarginInfo& ma
if (marginInfo.canCollapseWithMarginBefore()) {
// We can no longer collapse with the top of the block since a clear
// occurred. The empty blocks collapse into the cleared block.
- // FIXME: This isn't quite correct. Need clarification for what to do
- // if the height the cleared block is offset by is smaller than the
- // margins involved.
setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
marginInfo.setAtBeforeSideOfBlock(false);
@@ -1201,7 +1319,7 @@ void RenderBlockFlow::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit&
// Give up if in quirks mode and we're a body/table cell and the top margin of the child box is quirky.
// Give up if the child specified -webkit-margin-collapse: separate that prevents collapsing.
// FIXME: Use writing mode independent accessor for marginBeforeCollapse.
- if ((document().inQuirksMode() && hasMarginAfterQuirk(child) && (isTableCell() || isBody())) || child->style()->marginBeforeCollapse() == MSEPARATE)
+ if ((document().inQuirksMode() && hasMarginBeforeQuirk(child) && (isTableCell() || isBody())) || child->style()->marginBeforeCollapse() == MSEPARATE)
return;
// The margins are discarded by a child that specified -webkit-margin-collapse: discard.
@@ -1281,8 +1399,7 @@ LayoutUnit RenderBlockFlow::estimateLogicalTopPosition(RenderBox* child, const M
// Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
// page.
LayoutState* layoutState = view()->layoutState();
- if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight()
- && hasNextPage(logicalHeight()))
+ if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight())
logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
@@ -1333,16 +1450,18 @@ void RenderBlockFlow::adjustFloatingBlock(const MarginInfo& marginInfo)
setLogicalHeight(logicalHeight() - marginOffset);
}
-void RenderBlockFlow::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo)
+void RenderBlockFlow::handleAfterSideOfBlock(RenderBox* lastChild, LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo)
{
marginInfo.setAtAfterSideOfBlock(true);
// If our last child was a self-collapsing block with clearance then our logical height is flush with the
// bottom edge of the float that the child clears. The correct vertical position for the margin-collapsing we want
// to perform now is at the child's margin-top - so adjust our height to that position.
- RenderObject* child = lastChild();
- if (child && child->isRenderBlockFlow() && toRenderBlockFlow(child)->isSelfCollapsingBlock())
- setLogicalHeight(logicalHeight() - toRenderBlockFlow(child)->marginOffsetForSelfCollapsingBlock());
+ if (lastChild && lastChild->isRenderBlockFlow() && lastChild->isSelfCollapsingBlock())
+ setLogicalHeight(logicalHeight() - toRenderBlockFlow(lastChild)->marginOffsetForSelfCollapsingBlock());
+
+ if (marginInfo.canCollapseMarginAfterWithChildren() && !marginInfo.canCollapseMarginAfterWithLastChild())
+ marginInfo.setCanCollapseMarginAfterWithChildren(false);
// If we can't collapse with children then go ahead and add in the bottom margin.
if (!marginInfo.discardMargin() && (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
@@ -1478,19 +1597,21 @@ bool RenderBlockFlow::mustSeparateMarginAfterForChild(const RenderBox* child) co
LayoutUnit RenderBlockFlow::applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset)
{
// FIXME: Add page break checking here when we support printing.
- bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
- bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
RenderFlowThread* flowThread = flowThreadContainingBlock();
- bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
- bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS)
- || (checkRegionBreaks && child->style()->regionBreakBefore() == PBALWAYS);
- if (checkBeforeAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
- if (checkColumnBreaks)
- view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
- if (checkRegionBreaks) {
- LayoutUnit offsetBreakAdjustment = 0;
- if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, child, true, &offsetBreakAdjustment))
- return logicalOffset + offsetBreakAdjustment;
+ bool isInsideMulticolFlowThread = flowThread;
+ bool checkColumnBreaks = isInsideMulticolFlowThread || view()->layoutState()->isPaginatingColumns();
+ bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); // FIXME: Once columns can print we have to check this.
+ bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS)
+ || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS);
+ if (checkBeforeAlways && inNormalFlow(child)) {
+ if (checkColumnBreaks) {
+ if (isInsideMulticolFlowThread) {
+ LayoutUnit offsetBreakAdjustment = 0;
+ if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, child, true, &offsetBreakAdjustment))
+ return logicalOffset + offsetBreakAdjustment;
+ } else {
+ view()->layoutState()->addForcedColumnBreak(*child, logicalOffset);
+ }
}
return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
}
@@ -1500,24 +1621,26 @@ LayoutUnit RenderBlockFlow::applyBeforeBreak(RenderBox* child, LayoutUnit logica
LayoutUnit RenderBlockFlow::applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo& marginInfo)
{
// FIXME: Add page break checking here when we support printing.
- bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
- bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
RenderFlowThread* flowThread = flowThreadContainingBlock();
- bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
- bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS)
- || (checkRegionBreaks && child->style()->regionBreakAfter() == PBALWAYS);
- if (checkAfterAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
+ bool isInsideMulticolFlowThread = flowThread;
+ bool checkColumnBreaks = isInsideMulticolFlowThread || view()->layoutState()->isPaginatingColumns();
+ bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); // FIXME: Once columns can print we have to check this.
+ bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS)
+ || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS);
+ if (checkAfterAlways && inNormalFlow(child)) {
LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin();
// So our margin doesn't participate in the next collapsing steps.
marginInfo.clearMargin();
- if (checkColumnBreaks)
- view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
- if (checkRegionBreaks) {
- LayoutUnit offsetBreakAdjustment = 0;
- if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset + marginOffset, child, false, &offsetBreakAdjustment))
- return logicalOffset + marginOffset + offsetBreakAdjustment;
+ if (checkColumnBreaks) {
+ if (isInsideMulticolFlowThread) {
+ LayoutUnit offsetBreakAdjustment = 0;
+ if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset + marginOffset, child, false, &offsetBreakAdjustment))
+ return logicalOffset + marginOffset + offsetBreakAdjustment;
+ } else {
+ view()->layoutState()->addForcedColumnBreak(*child, logicalOffset);
+ }
}
return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
}
@@ -1532,7 +1655,7 @@ void RenderBlockFlow::addOverflowFromFloats()
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (floatingObject->isDescendant())
addOverflowFromChild(floatingObject->renderer(), IntSize(xPositionForFloatIncludingMargin(floatingObject), yPositionForFloatIncludingMargin(floatingObject)));
}
@@ -1541,10 +1664,23 @@ void RenderBlockFlow::addOverflowFromFloats()
void RenderBlockFlow::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
{
RenderBlock::computeOverflow(oldClientAfterEdge, recomputeFloats);
- if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
+ if (!hasColumns() && (recomputeFloats || createsBlockFormattingContext() || hasSelfPaintingLayer()))
addOverflowFromFloats();
}
+RootInlineBox* RenderBlockFlow::createAndAppendRootInlineBox()
+{
+ RootInlineBox* rootBox = createRootInlineBox();
+ m_lineBoxes.appendLineBox(rootBox);
+
+ if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && m_lineBoxes.firstLineBox() == rootBox) {
+ if (AXObjectCache* cache = document().existingAXObjectCache())
+ cache->recomputeIsIgnored(this);
+ }
+
+ return rootBox;
+}
+
void RenderBlockFlow::deleteLineBoxTree()
{
if (containsFloats())
@@ -1633,11 +1769,10 @@ LayoutUnit RenderBlockFlow::getClearDelta(RenderBox* child, LayoutUnit logicalTo
LayoutUnit newLogicalTop = logicalTop;
while (true) {
LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child));
- if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
+ if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent())
return newLogicalTop - logicalTop;
- RenderRegion* region = regionAtBlockOffset(logicalTopForChild(child));
- LayoutRect borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo);
+ LayoutRect borderBox = child->borderBoxRect();
LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
// FIXME: None of this is right for perpendicular writing-mode children.
@@ -1648,8 +1783,7 @@ LayoutUnit RenderBlockFlow::getClearDelta(RenderBox* child, LayoutUnit logicalTo
child->setLogicalTop(newLogicalTop);
child->updateLogicalWidth();
- region = regionAtBlockOffset(logicalTopForChild(child));
- borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo);
+ borderBox = child->borderBoxRect();
LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
child->setLogicalTop(childOldLogicalTop);
@@ -1681,12 +1815,12 @@ void RenderBlockFlow::createFloatingObjects()
m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
}
-void RenderBlockFlow::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderBlockFlow::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
RenderStyle* oldStyle = style();
s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false;
- if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position()
- && containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
+ if (oldStyle && parent() && diff.needsFullLayout() && oldStyle->position() != newStyle.position()
+ && containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
markAllDescendantsWithFloatsForLayout();
RenderBlock::styleWillChange(diff, newStyle);
@@ -1701,7 +1835,7 @@ void RenderBlockFlow::styleDidChange(StyleDifference diff, const RenderStyle* ol
// then mark its descendants with floats for layout and clear all floats from its next
// sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats();
- if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
+ if (diff.needsFullLayout() && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
RenderBlockFlow* parentBlockFlow = this;
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
@@ -1726,8 +1860,8 @@ void RenderBlockFlow::styleDidChange(StyleDifference diff, const RenderStyle* ol
parentBlockFlow->markSiblingsWithFloatsForLayout();
}
- if (renderNamedFlowFragment())
- renderNamedFlowFragment()->setStyleForNamedFlowFragment(style());
+ if (diff.needsFullLayout() || !oldStyle)
+ createOrDestroyMultiColumnFlowThreadIfNeeded();
}
void RenderBlockFlow::updateStaticInlinePositionForChild(RenderBox* child, LayoutUnit logicalTop)
@@ -1735,18 +1869,23 @@ void RenderBlockFlow::updateStaticInlinePositionForChild(RenderBox* child, Layou
if (child->style()->isOriginalDisplayInlineType())
setStaticInlinePositionForChild(child, logicalTop, startAlignedOffsetForLine(logicalTop, false));
else
- setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop));
+ setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent());
}
void RenderBlockFlow::setStaticInlinePositionForChild(RenderBox* child, LayoutUnit blockOffset, LayoutUnit inlinePosition)
{
- if (flowThreadContainingBlock()) {
- // Shift the inline position to exclude the region offset.
- inlinePosition += startOffsetForContent() - startOffsetForContent(blockOffset);
- }
child->layer()->setStaticInlinePosition(inlinePosition);
}
+void RenderBlockFlow::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+ if (RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread()) {
+ flowThread->addChild(newChild, beforeChild);
+ return;
+ }
+ RenderBlock::addChild(newChild, beforeChild);
+}
+
void RenderBlockFlow::moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert)
{
RenderBlockFlow* toBlockFlow = toRenderBlockFlow(toBlock);
@@ -1777,7 +1916,7 @@ void RenderBlockFlow::moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, boo
FloatingObjectSetIterator end = fromFloatingObjectSet.end();
for (FloatingObjectSetIterator it = fromFloatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
// Don't insert the object again if it's already in the list
if (toBlockFlow->containsFloat(floatingObject->renderer()))
@@ -1798,11 +1937,11 @@ void RenderBlockFlow::repaintOverhangingFloats(bool paintAllDescendants)
// FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
// in this block. Better yet would be to push extra state for the containers of other floats.
- LayoutStateDisabler layoutStateDisabler(view());
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
// 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.
@@ -1811,18 +1950,17 @@ void RenderBlockFlow::repaintOverhangingFloats(bool paintAllDescendants)
&& (floatingObject->shouldPaint() || (paintAllDescendants && floatingObject->renderer()->isDescendantOf(this)))) {
RenderBox* floatingRenderer = floatingObject->renderer();
- LayoutRectRecorder recorder(*floatingRenderer);
if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
- floatingRenderer->setShouldDoFullRepaintAfterLayout(true);
+ floatingRenderer->setShouldDoFullPaintInvalidationAfterLayout(true);
else
- floatingRenderer->repaint();
+ floatingRenderer->paintInvalidationForWholeRenderer();
floatingRenderer->repaintOverhangingFloats(false);
}
}
}
-void RenderBlockFlow::repaintOverflow()
+void RenderBlockFlow::invalidatePaintForOverflow()
{
// FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines
// it had to lay out. We wouldn't need the hasOverflowClip() hack in that case either.
@@ -1845,8 +1983,6 @@ void RenderBlockFlow::repaintOverflow()
// The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
adjustRectForColumns(repaintRect);
- repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
-
if (hasOverflowClip()) {
// Adjust repaint rect for scroll offset
repaintRect.move(-scrolledContentOffset());
@@ -1857,9 +1993,12 @@ void RenderBlockFlow::repaintOverflow()
// Make sure the rect is still non-empty after intersecting for overflow above
if (!repaintRect.isEmpty()) {
- repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
+ // Hits in media/event-attributes.html
+ DisableCompositingQueryAsserts disabler;
+
+ invalidatePaintRectangle(repaintRect); // We need to do a partial repaint of our content.
if (hasReflection())
- repaintRectangle(reflectedRect(repaintRect));
+ invalidatePaintRectangle(reflectedRect(repaintRect));
}
m_repaintLogicalTop = 0;
@@ -1874,7 +2013,7 @@ void RenderBlockFlow::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paint
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
// Only paint the object if our m_shouldPaint flag is set.
if (floatingObject->shouldPaint() && !floatingObject->renderer()->hasSelfPaintingLayer()) {
PaintInfo currentPaintInfo(paintInfo);
@@ -1902,7 +2041,7 @@ void RenderBlockFlow::clipOutFloatingObjects(RenderBlock* rootBlock, const Paint
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(floatingObject),
offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(floatingObject),
floatingObject->renderer()->width(), floatingObject->renderer()->height());
@@ -1944,6 +2083,8 @@ void RenderBlockFlow::removeFloatingObjects()
if (!m_floatingObjects)
return;
+ markSiblingsWithFloatsForLayout();
+
m_floatingObjects->clear();
}
@@ -1976,34 +2117,32 @@ LayoutUnit RenderBlockFlow::logicalRightOffsetForPositioningFloat(LayoutUnit log
return adjustLogicalRightOffsetForLine(offset, applyTextIndent);
}
+LayoutUnit RenderBlockFlow::adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
+{
+ LayoutUnit left = offsetFromFloats;
+
+ if (applyTextIndent && style()->isLeftToRightDirection())
+ left += textIndentOffset();
+
+ return left;
+}
+
+LayoutUnit RenderBlockFlow::adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const
+{
+ LayoutUnit right = offsetFromFloats;
+
+ if (applyTextIndent && !style()->isLeftToRightDirection())
+ right -= textIndentOffset();
+
+ return right;
+}
+
LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
{
RenderBox* childBox = floatingObject->renderer();
- LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+ LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(); // Constant part of left offset.
LayoutUnit logicalRightOffset; // Constant part of right offset.
- // FIXME Bug 102948: This only works for shape outside directly set on this block.
- ShapeInsideInfo* shapeInsideInfo = this->layoutShapeInsideInfo();
- // FIXME: Implement behavior for right floats.
- if (shapeInsideInfo) {
- LayoutSize floatLogicalSize = logicalSizeForFloat(floatingObject);
- // floatingObject's logicalSize doesn't contain the actual height at this point, so we need to calculate it
- floatLogicalSize.setHeight(logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox));
-
- // FIXME: If the float doesn't fit in the shape we should push it under the content box
- logicalTopOffset = shapeInsideInfo->computeFirstFitPositionForFloat(floatLogicalSize);
- if (logicalHeight() > logicalTopOffset)
- logicalTopOffset = logicalHeight();
-
- SegmentList segments = shapeInsideInfo->computeSegmentsForLine(logicalTopOffset, floatLogicalSize.height());
- // FIXME: Add support for shapes with multiple segments.
- if (segments.size() == 1) {
- // The segment offsets are relative to the content box.
- logicalRightOffset = logicalLeftOffset + segments[0].logicalRight;
- logicalLeftOffset += segments[0].logicalLeft;
- }
- } else {
- logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset);
- }
+ logicalRightOffset = logicalRightOffsetForContent();
LayoutUnit floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); // The width we look for.
@@ -2020,8 +2159,8 @@ LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject
floatLogicalLeft = logicalLeftOffsetForPositioningFloat(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
if (insideFlowThread) {
// Have to re-evaluate all of our offsets, since they may have changed.
- logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
- logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+ logicalRightOffset = logicalRightOffsetForContent(); // Constant part of right offset.
+ logicalLeftOffset = logicalLeftOffsetForContent(); // Constant part of left offset.
floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
}
}
@@ -2035,8 +2174,8 @@ LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject
floatLogicalLeft = logicalRightOffsetForPositioningFloat(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
if (insideFlowThread) {
// Have to re-evaluate all of our offsets, since they may have changed.
- logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
- logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+ logicalRightOffset = logicalRightOffsetForContent(); // Constant part of right offset.
+ logicalLeftOffset = logicalLeftOffsetForContent(); // Constant part of left offset.
floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
}
}
@@ -2061,7 +2200,7 @@ FloatingObject* RenderBlockFlow::insertFloatingObject(RenderBox* floatBox)
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator it = floatingObjectSet.find<FloatingObjectHashTranslator>(floatBox);
if (it != floatingObjectSet.end())
- return *it;
+ return it->get();
}
// Create the special object entry & append it to the list
@@ -2093,7 +2232,7 @@ void RenderBlockFlow::removeFloatingObject(RenderBox* floatBox)
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator it = floatingObjectSet.find<FloatingObjectHashTranslator>(floatBox);
if (it != floatingObjectSet.end()) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (childrenInline()) {
LayoutUnit logicalTop = logicalTopForFloat(floatingObject);
LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject);
@@ -2112,7 +2251,7 @@ void RenderBlockFlow::removeFloatingObject(RenderBox* floatBox)
ASSERT(floatingObject->originatingLine()->renderer() == this);
floatingObject->originatingLine()->markDirty();
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
floatingObject->setOriginatingLine(0);
#endif
}
@@ -2129,12 +2268,12 @@ void RenderBlockFlow::removeFloatingObjectsBelow(FloatingObject* lastFloat, int
return;
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- FloatingObject* curr = floatingObjectSet.last();
+ FloatingObject* curr = floatingObjectSet.last().get();
while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) {
m_floatingObjects->remove(curr);
if (floatingObjectSet.isEmpty())
break;
- curr = floatingObjectSet.last();
+ curr = floatingObjectSet.last().get();
}
}
@@ -2161,7 +2300,7 @@ bool RenderBlockFlow::positionNewFloats()
while (it != begin) {
--it;
if ((*it)->isPlaced()) {
- lastPlacedFloatingObject = *it;
+ lastPlacedFloatingObject = it->get();
++it;
break;
}
@@ -2176,15 +2315,18 @@ bool RenderBlockFlow::positionNewFloats()
FloatingObjectSetIterator end = floatingObjectSet.end();
// Now walk through the set of unpositioned floats and place them.
for (; it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
// 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.
if (floatingObject->renderer()->containingBlock() != this)
continue;
RenderBox* childBox = floatingObject->renderer();
- LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
+ // FIXME Investigate if this can be removed. crbug.com/370006
+ childBox->setMayNeedPaintInvalidation(true);
+
+ LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
LayoutRect oldRect = childBox->frameRect();
if (childBox->style()->clear() & CLEFT)
@@ -2199,7 +2341,7 @@ bool RenderBlockFlow::positionNewFloats()
setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
- SubtreeLayoutScope layoutScope(childBox);
+ SubtreeLayoutScope layoutScope(*childBox);
LayoutState* layoutState = view()->layoutState();
bool isPaginated = layoutState->isPaginated();
if (isPaginated && !childBox->needsLayout())
@@ -2243,10 +2385,11 @@ bool RenderBlockFlow::positionNewFloats()
m_floatingObjects->addPlacedObject(floatingObject);
if (ShapeOutsideInfo* shapeOutside = childBox->shapeOutsideInfo())
- shapeOutside->setShapeSize(logicalWidthForChild(childBox), logicalHeightForChild(childBox));
+ shapeOutside->setReferenceBoxLogicalSize(logicalSizeForChild(childBox));
// If the child moved, we have to repaint it.
- if (childBox->checkForRepaintDuringLayout())
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()
+ && childBox->checkForPaintInvalidationDuringLayout())
childBox->repaintDuringLayoutIfMoved(oldRect);
}
return true;
@@ -2262,13 +2405,17 @@ bool RenderBlockFlow::hasOverhangingFloat(RenderBox* renderer)
if (it == floatingObjectSet.end())
return false;
- return logicalBottomForFloat(*it) > logicalHeight();
+ return logicalBottomForFloat(it->get()) > logicalHeight();
}
void RenderBlockFlow::addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset)
{
ASSERT(!avoidsFloats());
+ // If we create our own block formatting context then our contents don't interact with floats outside it, even those from our parent.
+ if (createsBlockFormattingContext())
+ return;
+
// If the parent or previous sibling doesn't have any floats to add, don't bother.
if (!prev->m_floatingObjects)
return;
@@ -2278,7 +2425,7 @@ void RenderBlockFlow::addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit logic
const FloatingObjectSet& prevSet = prev->m_floatingObjects->set();
FloatingObjectSetIterator prevEnd = prevSet.end();
for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) {
- FloatingObject* floatingObject = *prevIt;
+ FloatingObject* floatingObject = prevIt->get();
if (logicalBottomForFloat(floatingObject) > logicalTopOffset) {
if (!m_floatingObjects || !m_floatingObjects->set().contains(floatingObject)) {
// We create the floating object list lazily.
@@ -2300,24 +2447,22 @@ void RenderBlockFlow::addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit logic
}
}
-LayoutUnit RenderBlockFlow::addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats)
+void RenderBlockFlow::addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats)
{
// Prevent floats from being added to the canvas by the root element, e.g., <html>.
- if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
- return 0;
+ if (!child->containsFloats() || child->isRenderRegion() || child->createsBlockFormattingContext())
+ return;
LayoutUnit childLogicalTop = child->logicalTop();
LayoutUnit childLogicalLeft = child->logicalLeft();
- LayoutUnit lowestFloatLogicalBottom = 0;
// Floats that will remain the child's responsibility to paint should factor into its
// overflow.
FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end();
for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
- FloatingObject* floatingObject = *childIt;
+ FloatingObject* floatingObject = childIt->get();
LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(floatingObject), LayoutUnit::max() - childLogicalTop);
LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat;
- lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
if (logicalBottom > logicalHeight()) {
// If the object is not in the list, we add it now.
@@ -2356,7 +2501,6 @@ LayoutUnit RenderBlockFlow::addOverhangingFloats(RenderBlockFlow* child, bool ma
child->addOverflowFromChild(floatingObject->renderer(), LayoutSize(xPositionForFloatIncludingMargin(floatingObject), yPositionForFloatIncludingMargin(floatingObject)));
}
}
- return lowestFloatLogicalBottom;
}
LayoutUnit RenderBlockFlow::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
@@ -2372,11 +2516,11 @@ LayoutUnit RenderBlockFlow::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight
if (!m_floatingObjects)
return logicalHeight;
- LayoutUnit logicalBottom = LayoutUnit::max();
+ LayoutUnit logicalBottom;
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
LayoutUnit floatLogicalBottom = logicalBottomForFloat(floatingObject);
ShapeOutsideInfo* shapeOutside = floatingObject->renderer()->shapeOutsideInfo();
if (shapeOutside && (offsetMode == ShapeOutsideFloatShapeOffset)) {
@@ -2386,10 +2530,10 @@ LayoutUnit RenderBlockFlow::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight
floatLogicalBottom = shapeLogicalBottom;
}
if (floatLogicalBottom > logicalHeight)
- logicalBottom = min(floatLogicalBottom, logicalBottom);
+ logicalBottom = logicalBottom ? min(floatLogicalBottom, logicalBottom) : floatLogicalBottom;
}
- return logicalBottom == LayoutUnit::max() ? LayoutUnit() : logicalBottom;
+ return logicalBottom;
}
bool RenderBlockFlow::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
@@ -2406,7 +2550,7 @@ bool RenderBlockFlow::hitTestFloats(const HitTestRequest& request, HitTestResult
FloatingObjectSetIterator begin = floatingObjectSet.begin();
for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) {
--it;
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (floatingObject->shouldPaint() && !floatingObject->renderer()->hasSelfPaintingLayer()) {
LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->x();
LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->y();
@@ -2428,7 +2572,7 @@ void RenderBlockFlow::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutU
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
// Only examine the object if our m_shouldPaint flag is set.
if (floatingObject->shouldPaint()) {
LayoutUnit floatLeft = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->x();
@@ -2512,12 +2656,40 @@ GapRects RenderBlockFlow::inlineSelectionGaps(RenderBlock* rootBlock, const Layo
return result;
}
+LayoutUnit RenderBlockFlow::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
+{
+ LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
+ if (logicalLeft == logicalLeftOffsetForContent())
+ return RenderBlock::logicalLeftSelectionOffset(rootBlock, position);
+
+ RenderBlock* cb = this;
+ while (cb != rootBlock) {
+ logicalLeft += cb->logicalLeft();
+ cb = cb->containingBlock();
+ }
+ return logicalLeft;
+}
+
+LayoutUnit RenderBlockFlow::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
+{
+ LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
+ if (logicalRight == logicalRightOffsetForContent())
+ return RenderBlock::logicalRightSelectionOffset(rootBlock, position);
+
+ RenderBlock* cb = this;
+ while (cb != rootBlock) {
+ logicalRight += cb->logicalLeft();
+ cb = cb->containingBlock();
+ }
+ return logicalRight;
+}
+
template <typename CharacterType>
-static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion)
{
ASSERT(style);
- TextDirection textDirection = LTR;
+ TextDirection textDirection = direction;
bool directionalOverride = style->rtlOrdering() == VisualOrder;
TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
@@ -2528,11 +2700,11 @@ static inline TextRun constructTextRunInternal(RenderObject* context, const Font
}
template <typename CharacterType>
-static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
+static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
{
ASSERT(style);
- TextDirection textDirection = LTR;
+ TextDirection textDirection = direction;
bool directionalOverride = style->rtlOrdering() == VisualOrder;
if (flags != DefaultTextRunFlags) {
if (flags & RespectDirection)
@@ -2542,109 +2714,90 @@ static inline TextRun constructTextRunInternal(RenderObject* context, const Font
}
TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
- if (!directionalOverride) {
- BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
- bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
- bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
- bool hasStrongDirectionality;
- TextDirection direction = bidiResolver.determineParagraphDirectionality(&hasStrongDirectionality);
- if (hasStrongDirectionality)
- run.setDirection(direction);
- }
-
if (textRunNeedsRenderingContext(font))
run.setRenderingContext(SVGTextRunRenderingContext::create(context));
return run;
}
-TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion)
{
- return constructTextRunInternal(context, font, characters, length, style, expansion);
+ return constructTextRunInternal(context, font, characters, length, style, direction, expansion);
}
-TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion)
{
- return constructTextRunInternal(context, font, characters, length, style, expansion);
+ return constructTextRunInternal(context, font, characters, length, style, direction, expansion);
}
-TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion)
{
if (text->is8Bit())
- return constructTextRunInternal(context, font, text->characters8(), text->textLength(), style, expansion);
- return constructTextRunInternal(context, font, text->characters16(), text->textLength(), style, expansion);
+ return constructTextRunInternal(context, font, text->characters8(), text->textLength(), style, direction, expansion);
+ return constructTextRunInternal(context, font, text->characters16(), text->textLength(), style, direction, expansion);
}
-TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion)
{
ASSERT(offset + length <= text->textLength());
if (text->is8Bit())
- return constructTextRunInternal(context, font, text->characters8() + offset, length, style, expansion);
- return constructTextRunInternal(context, font, text->characters16() + offset, length, style, expansion);
+ return constructTextRunInternal(context, font, text->characters8() + offset, length, style, direction, expansion);
+ return constructTextRunInternal(context, font, text->characters16() + offset, length, style, direction, expansion);
}
-TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, TextDirection direction, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
{
unsigned length = string.length();
if (!length)
- return constructTextRunInternal(context, font, static_cast<const LChar*>(0), length, style, expansion, flags);
+ return constructTextRunInternal(context, font, static_cast<const LChar*>(0), length, style, direction, expansion, flags);
if (string.is8Bit())
- return constructTextRunInternal(context, font, string.characters8(), length, style, expansion, flags);
- return constructTextRunInternal(context, font, string.characters16(), length, style, expansion, flags);
-}
-
-RootInlineBox* RenderBlockFlow::createRootInlineBox()
-{
- return new RootInlineBox(this);
-}
-
-void RenderBlockFlow::createRenderNamedFlowFragmentIfNeeded()
-{
- if (!RuntimeEnabledFeatures::cssRegionsEnabled()
- || renderNamedFlowFragment()
- || isRenderNamedFlowFragment())
- return;
-
- RenderStyle* styleToUse = style();
- if (styleToUse->isDisplayRegionType() && styleToUse->hasFlowFrom() && document().renderView()) {
- RenderNamedFlowFragment* flowFragment = RenderNamedFlowFragment::createAnonymous(&document());
- flowFragment->setStyleForNamedFlowFragment(styleToUse);
- setRenderNamedFlowFragment(flowFragment);
- addChild(flowFragment);
- }
+ return constructTextRunInternal(context, font, string.characters8(), length, style, direction, expansion, flags);
+ return constructTextRunInternal(context, font, string.characters16(), length, style, direction, expansion, flags);
}
-void RenderBlockFlow::insertedIntoTree()
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
{
- RenderBlock::insertedIntoTree();
-
- createRenderNamedFlowFragmentIfNeeded();
+ bool hasStrongDirectionality;
+ return constructTextRun(context, font, string, style,
+ determineDirectionality(string, hasStrongDirectionality),
+ expansion, flags);
}
-bool RenderBlockFlow::canHaveChildren() const
+TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
{
- return !renderNamedFlowFragment() ? RenderBlock::canHaveChildren() : renderNamedFlowFragment()->canHaveChildren();
+ ASSERT(offset + length <= text->textLength());
+ TextRun run = text->is8Bit()
+ ? constructTextRunInternal(context, font, text->characters8() + offset, length, style, LTR, expansion)
+ : constructTextRunInternal(context, font, text->characters16() + offset, length, style, LTR, expansion);
+ bool hasStrongDirectionality;
+ run.setDirection(directionForRun(run, hasStrongDirectionality));
+ return run;
}
-bool RenderBlockFlow::canHaveGeneratedChildren() const
+RootInlineBox* RenderBlockFlow::createRootInlineBox()
{
- return !renderNamedFlowFragment() ? RenderBlock::canHaveGeneratedChildren() : renderNamedFlowFragment()->canHaveGeneratedChildren();
+ return new RootInlineBox(*this);
}
-void RenderBlockFlow::updateLogicalHeight()
+void RenderBlockFlow::createOrDestroyMultiColumnFlowThreadIfNeeded()
{
- RenderBlock::updateLogicalHeight();
-
- if (renderNamedFlowFragment())
- renderNamedFlowFragment()->setLogicalHeight(max<LayoutUnit>(0, logicalHeight() - borderAndPaddingLogicalHeight()));
-}
+ if (!document().regionBasedColumnsEnabled())
+ return;
-void RenderBlockFlow::setRenderNamedFlowFragment(RenderNamedFlowFragment* flowFragment)
-{
- RenderBlockFlow::RenderBlockFlowRareData& rareData = ensureRareData();
- if (rareData.m_renderNamedFlowFragment)
- rareData.m_renderNamedFlowFragment->destroy();
- rareData.m_renderNamedFlowFragment = flowFragment;
+ bool needsFlowThread = style()->specifiesColumns();
+ if (needsFlowThread != static_cast<bool>(multiColumnFlowThread())) {
+ if (needsFlowThread) {
+ RenderMultiColumnFlowThread* flowThread = RenderMultiColumnFlowThread::createAnonymous(document(), style());
+ addChild(flowThread);
+ flowThread->populate();
+ RenderBlockFlowRareData& rareData = ensureRareData();
+ ASSERT(!rareData.m_multiColumnFlowThread);
+ rareData.m_multiColumnFlowThread = flowThread;
+ } else {
+ multiColumnFlowThread()->evacuateAndDestroy();
+ ASSERT(!multiColumnFlowThread());
+ }
+ }
}
RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.h b/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.h
index e68388194f5..2f94081d965 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBlockFlow.h
@@ -38,6 +38,7 @@
#include "core/rendering/FloatingObjects.h"
#include "core/rendering/RenderBlock.h"
+#include "core/rendering/line/TrailingObjects.h"
#include "core/rendering/style/RenderStyleConstants.h"
namespace WebCore {
@@ -45,7 +46,7 @@ namespace WebCore {
class MarginInfo;
class LineBreaker;
class LineWidth;
-class RenderNamedFlowFragment;
+class RenderMultiColumnFlowThread;
class RenderBlockFlow : public RenderBlock {
public:
@@ -53,15 +54,44 @@ public:
virtual ~RenderBlockFlow();
static RenderBlockFlow* createAnonymous(Document*);
- RenderBlockFlow* createAnonymousBlockFlow() const;
virtual bool isRenderBlockFlow() const OVERRIDE FINAL { return true; }
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
+ virtual void layoutBlock(bool relayoutChildren) OVERRIDE;
virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) OVERRIDE;
virtual void deleteLineBoxTree() OVERRIDE FINAL;
+ LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+ {
+ return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, logicalHeight) - logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
+ }
+ LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+ {
+ return logicalRightOffsetForLine(position, logicalRightOffsetForContent(), shouldIndentText, logicalHeight);
+ }
+ LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+ {
+ return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(), shouldIndentText, logicalHeight);
+ }
+ LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+ {
+ return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
+ : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
+ }
+ LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+ {
+ return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
+ : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
+ }
+
+ virtual LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position) OVERRIDE;
+ virtual LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position) OVERRIDE;
+
+ LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart);
+
+ RootInlineBox* createAndAppendRootInlineBox();
+
void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
@@ -70,6 +100,10 @@ public:
void removeFloatingObjects();
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+
+ void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert);
+
bool generatesLineBoxesForInlineChild(RenderObject*);
LayoutUnit logicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->y() : floatingObject->x(); }
@@ -124,67 +158,82 @@ public:
return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
}
+ // Direction resolved from string value.
static TextRun constructTextRun(RenderObject* context, const Font&, const String&, RenderStyle*,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
+ static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, unsigned length, RenderStyle*,
+ TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
- static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, RenderStyle*,
+ // Explicit direction.
+ static TextRun constructTextRun(RenderObject* context, const Font&, const String&, RenderStyle*, TextDirection,
+ TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
+
+ static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, RenderStyle*, TextDirection,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
- static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, unsigned length, RenderStyle*,
+ static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, unsigned length, RenderStyle*, TextDirection,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, RenderStyle*,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
- static TextRun constructTextRun(RenderObject* context, const Font&, const LChar* characters, int length, RenderStyle*,
+ static TextRun constructTextRun(RenderObject* context, const Font&, const LChar* characters, int length, RenderStyle*, TextDirection,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
- static TextRun constructTextRun(RenderObject* context, const Font&, const UChar* characters, int length, RenderStyle*,
+ static TextRun constructTextRun(RenderObject* context, const Font&, const UChar* characters, int length, RenderStyle*, TextDirection,
TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
- RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
- void setLineGridBox(RootInlineBox* box)
+ RenderMultiColumnFlowThread* multiColumnFlowThread() const { return m_rareData ? m_rareData->m_multiColumnFlowThread : 0; }
+ void resetMultiColumnFlowThread()
{
- RenderBlockFlow::RenderBlockFlowRareData& rareData = ensureRareData();
- if (rareData.m_lineGridBox)
- rareData.m_lineGridBox->destroy();
- rareData.m_lineGridBox = box;
+ if (m_rareData)
+ m_rareData->m_multiColumnFlowThread = 0;
}
- void layoutLineGridBox();
void addOverflowFromInlineChildren();
+ // FIXME: This should be const to avoid a const_cast, but can modify child dirty bits and RenderCombineText
+ void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
+
GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
protected:
- // Only used by RenderSVGText, which explicitly overrides RenderBlock::layoutBlock(), do NOT use for anything else.
- void forceLayoutInlineChildren()
- {
- LayoutUnit repaintLogicalTop = 0;
- LayoutUnit repaintLogicalBottom = 0;
- rebuildFloatsFromIntruding();
- layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
- }
+ void rebuildFloatsFromIntruding();
+ void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, LayoutUnit afterEdge);
void createFloatingObjects();
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
void addOverflowFromFloats();
- virtual void insertedIntoTree() OVERRIDE;
- virtual void willBeDestroyed() OVERRIDE;
+ LayoutUnit logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
+ {
+ return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
+ }
+ LayoutUnit logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
+ {
+ return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
+ }
+
+ virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/, SubtreeLayoutScope&);
+ virtual bool updateLogicalWidthAndColumnWidth() OVERRIDE;
+
+ // These functions optionally update LayoutState's layoutDelta, which is used to ensure they're repainted correctly when moved
+ enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
+ void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
+ void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
+ void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
+
private:
- void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom, SubtreeLayoutScope&);
- void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
+ bool layoutBlockFlow(bool relayoutChildren, LayoutUnit& pageLogicalHeight, SubtreeLayoutScope&);
+ void layoutBlockChildren(bool relayoutChildren, SubtreeLayoutScope&, LayoutUnit beforeEdge, LayoutUnit afterEdge);
- void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
+ void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom);
void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
void adjustFloatingBlock(const MarginInfo&);
- void rebuildFloatsFromIntruding();
-
LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
@@ -218,32 +267,39 @@ private:
bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
bool hasOverhangingFloat(RenderBox*);
void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset);
- LayoutUnit addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats);
+ void addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats);
LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const;
virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE FINAL;
- virtual void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) OVERRIDE;
virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
- virtual void repaintOverflow() OVERRIDE;
+ virtual void invalidatePaintForOverflow() OVERRIDE FINAL;
virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) OVERRIDE FINAL;
virtual void clipOutFloatingObjects(RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) OVERRIDE;
void clearFloats(EClear);
- virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const OVERRIDE;
- virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const OVERRIDE;
+ LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const;
+ LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const;
LayoutUnit logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
LayoutUnit logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
+ LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
+ LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
+
virtual void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const OVERRIDE; // Helper function for borderFitAdjust
- virtual RootInlineBox* createRootInlineBox() OVERRIDE;
+ virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG
+
+ void createOrDestroyMultiColumnFlowThreadIfNeeded();
+
+ void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount);
+ void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
+ bool shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const;
+ void setColumnCountAndHeight(unsigned count, LayoutUnit pageLogicalHeight);
- void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
- virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&);
public:
struct FloatWithRect {
FloatWithRect(RenderBox* f)
@@ -285,18 +341,15 @@ public:
};
MarginValues marginValuesForChild(RenderBox* child) const;
- virtual void updateLogicalHeight() OVERRIDE;
-
// Allocated only when some of these fields have non-default values
struct RenderBlockFlowRareData {
WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED;
public:
RenderBlockFlowRareData(const RenderBlockFlow* block)
: m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
- , m_lineGridBox(0)
+ , m_multiColumnFlowThread(0)
, m_discardMarginBefore(false)
, m_discardMarginAfter(false)
- , m_renderNamedFlowFragment(0)
{
}
@@ -319,17 +372,13 @@ public:
MarginValues m_margins;
- RootInlineBox* m_lineGridBox;
+ RenderMultiColumnFlowThread* m_multiColumnFlowThread;
bool m_discardMarginBefore : 1;
bool m_discardMarginAfter : 1;
- RenderNamedFlowFragment* m_renderNamedFlowFragment;
};
LayoutUnit marginOffsetForSelfCollapsingBlock();
- RenderNamedFlowFragment* renderNamedFlowFragment() const { return m_rareData ? m_rareData->m_renderNamedFlowFragment : 0; }
- void setRenderNamedFlowFragment(RenderNamedFlowFragment*);
-
protected:
LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(this); }
LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(this); }
@@ -367,11 +416,11 @@ private:
virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
- LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
- LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
+ LayoutUnit collapseMargins(RenderBox* child, MarginInfo&, bool childIsSelfCollapsing);
+ LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos, bool childIsSelfCollapsing);
LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
- void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
+ void handleAfterSideOfBlock(RenderBox* lastChild, LayoutUnit top, LayoutUnit bottom, MarginInfo&);
void setCollapsedBottomMargin(const MarginInfo&);
LayoutUnit applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset); // If the child has a before break, then return a new yPos that shifts to the top of the next page/column.
@@ -382,16 +431,12 @@ private:
// Used to store state between styleWillChange and styleDidChange
static bool s_canPropagateFloatIntoSibling;
- virtual bool canHaveChildren() const OVERRIDE;
- virtual bool canHaveGeneratedChildren() const OVERRIDE;
-
- void createRenderNamedFlowFragmentIfNeeded();
-
RenderBlockFlowRareData& ensureRareData();
LayoutUnit m_repaintLogicalTop;
LayoutUnit m_repaintLogicalBottom;
+ virtual bool isSelfCollapsingBlock() const OVERRIDE;
protected:
OwnPtr<RenderBlockFlowRareData> m_rareData;
OwnPtr<FloatingObjects> m_floatingObjects;
@@ -406,7 +451,7 @@ protected:
// line layout code is separated from RenderBlock and RenderBlockFlow.
// START METHODS DEFINED IN RenderBlockLineLayout
private:
- InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment);
+ InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
@@ -417,12 +462,9 @@ private:
void appendFloatingObjectToLastLine(FloatingObject*);
// Helper function for layoutInlineChildren()
RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
- void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
+ void layoutRunsAndFloats(LineLayoutState&);
const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&);
void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
- void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, const LayoutSize&, LineLayoutState&);
- void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&);
- bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
void linkToEndLineIfNeeded(LineLayoutState&);
static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBlockLineLayout.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderBlockLineLayout.cpp
index 9c877c5d802..722299ed03c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBlockLineLayout.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBlockLineLayout.cpp
@@ -22,8 +22,7 @@
#include "config.h"
-#include "core/rendering/FastTextAutosizer.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/accessibility/AXObjectCache.h"
#include "core/rendering/RenderCounter.h"
#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderLayer.h"
@@ -34,7 +33,12 @@
#include "core/rendering/TrailingFloatsRootInlineBox.h"
#include "core/rendering/VerticalPositionCache.h"
#include "core/rendering/line/BreakingContextInlineHeaders.h"
+#include "core/rendering/line/LineLayoutState.h"
+#include "core/rendering/line/LineWidth.h"
+#include "core/rendering/line/RenderTextInfo.h"
+#include "core/rendering/line/WordMeasurement.h"
#include "core/rendering/svg/SVGRootInlineBox.h"
+#include "platform/fonts/Character.h"
#include "platform/text/BidiResolver.h"
#include "wtf/RefCountedLeakCounter.h"
#include "wtf/StdLibExtras.h"
@@ -43,41 +47,8 @@
namespace WebCore {
-static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBreak, RenderStyle* style)
-{
- if (isFirstLine)
- return IndentText;
- if (isAfterHardLineBreak && style->textIndentLine() == TextIndentEachLine)
- return IndentText;
-
- return DoNotIndentText;
-}
-
-class LineBreaker {
-public:
- friend class BreakingContext;
- LineBreaker(RenderBlockFlow* block)
- : m_block(block)
- {
- reset();
- }
-
- InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
-
- bool lineWasHyphenated() { return m_hyphenated; }
- const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
- EClear clear() { return m_clear; }
-private:
- void reset();
-
- InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
- void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
-
- RenderBlockFlow* m_block;
- bool m_hyphenated;
- EClear m_clear;
- Vector<RenderBox*> m_positionedObjects;
-};
+using namespace std;
+using namespace WTF::Unicode;
static RenderObject* firstRenderObjectForDirectionalityDetermination(RenderObject* root, RenderObject* current = 0)
{
@@ -95,7 +66,7 @@ static RenderObject* firstRenderObjectForDirectionalityDetermination(RenderObjec
}
if (!current)
- current = root->firstChild();
+ current = root->slowFirstChild();
while (current) {
next = 0;
@@ -103,7 +74,7 @@ static RenderObject* firstRenderObjectForDirectionalityDetermination(RenderObjec
break;
if (!isIteratorTarget(current) && !isIsolated(current->style()->unicodeBidi()))
- next = current->firstChild();
+ next = current->slowFirstChild();
if (!next) {
while (current && current != root) {
@@ -135,7 +106,7 @@ static TextDirection determinePlaintextDirectionality(RenderObject* root, Render
static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
{
if (isRootLineBox)
- return toRenderBlock(obj)->createAndAppendRootInlineBox();
+ return toRenderBlockFlow(obj)->createAndAppendRootInlineBox();
if (obj->isText()) {
InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
@@ -171,7 +142,7 @@ static bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
return false;
}
-InlineFlowBox* RenderBlockFlow::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox, bool startNewSegment)
+InlineFlowBox* RenderBlockFlow::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox)
{
// See if we have an unconstructed line box for this object that is also
// the last item on the line.
@@ -194,8 +165,7 @@ InlineFlowBox* RenderBlockFlow::createLineBoxes(RenderObject* obj, const LineInf
// the same line (this can happen with very fancy language mixtures).
bool constructedNewBox = false;
bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
- bool mustCreateBoxesToRoot = startNewSegment && !(parentBox && parentBox->isRootInlineBox());
- bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox) && !mustCreateBoxesToRoot;
+ bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox);
if (allowedToConstructNewBox && !canUseExistingParentBox) {
// We need to make a new box for this render object. Once
// made, we need to place it at the end of the current line.
@@ -287,19 +257,17 @@ RootInlineBox* RenderBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, co
if (!box)
continue;
- if (!rootHasSelectedChildren && box->renderer()->selectionState() != RenderObject::SelectionNone)
+ if (!rootHasSelectedChildren && box->renderer().selectionState() != RenderObject::SelectionNone)
rootHasSelectedChildren = true;
// If we have no parent box yet, or if the run is not simply a sibling,
// then we need to construct inline boxes as necessary to properly enclose the
// run's inline box. Segments can only be siblings at the root level, as
// they are positioned separately.
- bool runStartsSegment = r->m_startsSegment;
-
- if (!parentBox || parentBox->renderer() != r->m_object->parent() || runStartsSegment)
+ if (!parentBox || parentBox->renderer() != r->m_object->parent()) {
// Create new inline boxes all the way back to the appropriate insertion point.
- parentBox = createLineBoxes(r->m_object->parent(), lineInfo, box, runStartsSegment);
- else {
+ parentBox = createLineBoxes(r->m_object->parent(), lineInfo, box);
+ } else {
// Append the inline box to this line.
parentBox->addToLine(box);
}
@@ -314,6 +282,9 @@ RootInlineBox* RenderBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, co
text->setDirOverride(r->dirOverride(visuallyOrdered));
if (r->m_hasHyphen)
text->setHasHyphen(true);
+
+ if (AXObjectCache* cache = document().existingAXObjectCache())
+ cache->inlineTextBoxesUpdated(r->m_object);
}
}
@@ -324,7 +295,7 @@ RootInlineBox* RenderBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, co
// Set the m_selectedChildren flag on the root inline box if one of the leaf inline box
// from the bidi runs walk above has a selection state.
if (rootHasSelectedChildren)
- lastLineBox()->root()->setHasSelectedChildren(true);
+ lastLineBox()->root().setHasSelectedChildren(true);
// Set bits on our inline flow boxes that indicate which sides should
// paint borders/margins/padding. This knowledge will ultimately be used when
@@ -466,11 +437,11 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
LayoutUnit hyphenWidth = 0;
if (toInlineTextBox(run->m_box)->hasHyphen()) {
const Font& font = renderer->style(lineInfo.isFirstLine())->font();
- hyphenWidth = measureHyphenWidth(renderer, font);
+ hyphenWidth = measureHyphenWidth(renderer, font, run->direction());
}
float measuredWidth = 0;
- bool kerningIsEnabled = font.typesettingFeatures() & Kerning;
+ bool kerningIsEnabled = font.fontDescription().typesettingFeatures() & Kerning;
#if OS(MACOSX)
// FIXME: Having any font feature settings enabled can lead to selection gaps on
@@ -495,7 +466,7 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
lastEndOffset = wordMeasurement.endOffset;
if (kerningIsEnabled && lastEndOffset == run->m_stop) {
int wordLength = lastEndOffset - wordMeasurement.startOffset;
- measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos, lineInfo.isFirstLine());
+ measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos, run->direction(), lineInfo.isFirstLine());
if (i > 0 && wordLength == 1 && renderer->characterAt(wordMeasurement.startOffset) == ' ')
measuredWidth += renderer->style()->wordSpacing();
} else
@@ -514,19 +485,19 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
}
if (!measuredWidth)
- measuredWidth = renderer->width(run->m_start, run->m_stop - run->m_start, xPos, lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
+ measuredWidth = renderer->width(run->m_start, run->m_stop - run->m_start, xPos, run->direction(), lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
run->m_box->setLogicalWidth(measuredWidth + hyphenWidth);
if (!fallbackFonts.isEmpty()) {
ASSERT(run->m_box->isText());
- GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
+ GlyphOverflowAndFallbackFontsMap::ValueType* it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).storedValue;
ASSERT(it->value.first.isEmpty());
copyToVector(fallbackFonts, it->value.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())).iterator;
+ GlyphOverflowAndFallbackFontsMap::ValueType* it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).storedValue;
it->value.second = glyphOverflow;
run->m_box->clearKnownToHaveNoOverflow();
}
@@ -539,9 +510,6 @@ static inline void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun*
size_t i = 0;
for (BidiRun* r = firstRun; r; r = r->next()) {
- // This method is called once per segment, do not move past the current segment.
- if (r->m_startsSegment)
- break;
if (!r->m_box || r == trailingSpaceRun)
continue;
@@ -550,8 +518,8 @@ static inline void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun*
ASSERT(opportunitiesInRun <= expansionOpportunityCount);
- // Only justify text if whitespace is collapsed.
- if (r->m_object->style()->collapseWhiteSpace()) {
+ // Don't justify for white-space: pre.
+ if (r->m_object->style()->whiteSpace() != PRE) {
InlineTextBox* textBox = toInlineTextBox(r->m_box);
int expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
textBox->setExpansion(expansion);
@@ -564,10 +532,10 @@ static inline void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun*
}
}
-void RenderBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount)
+void RenderBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount)
{
TextDirection direction;
- if (rootInlineBox && rootInlineBox->renderer()->style()->unicodeBidi() == Plaintext)
+ if (rootInlineBox && rootInlineBox->renderer().style()->unicodeBidi() == Plaintext)
direction = rootInlineBox->direction();
else
direction = style()->direction();
@@ -612,15 +580,15 @@ void RenderBlockFlow::updateLogicalWidthForAlignment(const ETextAlign& textAlign
updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
break;
}
+ if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ logicalLeft += verticalScrollbarWidth();
}
static void updateLogicalInlinePositions(RenderBlockFlow* block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
{
LayoutUnit lineLogicalHeight = block->minLineHeightForReplacedRenderer(firstLine, boxLogicalHeight);
- lineLogicalLeft = block->logicalLeftOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
- // FIXME: This shouldn't be pixel snapped once multicolumn layout has been updated to correctly carry over subpixel values.
- // https://bugs.webkit.org/show_bug.cgi?id=105461
- lineLogicalRight = block->pixelSnappedLogicalRightOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
+ lineLogicalLeft = block->logicalLeftOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight).toFloat();
+ lineLogicalRight = block->logicalRightOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight).toFloat();
availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
}
@@ -633,7 +601,7 @@ void RenderBlockFlow::computeInlineDirectionPositionsForLine(RootInlineBox* line
// box is only affected if it is the first child of its parent element."
// CSS3 "text-indent", "each-line" affects the first line of the block container as well as each line after a forced line break,
// but does not affect lines after a soft wrap break.
- bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->firstChild() != this);
+ bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->slowFirstChild() != this);
bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak();
IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLineBreak, style());
float lineLogicalLeft;
@@ -641,35 +609,6 @@ void RenderBlockFlow::computeInlineDirectionPositionsForLine(RootInlineBox* line
float availableLogicalWidth;
updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, 0);
bool needsWordSpacing;
- ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
- if (shapeInsideInfo && shapeInsideInfo->hasSegments()) {
- BidiRun* segmentStart = firstRun;
- const SegmentList& segments = shapeInsideInfo->segments();
- float logicalLeft = max<float>(segments[0].logicalLeft, lineLogicalLeft);
- float logicalRight = min<float>(segments[0].logicalRight, lineLogicalRight);
- float startLogicalLeft = logicalLeft;
- float endLogicalRight = logicalLeft;
- float minLogicalLeft = logicalLeft;
- float maxLogicalRight = logicalLeft;
- lineBox->beginPlacingBoxRangesInInlineDirection(logicalLeft);
- for (size_t i = 0; i < segments.size(); i++) {
- if (i) {
- logicalLeft = max<float>(segments[i].logicalLeft, lineLogicalLeft);
- logicalRight = min<float>(segments[i].logicalRight, lineLogicalRight);
- }
- availableLogicalWidth = logicalRight - logicalLeft;
- BidiRun* newSegmentStart = computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, logicalLeft, availableLogicalWidth, segmentStart, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
- needsWordSpacing = false;
- endLogicalRight = lineBox->placeBoxRangeInInlineDirection(segmentStart->m_box, newSegmentStart ? newSegmentStart->m_box : 0, logicalLeft, minLogicalLeft, maxLogicalRight, needsWordSpacing, textBoxDataMap);
- if (!newSegmentStart || !newSegmentStart->next())
- break;
- ASSERT(newSegmentStart->m_startsSegment);
- // Discard the empty segment start marker bidi runs
- segmentStart = newSegmentStart->next();
- }
- lineBox->endPlacingBoxRangesInInlineDirection(startLogicalLeft, endLogicalRight, minLogicalLeft, maxLogicalRight);
- return;
- }
if (firstRun && firstRun->m_object->isReplaced()) {
RenderBox* renderBox = toRenderBox(firstRun->m_object);
@@ -687,8 +626,8 @@ BidiRun* RenderBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBo
float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
WordMeasurements& wordMeasurements)
{
- bool needsWordSpacing = false;
- float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
+ bool needsWordSpacing = true;
+ float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth().toFloat();
unsigned expansionOpportunityCount = 0;
bool isAfterExpansion = true;
Vector<unsigned, 16> expansionOpportunities;
@@ -697,10 +636,6 @@ BidiRun* RenderBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBo
BidiRun* r = firstRun;
for (; r; r = r->next()) {
- // Once we have reached the start of the next segment, we have finished
- // computing the positions for this segment's contents.
- if (r->m_startsSegment)
- break;
if (!r->m_box || r->m_object->isOutOfFlowPositioned() || r->m_box->isLineBreak())
continue; // Positioned objects are only participating to figure out their
// correct static x position. They have no effect on the width.
@@ -712,17 +647,17 @@ BidiRun* RenderBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBo
toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true);
unsigned opportunitiesInRun;
if (rt->is8Bit())
- opportunitiesInRun = Font::expansionOpportunityCount(rt->characters8() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
+ opportunitiesInRun = Character::expansionOpportunityCount(rt->characters8() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
else
- opportunitiesInRun = Font::expansionOpportunityCount(rt->characters16() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
+ opportunitiesInRun = Character::expansionOpportunityCount(rt->characters16() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
expansionOpportunities.append(opportunitiesInRun);
expansionOpportunityCount += opportunitiesInRun;
}
- if (int length = rt->textLength()) {
+ if (rt->textLength()) {
if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characterAt(r->m_start)))
- totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().wordSpacing();
- needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1)) && r->m_stop == length;
+ totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().fontDescription().wordSpacing();
+ needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1));
}
setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements);
@@ -732,7 +667,7 @@ BidiRun* RenderBlockFlow::computeInlineDirectionPositionsForSegment(RootInlineBo
RenderBox* renderBox = toRenderBox(r->m_object);
if (renderBox->isRubyRun())
setMarginsForRubyRun(r, toRenderRubyRun(renderBox), previousObject, lineInfo);
- r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
+ r->m_box->setLogicalWidth(logicalWidthForChild(renderBox).toFloat());
totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
}
}
@@ -767,7 +702,7 @@ void RenderBlockFlow::computeBlockDirectionPositionsForLine(RootInlineBox* lineB
// Align positioned boxes with the top of the line box. This is
// a reasonable approximation of an appropriate y position.
if (r->m_object->isOutOfFlowPositioned())
- r->m_box->setLogicalTop(logicalHeight());
+ r->m_box->setLogicalTop(logicalHeight().toFloat());
// Position is used to properly position both replaced elements and
// to update the static normal flow x/y of positioned elements.
@@ -776,83 +711,6 @@ void RenderBlockFlow::computeBlockDirectionPositionsForLine(RootInlineBox* lineB
else if (r->m_object->isBox())
toRenderBox(r->m_object)->positionLineBox(r->m_box);
}
- // Positioned objects and zero-length text nodes destroy their boxes in
- // position(), which unnecessarily dirties the line.
- lineBox->markDirty(false);
-}
-
-static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
-{
- if (character == ' ' || character == '\t' || character == softHyphen)
- return true;
- if (character == '\n')
- return !renderer->style()->preserveNewline();
- return false;
-}
-
-template <typename CharacterType>
-static inline int findFirstTrailingSpace(RenderText* lastText, const CharacterType* characters, int start, int stop)
-{
- int firstSpace = stop;
- while (firstSpace > start) {
- UChar current = characters[firstSpace - 1];
- if (!isCollapsibleSpace(current, lastText))
- break;
- firstSpace--;
- }
-
- return firstSpace;
-}
-
-inline BidiRun* RenderBlockFlow::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
-{
- if (!bidiRuns.runCount()
- || !bidiRuns.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
- || !bidiRuns.logicallyLastRun()->m_object->style()->autoWrap())
- return 0;
-
- BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
- RenderObject* lastObject = trailingSpaceRun->m_object;
- if (!lastObject->isText())
- return 0;
-
- RenderText* lastText = toRenderText(lastObject);
- int firstSpace;
- if (lastText->is8Bit())
- firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), trailingSpaceRun->start(), trailingSpaceRun->stop());
- else
- firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(), trailingSpaceRun->start(), trailingSpaceRun->stop());
-
- if (firstSpace == trailingSpaceRun->stop())
- return 0;
-
- TextDirection direction = style()->direction();
- bool shouldReorder = trailingSpaceRun != (direction == LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
- if (firstSpace != trailingSpaceRun->start()) {
- BidiContext* baseContext = currentContext;
- while (BidiContext* parent = baseContext->parent())
- baseContext = parent;
-
- BidiRun* newTrailingRun = new BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral);
- trailingSpaceRun->m_stop = firstSpace;
- if (direction == LTR)
- bidiRuns.addRun(newTrailingRun);
- else
- bidiRuns.prependRun(newTrailingRun);
- trailingSpaceRun = newTrailingRun;
- return trailingSpaceRun;
- }
- if (!shouldReorder)
- return trailingSpaceRun;
-
- if (direction == LTR) {
- bidiRuns.moveRunToEnd(trailingSpaceRun);
- trailingSpaceRun->m_level = 0;
- } else {
- bidiRuns.moveRunToBeginning(trailingSpaceRun);
- trailingSpaceRun->m_level = 1;
- }
- return trailingSpaceRun;
}
void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
@@ -891,14 +749,14 @@ static void restoreIsolatedMidpointStates(InlineBidiResolver& topResolver, Inlin
}
// FIXME: BidiResolver should have this logic.
-static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfRuns, VisualDirectionOverride override, bool previousLineBrokeCleanly, bool isNewUBAParagraph)
+static inline void constructBidiRunsForLine(const RenderBlockFlow* block, InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly, bool isNewUBAParagraph)
{
// FIXME: We should pass a BidiRunList into createBidiRunsForLine instead
// of the resolver owning the runs.
ASSERT(&topResolver.runs() == &bidiRuns);
- ASSERT(topResolver.position() != endOfRuns);
+ ASSERT(topResolver.position() != endOfLine);
RenderObject* currentRoot = topResolver.position().root();
- topResolver.createBidiRunsForLine(endOfRuns, override, previousLineBrokeCleanly);
+ topResolver.createBidiRunsForLine(endOfLine, override, previousLineBrokeCleanly);
while (!topResolver.isolatedRuns().isEmpty()) {
// It does not matter which order we resolve the runs as long as we resolve them all.
@@ -919,7 +777,7 @@ static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver,
LineMidpointState& isolatedLineMidpointState = isolatedResolver.midpointState();
isolatedLineMidpointState = topResolver.midpointStateForIsolatedRun(isolatedRun);
EUnicodeBidi unicodeBidi = isolatedInline->style()->unicodeBidi();
- TextDirection direction = isolatedInline->style()->direction();
+ TextDirection direction;
if (unicodeBidi == Plaintext) {
if (isNewUBAParagraph)
direction = determinePlaintextDirectionality(isolatedInline, startObj);
@@ -941,7 +799,7 @@ static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver,
// We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns().
// FIXME: What should end and previousLineBrokeCleanly be?
// rniwa says previousLineBrokeCleanly is just a WinIE hack and could always be false here?
- isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, previousLineBrokeCleanly);
+ isolatedResolver.createBidiRunsForLine(endOfLine, NoVisualOverride, previousLineBrokeCleanly);
ASSERT(isolatedResolver.runs().runCount());
if (isolatedResolver.runs().runCount())
@@ -950,49 +808,13 @@ static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver,
// If we encountered any nested isolate runs, just move them
// to the top resolver's list for later processing.
if (!isolatedResolver.isolatedRuns().isEmpty()) {
- topResolver.isolatedRuns().append(isolatedResolver.isolatedRuns());
+ topResolver.isolatedRuns().appendVector(isolatedResolver.isolatedRuns());
currentRoot = isolatedInline;
restoreIsolatedMidpointStates(topResolver, isolatedResolver);
}
}
}
-static inline bool segmentIsEmpty(const InlineIterator& segmentStart, const InlineIterator& segmentEnd)
-{
- return segmentStart == segmentEnd;
-}
-
-static inline void constructBidiRunsForLine(const RenderBlockFlow* block, InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly, bool isNewUBAParagraph)
-{
- ShapeInsideInfo* shapeInsideInfo = block->layoutShapeInsideInfo();
- if (!shapeInsideInfo || !shapeInsideInfo->hasSegments()) {
- constructBidiRunsForSegment(topResolver, bidiRuns, endOfLine, override, previousLineBrokeCleanly, isNewUBAParagraph);
- return;
- }
-
- const SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges();
- ASSERT(segmentRanges.size());
-
- for (size_t i = 0; i < segmentRanges.size(); i++) {
- LineSegmentIterator iterator = segmentRanges[i].start;
- InlineIterator segmentStart(iterator.root, iterator.object, iterator.offset);
- iterator = segmentRanges[i].end;
- InlineIterator segmentEnd(iterator.root, iterator.object, iterator.offset);
- if (i) {
- ASSERT(segmentStart.object());
- BidiRun* segmentMarker = createRun(segmentStart.m_pos, segmentStart.m_pos, segmentStart.object(), topResolver);
- segmentMarker->m_startsSegment = true;
- bidiRuns.addRun(segmentMarker);
- // Do not collapse midpoints between segments
- topResolver.midpointState().betweenMidpoints = false;
- }
- if (!segmentIsEmpty(segmentStart, segmentEnd)) {
- topResolver.setPosition(segmentStart, numberOfIsolateAncestors(segmentStart));
- constructBidiRunsForSegment(topResolver, bidiRuns, segmentEnd, override, previousLineBrokeCleanly, isNewUBAParagraph);
- }
- }
-}
-
// This function constructs line boxes for all of the text runs in the resolver and computes their position.
RootInlineBox* RenderBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
{
@@ -1036,95 +858,6 @@ RootInlineBox* RenderBlockFlow::createLineBoxesFromBidiRuns(unsigned bidiLevel,
return lineBox;
}
-// Like LayoutState for layout(), LineLayoutState keeps track of global information
-// during an entire linebox tree layout pass (aka layoutInlineChildren).
-class LineLayoutState {
-public:
- LineLayoutState(bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFlowThread* flowThread)
- : m_lastFloat(0)
- , m_endLine(0)
- , m_floatIndex(0)
- , m_endLineLogicalTop(0)
- , m_endLineMatched(false)
- , m_checkForFloatsFromLastLine(false)
- , m_isFullLayout(fullLayout)
- , m_repaintLogicalTop(repaintLogicalTop)
- , m_repaintLogicalBottom(repaintLogicalBottom)
- , m_adjustedLogicalLineTop(0)
- , m_usesRepaintBounds(false)
- , m_flowThread(flowThread)
- { }
-
- void markForFullLayout() { m_isFullLayout = true; }
- bool isFullLayout() const { return m_isFullLayout; }
-
- bool usesRepaintBounds() const { return m_usesRepaintBounds; }
-
- void setRepaintRange(LayoutUnit logicalHeight)
- {
- m_usesRepaintBounds = true;
- m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight;
- }
-
- void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0)
- {
- m_usesRepaintBounds = true;
- m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min<LayoutUnit>(paginationDelta, 0));
- m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max<LayoutUnit>(paginationDelta, 0));
- }
-
- bool endLineMatched() const { return m_endLineMatched; }
- void setEndLineMatched(bool endLineMatched) { m_endLineMatched = endLineMatched; }
-
- bool checkForFloatsFromLastLine() const { return m_checkForFloatsFromLastLine; }
- void setCheckForFloatsFromLastLine(bool check) { m_checkForFloatsFromLastLine = check; }
-
- LineInfo& lineInfo() { return m_lineInfo; }
- const LineInfo& lineInfo() const { return m_lineInfo; }
-
- 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; }
-
- FloatingObject* lastFloat() const { return m_lastFloat; }
- void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
-
- Vector<RenderBlockFlow::FloatWithRect>& floats() { return m_floats; }
-
- unsigned floatIndex() const { return m_floatIndex; }
- void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }
-
- LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; }
- void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; }
-
- RenderFlowThread* flowThread() const { return m_flowThread; }
- void setFlowThread(RenderFlowThread* thread) { m_flowThread = thread; }
-
-private:
- Vector<RenderBlockFlow::FloatWithRect> m_floats;
- FloatingObject* m_lastFloat;
- RootInlineBox* m_endLine;
- LineInfo m_lineInfo;
- unsigned m_floatIndex;
- LayoutUnit m_endLineLogicalTop;
- bool m_endLineMatched;
- bool m_checkForFloatsFromLastLine;
-
- bool m_isFullLayout;
-
- // FIXME: Should this be a range object instead of two ints?
- LayoutUnit& m_repaintLogicalTop;
- LayoutUnit& m_repaintLogicalBottom;
-
- LayoutUnit m_adjustedLogicalLineTop;
-
- bool m_usesRepaintBounds;
-
- RenderFlowThread* m_flowThread;
-};
-
static void deleteLineRange(LineLayoutState& layoutState, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
{
RootInlineBox* boxToDelete = startLine;
@@ -1138,7 +871,7 @@ static void deleteLineRange(LineLayoutState& layoutState, RootInlineBox* startLi
}
}
-void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
+void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState)
{
// We want to skip ahead to the first dirty line
InlineBidiResolver resolver;
@@ -1150,30 +883,8 @@ void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool has
consecutiveHyphenatedLines++;
}
- // FIXME: This would make more sense outside of this function, but since
- // 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()) {
- // Mark as needing a full layout to force us to repaint. Allow regions
- // to reflow as needed.
- setNeedsLayout(MarkOnlyThis);
-
- if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
- setShouldDoFullRepaintAfterLayout(true);
- } else {
- RenderView* v = view();
- if (v && !v->doingFullRepaint() && hasLayer()) {
- // Because we waited until we were already inside layout to discover
- // that the block really needed a full layout, we missed our chance to repaint the layer
- // before layout started. Luckily the layer has cached the repaint rect for its original
- // position and size, and so we can use that to make a repaint happen now.
- repaintUsingContainer(containerForRepaint(), pixelSnappedIntRect(layer()->repainter().repaintRect()));
- }
- }
- }
-
if (containsFloats())
- layoutState.setLastFloat(m_floatingObjects->set().last());
+ layoutState.setLastFloat(m_floatingObjects->set().last().get());
// We also find the first clean line and extract these lines. We will add them back
// if we determine that we're able to synchronize after handling all our dirty lines.
@@ -1193,9 +904,9 @@ void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool has
// adjust the height accordingly.
// A line break can be either the first or the last object on a line, depending on its direction.
if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) {
- RenderObject* lastObject = lastLeafChild->renderer();
+ RenderObject* lastObject = &lastLeafChild->renderer();
if (!lastObject->isBR())
- lastObject = lastRootBox()->firstLeafChild()->renderer();
+ lastObject = &lastRootBox()->firstLeafChild()->renderer();
if (lastObject->isBR()) {
EClear clear = lastObject->style()->clear();
if (clear != CNONE)
@@ -1209,16 +920,6 @@ void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool has
repaintDirtyFloats(layoutState.floats());
}
-RenderTextInfo::RenderTextInfo()
- : m_text(0)
- , m_font(0)
-{
-}
-
-RenderTextInfo::~RenderTextInfo()
-{
-}
-
// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver, const InlineIterator& oldEnd)
{
@@ -1228,161 +929,6 @@ inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(
return oldEnd;
}
-static inline LayoutUnit adjustLogicalLineTop(ShapeInsideInfo* shapeInsideInfo, InlineIterator start, InlineIterator end, const WordMeasurements& wordMeasurements)
-{
- if (!shapeInsideInfo || end != start)
- return 0;
-
- float minWidth = firstPositiveWidth(wordMeasurements);
- ASSERT(minWidth || wordMeasurements.isEmpty());
- if (minWidth > 0 && shapeInsideInfo->adjustLogicalLineTop(minWidth))
- return shapeInsideInfo->logicalLineTop();
-
- return shapeInsideInfo->shapeLogicalBottom();
-}
-
-static inline void pushShapeContentOverflowBelowTheContentBox(RenderBlockFlow* block, ShapeInsideInfo* shapeInsideInfo, LayoutUnit lineTop, LayoutUnit lineHeight)
-{
- ASSERT(shapeInsideInfo);
-
- LayoutUnit logicalLineBottom = lineTop + lineHeight;
- LayoutUnit shapeLogicalBottom = shapeInsideInfo->shapeLogicalBottom();
- LayoutUnit shapeContainingBlockHeight = shapeInsideInfo->shapeContainingBlockHeight();
-
- bool isOverflowPositionedAlready = (shapeContainingBlockHeight - shapeInsideInfo->owner()->borderAndPaddingAfter() + lineHeight) <= lineTop;
-
- // If the last line overlaps with the shape, we don't need the segments anymore
- if (lineTop < shapeLogicalBottom && shapeLogicalBottom < logicalLineBottom)
- shapeInsideInfo->clearSegments();
- if (logicalLineBottom <= shapeLogicalBottom || !shapeContainingBlockHeight || isOverflowPositionedAlready)
- return;
-
- LayoutUnit newLogicalHeight = block->logicalHeight() + (shapeContainingBlockHeight - (lineTop + shapeInsideInfo->owner()->borderAndPaddingAfter()));
- block->setLogicalHeight(newLogicalHeight);
-}
-
-void RenderBlockFlow::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, const LayoutSize& logicalOffsetFromShapeContainer, LineLayoutState& layoutState)
-{
- if (layoutState.flowThread())
- return updateShapeAndSegmentsForCurrentLineInFlowThread(shapeInsideInfo, layoutState);
-
- if (!shapeInsideInfo)
- return;
-
- LayoutUnit lineTop = logicalHeight() + logicalOffsetFromShapeContainer.height();
- LayoutUnit lineLeft = logicalOffsetFromShapeContainer.width();
- LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
-
- // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which case these segments may be incorrect.
- shapeInsideInfo->updateSegmentsForLine(LayoutSize(lineLeft, lineTop), lineHeight);
-
- pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
-}
-
-void RenderBlockFlow::updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*& shapeInsideInfo, LineLayoutState& layoutState)
-{
- ASSERT(layoutState.flowThread());
-
- RenderRegion* currentRegion = regionAtBlockOffset(logicalHeight());
- if (!currentRegion || !currentRegion->logicalHeight())
- return;
-
- shapeInsideInfo = currentRegion->shapeInsideInfo();
-
- RenderRegion* nextRegion = 0;
- if (!currentRegion->isLastRegion()) {
- RenderRegionList regionList = layoutState.flowThread()->renderRegionList();
- RenderRegionList::const_iterator it = regionList.find(currentRegion);
- nextRegion = *(++it);
- }
-
- // We only want to deal regions with shapes, so we check if the next region has a shape
- if (!shapeInsideInfo && nextRegion && !nextRegion->shapeInsideInfo())
- return;
-
- LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
- LayoutUnit logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFirstPage();
- LayoutUnit logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight;
- LayoutUnit logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadContent();
- LayoutUnit logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegion->borderAndPaddingAfter();
-
- LayoutUnit shapeBottomInFlowThread = LayoutUnit::max();
- if (shapeInsideInfo)
- shapeBottomInFlowThread = shapeInsideInfo->shapeLogicalBottom() + currentRegion->logicalTopForFlowThreadContent();
-
- bool lineOverLapsWithShapeBottom = shapeBottomInFlowThread < logicalLineBottomInFlowThread;
- bool lineOverLapsWithRegionBottom = logicalLineBottomInFlowThread > logicalRegionBottomInFlowThread;
- bool overFlowsToNextRegion = nextRegion && (lineOverLapsWithShapeBottom || lineOverLapsWithRegionBottom);
-
- // If the line is between two shapes/regions we position the line to the top of the next shape/region
- if (overFlowsToNextRegion) {
- ASSERT(currentRegion != nextRegion);
- LayoutUnit deltaToNextRegion = logicalRegionBottomInFlowThread - logicalLineTopInFlowThread;
- setLogicalHeight(logicalHeight() + deltaToNextRegion);
-
- currentRegion = nextRegion;
- shapeInsideInfo = currentRegion->shapeInsideInfo();
-
- logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFirstPage();
- logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight;
- logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadContent();
- logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegion->borderAndPaddingAfter();
- }
-
- if (!shapeInsideInfo)
- return;
-
- bool isFirstLineInRegion = logicalLineBottomInFlowThread <= (logicalRegionTopInFlowThread + lineHeight);
- bool isFirstLineAdjusted = (logicalLineTopInFlowThread - logicalRegionTopInFlowThread) < (layoutState.adjustedLogicalLineTop() - currentRegion->borderAndPaddingBefore());
- // We position the first line to the top of the shape in the region or to the previously adjusted position in the shape
- if (isFirstLineInRegion || isFirstLineAdjusted) {
- LayoutUnit shapeTopOffset = layoutState.adjustedLogicalLineTop();
- if (!shapeTopOffset && (shapeInsideInfo->shapeLogicalTop() > 0))
- shapeTopOffset = shapeInsideInfo->shapeLogicalTop();
-
- LayoutUnit shapePositionInFlowThread = currentRegion->logicalTopForFlowThreadContent() + shapeTopOffset;
- LayoutUnit shapeTopLineTopDelta = shapePositionInFlowThread - logicalLineTopInFlowThread - currentRegion->borderAndPaddingBefore();
-
- setLogicalHeight(logicalHeight() + shapeTopLineTopDelta);
- logicalLineTopInFlowThread += shapeTopLineTopDelta;
- layoutState.setAdjustedLogicalLineTop(0);
- }
-
- LayoutUnit lineTop = logicalLineTopInFlowThread - currentRegion->logicalTopForFlowThreadContent() + currentRegion->borderAndPaddingBefore();
- // FIXME: Shape inside on a region does not yet take into account its padding for nested flow blocks
- shapeInsideInfo->updateSegmentsForLine(LayoutSize(0, lineTop), lineHeight);
-
- if (currentRegion->isLastRegion())
- pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
-}
-
-bool RenderBlockFlow::adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo* shapeInsideInfo, LayoutUnit absoluteLogicalTop, LineLayoutState& layoutState, InlineBidiResolver& resolver, FloatingObject* lastFloatFromPreviousLine, InlineIterator& end, WordMeasurements& wordMeasurements)
-{
- LayoutUnit adjustedLogicalLineTop = adjustLogicalLineTop(shapeInsideInfo, resolver.position(), end, wordMeasurements);
-
- if (shapeInsideInfo && containsFloats()) {
- lastFloatFromPreviousLine = m_floatingObjects->set().last();
- if (!wordMeasurements.size()) {
- LayoutUnit floatLogicalTopOffset = shapeInsideInfo->computeFirstFitPositionForFloat(logicalSizeForFloat(lastFloatFromPreviousLine));
- if (logicalHeight() < floatLogicalTopOffset)
- adjustedLogicalLineTop = floatLogicalTopOffset;
- }
- }
-
- if (!adjustedLogicalLineTop)
- return false;
-
- LayoutUnit newLogicalHeight = adjustedLogicalLineTop - absoluteLogicalTop;
-
- if (layoutState.flowThread()) {
- layoutState.setAdjustedLogicalLineTop(adjustedLogicalLineTop);
- newLogicalHeight = logicalHeight();
- }
-
- end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, lastFloatFromPreviousLine, resolver, end);
- return true;
-}
-
void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
{
RenderStyle* styleToUse = style();
@@ -1396,22 +942,6 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
LineBreaker lineBreaker(this);
LayoutSize logicalOffsetFromShapeContainer;
- ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
- if (shapeInsideInfo) {
- ASSERT(shapeInsideInfo->owner() == this || allowsShapeInsideInfoSharing(shapeInsideInfo->owner()));
- if (shapeInsideInfo != this->shapeInsideInfo()) {
- // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add
- // their offsets from the original shape-inside container.
- logicalOffsetFromShapeContainer = logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner());
- }
- // Begin layout at the logical top of our shape inside.
- if (logicalHeight() + logicalOffsetFromShapeContainer.height() < shapeInsideInfo->shapeLogicalTop()) {
- LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - logicalOffsetFromShapeContainer.height();
- if (layoutState.flowThread())
- logicalHeight -= shapeInsideInfo->owner()->borderAndPaddingBefore();
- setLogicalHeight(logicalHeight);
- }
- }
while (!endOfLine.atEnd()) {
// FIXME: Is this check necessary before the first iteration or can it be moved to the end?
@@ -1430,9 +960,7 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
const InlineIterator previousEndofLine = endOfLine;
bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
- FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_floatingObjects->set().last() : 0;
-
- updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, logicalOffsetFromShapeContainer, layoutState);
+ FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_floatingObjects->set().last().get() : 0;
WordMeasurements wordMeasurements;
endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
@@ -1447,18 +975,14 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
break;
}
- if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, logicalOffsetFromShapeContainer.height(), layoutState, resolver, lastFloatFromPreviousLine, endOfLine, wordMeasurements))
- continue;
-
ASSERT(endOfLine != resolver.position());
// This is a short-cut for empty lines.
if (layoutState.lineInfo().isEmpty()) {
if (lastRootBox())
- lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.m_pos, resolver.status());
+ lastRootBox()->setLineBreakInfo(endOfLine.object(), endOfLine.offset(), resolver.status());
} else {
VisualDirectionOverride override = (styleToUse->rtlOrdering() == VisualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
-
if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && !resolver.context()->parent()) {
TextDirection direction = determinePlaintextDirectionality(resolver.position().root(), resolver.position().object(), resolver.position().offset());
resolver.setStatus(BidiStatus(direction, isOverride(styleToUse->unicodeBidi())));
@@ -1468,7 +992,7 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
constructBidiRunsForLine(this, resolver, bidiRuns, endOfLine, override, layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph);
ASSERT(resolver.position() == endOfLine);
- BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrokeCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
+ BidiRun* trailingSpaceRun = resolver.trailingSpaceRun();
if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
bidiRuns.logicallyLastRun()->m_hasHyphen = true;
@@ -1487,7 +1011,7 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
if (lineBox) {
- lineBox->setLineBreakInfo(endOfLine.object(), endOfLine.m_pos, resolver.status());
+ lineBox->setLineBreakInfo(endOfLine.object(), endOfLine.offset(), resolver.status());
if (layoutState.usesRepaintBounds())
layoutState.updateRepaintRangeFromBox(lineBox);
@@ -1496,7 +1020,7 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
adjustLinePositionForPagination(lineBox, adjustment, layoutState.flowThread());
if (adjustment) {
LayoutUnit oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, layoutState.lineInfo().isFirstLine());
- lineBox->adjustBlockDirectionPosition(adjustment);
+ lineBox->adjustBlockDirectionPosition(adjustment.toFloat());
if (layoutState.usesRepaintBounds())
layoutState.updateRepaintRangeFromBox(lineBox);
@@ -1509,9 +1033,6 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
setLogicalHeight(lineBox->lineBottomWithLeading());
}
-
- if (layoutState.flowThread())
- updateRegionForLine(lineBox);
}
}
}
@@ -1535,7 +1056,7 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
it = lastFloatIterator;
}
for (; it != end; ++it) {
- FloatingObject* f = *it;
+ FloatingObject* f = it->get();
appendFloatingObjectToLastLine(f);
ASSERT(f->renderer() == layoutState.floats()[layoutState.floatIndex()].object);
// If a float's geometry has changed, give up on syncing with clean lines.
@@ -1543,7 +1064,7 @@ void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I
checkForEndLineMatch = false;
layoutState.setFloatIndex(layoutState.floatIndex() + 1);
}
- layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0);
+ layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : 0);
}
lineMidpointState.reset();
@@ -1628,10 +1149,8 @@ void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
}
if (delta) {
layoutState.updateRepaintRangeFromBox(line, delta);
- line->adjustBlockDirectionPosition(delta);
+ line->adjustBlockDirectionPosition(delta.toFloat());
}
- if (layoutState.flowThread())
- updateRegionForLine(line);
if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
Vector<RenderBox*>::iterator end = cleanLineFloats->end();
for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
@@ -1657,7 +1176,7 @@ void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
if (layoutState.checkForFloatsFromLastLine()) {
LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
- TrailingFloatsRootInlineBox* trailingFloatsLineBox = new TrailingFloatsRootInlineBox(this);
+ TrailingFloatsRootInlineBox* trailingFloatsLineBox = new TrailingFloatsRootInlineBox(*this);
m_lineBoxes.appendLineBox(trailingFloatsLineBox);
trailingFloatsLineBox->setConstructed();
GlyphOverflowAndFallbackFontsMap textBoxDataMap;
@@ -1665,12 +1184,10 @@ void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
LayoutUnit blockLogicalHeight = logicalHeight();
trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
- trailingFloatsLineBox->setPaginatedLineWidth(availableLogicalWidthForContent(blockLogicalHeight));
+ trailingFloatsLineBox->setPaginatedLineWidth(availableLogicalWidthForContent());
LayoutRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
- if (layoutState.flowThread())
- updateRegionForLine(trailingFloatsLineBox);
}
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
@@ -1683,42 +1200,460 @@ void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
it = lastFloatIterator;
}
for (; it != end; ++it)
- appendFloatingObjectToLastLine(*it);
- layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0);
+ appendFloatingObjectToLastLine(it->get());
+ layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : 0);
}
}
void RenderBlockFlow::repaintDirtyFloats(Vector<FloatWithRect>& floats)
{
size_t floatCount = floats.size();
- // Floats that did not have layout did not repaint when we laid them out. They would have
+ // Floats that did not have layout did not paint invalidations when we laid them out. They would have
// painted by now if they had moved, but if they stayed at (0, 0), they still need to be
// painted.
for (size_t i = 0; i < floatCount; ++i) {
if (!floats[i].everHadLayout) {
RenderBox* f = floats[i].object;
- if (!f->x() && !f->y() && f->checkForRepaintDuringLayout()) {
+ if (!f->x() && !f->y() && f->checkForPaintInvalidation()) {
if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
- f->setShouldDoFullRepaintAfterLayout(true);
+ f->setShouldDoFullPaintInvalidationAfterLayout(true);
else
- f->repaint();
+ f->paintInvalidationForWholeRenderer();
}
}
}
}
-void RenderBlockFlow::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom)
+struct InlineMinMaxIterator {
+/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
+ inline min/max width calculations. Note the following about the way it walks:
+ (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
+ (2) We do not drill into the children of floats or replaced elements, since you can't break
+ in the middle of such an element.
+ (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
+ distinct borders/margin/padding that contribute to the min/max width.
+*/
+ RenderObject* parent;
+ RenderObject* current;
+ bool endOfInline;
+
+ InlineMinMaxIterator(RenderObject* p, bool end = false)
+ : parent(p), current(p), endOfInline(end)
+ {
+
+ }
+
+ RenderObject* next();
+};
+
+RenderObject* InlineMinMaxIterator::next()
{
- FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
- if (textAutosizer)
- textAutosizer->inflate(this);
+ RenderObject* result = 0;
+ bool oldEndOfInline = endOfInline;
+ endOfInline = false;
+ while (current || current == parent) {
+ if (!oldEndOfInline && (current == parent || (!current->isFloating() && !current->isReplaced() && !current->isOutOfFlowPositioned())))
+ result = current->slowFirstChild();
+
+ if (!result) {
+ // We hit the end of our inline. (It was empty, e.g., <span></span>.)
+ if (!oldEndOfInline && current->isRenderInline()) {
+ result = current;
+ endOfInline = true;
+ break;
+ }
- setLogicalHeight(borderBefore() + paddingBefore());
+ while (current && current != parent) {
+ result = current->nextSibling();
+ if (result)
+ break;
+ current = current->parent();
+ if (current && current != parent && current->isRenderInline()) {
+ result = current;
+ endOfInline = true;
+ break;
+ }
+ }
+ }
+
+ if (!result)
+ break;
- // Lay out our hypothetical grid line as though it occurs at the top of the block.
- if (view()->layoutState() && view()->layoutState()->lineGrid() == this)
- layoutLineGridBox();
+ if (!result->isOutOfFlowPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
+ break;
+ current = result;
+ result = 0;
+ }
+
+ // Update our position.
+ current = result;
+ return current;
+}
+
+static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
+{
+ if (cssUnit.type() != Auto)
+ return (cssUnit.isFixed() ? static_cast<LayoutUnit>(cssUnit.value()) : childValue);
+ return 0;
+}
+
+static LayoutUnit getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline)
+{
+ RenderStyle* childStyle = child->style();
+ if (endOfInline) {
+ return getBPMWidth(child->marginEnd(), childStyle->marginEnd()) +
+ getBPMWidth(child->paddingEnd(), childStyle->paddingEnd()) +
+ child->borderEnd();
+ }
+ return getBPMWidth(child->marginStart(), childStyle->marginStart()) +
+ getBPMWidth(child->paddingStart(), childStyle->paddingStart()) +
+ child->borderStart();
+}
+
+static inline void stripTrailingSpace(float& inlineMax, float& inlineMin, RenderObject* trailingSpaceChild)
+{
+ if (trailingSpaceChild && trailingSpaceChild->isText()) {
+ // Collapse away the trailing space at the end of a block.
+ RenderText* t = toRenderText(trailingSpaceChild);
+ const UChar space = ' ';
+ const Font& font = t->style()->font(); // FIXME: This ignores first-line.
+ float spaceWidth = font.width(RenderBlockFlow::constructTextRun(t, font, &space, 1, t->style(), LTR));
+ inlineMax -= spaceWidth + font.fontDescription().wordSpacing();
+ if (inlineMin > inlineMax)
+ inlineMin = inlineMax;
+ }
+}
+
+static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
+{
+ LayoutUnit snappedResult = LayoutUnit::fromFloatCeil(result);
+ preferredWidth = max(snappedResult, preferredWidth);
+}
+
+// When converting between floating point and LayoutUnits we risk losing precision
+// with each conversion. When this occurs while accumulating our preferred widths,
+// we can wind up with a line width that's larger than our maxPreferredWidth due to
+// pure float accumulation.
+static inline LayoutUnit adjustFloatForSubPixelLayout(float value)
+{
+ return LayoutUnit::fromFloatCeil(value);
+}
+
+// FIXME: This function should be broken into something less monolithic.
+// FIXME: The main loop here is very similar to LineBreaker::nextSegmentBreak. They can probably reuse code.
+void RenderBlockFlow::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth)
+{
+ float inlineMax = 0;
+ float inlineMin = 0;
+
+ RenderStyle* styleToUse = style();
+ RenderBlock* containingBlock = this->containingBlock();
+ LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
+
+ // 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.
+ bool stripFrontSpaces = true;
+ RenderObject* trailingSpaceChild = 0;
+
+ // Firefox and Opera will allow a table cell to grow to fit an image inside it under
+ // very specific cirucumstances (in order to match common WinIE renderings).
+ // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
+ bool allowImagesToBreak = !document().inQuirksMode() || !isTableCell() || !styleToUse->logicalWidth().isIntrinsicOrAuto();
+
+ bool autoWrap, oldAutoWrap;
+ autoWrap = oldAutoWrap = styleToUse->autoWrap();
+
+ InlineMinMaxIterator childIterator(this);
+
+ // Only gets added to the max preffered width once.
+ bool addedTextIndent = false;
+ // Signals the text indent was more negative than the min preferred width
+ bool hasRemainingNegativeTextIndent = false;
+
+ LayoutUnit textIndent = minimumValueForLength(styleToUse->textIndent(), cw);
+ RenderObject* prevFloat = 0;
+ bool isPrevChildInlineFlow = false;
+ bool shouldBreakLineAfterText = false;
+ while (RenderObject* child = childIterator.next()) {
+ autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() :
+ child->style()->autoWrap();
+
+ if (!child->isBR()) {
+ // Step One: determine whether or not we need to go ahead and
+ // terminate our current line. Each discrete chunk can become
+ // the new min-width, if it is the widest chunk seen so far, and
+ // it can also become the max-width.
+
+ // Children fall into three categories:
+ // (1) An inline flow object. These objects always have a min/max of 0,
+ // and are included in the iteration solely so that their margins can
+ // be added in.
+ //
+ // (2) An inline non-text non-flow object, e.g., an inline replaced element.
+ // These objects can always be on a line by themselves, so in this situation
+ // we need to go ahead and break the current line, and then add in our own
+ // margins and min/max width on its own line, and then terminate the line.
+ //
+ // (3) A text object. Text runs can have breakable characters at the start,
+ // the middle or the end. They may also lose whitespace off the front if
+ // we're already ignoring whitespace. In order to compute accurate min-width
+ // information, we need three pieces of information.
+ // (a) the min-width of the first non-breakable run. Should be 0 if the text string
+ // starts with whitespace.
+ // (b) the min-width of the last non-breakable run. Should be 0 if the text string
+ // ends with whitespace.
+ // (c) the min/max width of the string (trimmed for whitespace).
+ //
+ // If the text string starts with whitespace, then we need to go ahead and
+ // terminate our current line (unless we're already in a whitespace stripping
+ // mode.
+ //
+ // If the text string has a breakable character in the middle, but didn't start
+ // with whitespace, then we add the width of the first non-breakable run and
+ // then end the current line. We then need to use the intermediate min/max width
+ // values (if any of them are larger than our current min/max). We then look at
+ // the width of the last non-breakable run and use that to start a new line
+ // (unless we end in whitespace).
+ RenderStyle* childStyle = child->style();
+ float childMin = 0;
+ float childMax = 0;
+
+ if (!child->isText()) {
+ // Case (1) and (2). Inline replaced and inline flow elements.
+ if (child->isRenderInline()) {
+ // Add in padding/border/margin from the appropriate side of
+ // the element.
+ float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline).toFloat();
+ childMin += bpm;
+ childMax += bpm;
+
+ inlineMin += childMin;
+ inlineMax += childMax;
+
+ child->clearPreferredLogicalWidthsDirty();
+ } else {
+ // Inline replaced elts add in their margins to their min/max values.
+ LayoutUnit margins = 0;
+ Length startMargin = childStyle->marginStart();
+ Length endMargin = childStyle->marginEnd();
+ if (startMargin.isFixed())
+ margins += adjustFloatForSubPixelLayout(startMargin.value());
+ if (endMargin.isFixed())
+ margins += adjustFloatForSubPixelLayout(endMargin.value());
+ childMin += margins.ceilToFloat();
+ childMax += margins.ceilToFloat();
+ }
+ }
+
+ if (!child->isRenderInline() && !child->isText()) {
+ // Case (2). Inline replaced elements and floats.
+ // Go ahead and terminate the current line as far as
+ // minwidth is concerned.
+ LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
+ if (child->isBox() && child->isHorizontalWritingMode() != isHorizontalWritingMode()) {
+ RenderBox* childBox = toRenderBox(child);
+ LogicalExtentComputedValues computedValues;
+ childBox->computeLogicalHeight(childBox->borderAndPaddingLogicalHeight(), 0, computedValues);
+ childMinPreferredLogicalWidth = childMaxPreferredLogicalWidth = computedValues.m_extent;
+ } else {
+ childMinPreferredLogicalWidth = child->minPreferredLogicalWidth();
+ childMaxPreferredLogicalWidth = child->maxPreferredLogicalWidth();
+ }
+ childMin += childMinPreferredLogicalWidth.ceilToFloat();
+ childMax += childMaxPreferredLogicalWidth.ceilToFloat();
+
+ bool clearPreviousFloat;
+ if (child->isFloating()) {
+ clearPreviousFloat = (prevFloat
+ && ((prevFloat->style()->floating() == LeftFloat && (childStyle->clear() & CLEFT))
+ || (prevFloat->style()->floating() == RightFloat && (childStyle->clear() & CRIGHT))));
+ prevFloat = child;
+ } else {
+ clearPreviousFloat = false;
+ }
+
+ bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
+ if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ }
+
+ // If we're supposed to clear the previous float, then terminate maxwidth as well.
+ if (clearPreviousFloat) {
+ updatePreferredWidth(maxLogicalWidth, inlineMax);
+ inlineMax = 0;
+ }
+
+ // Add in text-indent. This is added in only once.
+ if (!addedTextIndent && !child->isFloating()) {
+ float ceiledTextIndent = textIndent.ceilToFloat();
+ childMin += ceiledTextIndent;
+ childMax += ceiledTextIndent;
+
+ if (childMin < 0)
+ textIndent = adjustFloatForSubPixelLayout(childMin);
+ else
+ addedTextIndent = true;
+ }
+
+ // Add our width to the max.
+ inlineMax += max<float>(0, childMax);
+
+ if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
+ if (child->isFloating())
+ updatePreferredWidth(minLogicalWidth, childMin);
+ else
+ inlineMin += childMin;
+ } else {
+ // Now check our line.
+ updatePreferredWidth(minLogicalWidth, childMin);
+
+ // Now start a new line.
+ inlineMin = 0;
+ }
+
+ if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ }
+
+ // We are no longer stripping whitespace at the start of
+ // a line.
+ if (!child->isFloating()) {
+ stripFrontSpaces = false;
+ trailingSpaceChild = 0;
+ }
+ } else if (child->isText()) {
+ // Case (3). Text.
+ RenderText* t = toRenderText(child);
+
+ if (t->isWordBreak()) {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ continue;
+ }
+
+ if (t->style()->hasTextCombine() && t->isCombineText())
+ toRenderCombineText(t)->combineText();
+
+ // Determine if we have a breakable character. Pass in
+ // whether or not we should ignore any spaces at the front
+ // of the string. If those are going to be stripped out,
+ // then they shouldn't be considered in the breakable char
+ // check.
+ bool hasBreakableChar, hasBreak;
+ float firstLineMinWidth, lastLineMinWidth;
+ bool hasBreakableStart, hasBreakableEnd;
+ float firstLineMaxWidth, lastLineMaxWidth;
+ t->trimmedPrefWidths(inlineMax,
+ firstLineMinWidth, hasBreakableStart, lastLineMinWidth, hasBreakableEnd,
+ hasBreakableChar, hasBreak, firstLineMaxWidth, lastLineMaxWidth,
+ childMin, childMax, stripFrontSpaces, styleToUse->direction());
+
+ // This text object will not be rendered, but it may still provide a breaking opportunity.
+ if (!hasBreak && !childMax) {
+ if (autoWrap && (hasBreakableStart || hasBreakableEnd)) {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ }
+ continue;
+ }
+
+ if (stripFrontSpaces)
+ trailingSpaceChild = child;
+ else
+ trailingSpaceChild = 0;
+
+ // Add in text-indent. This is added in only once.
+ float ti = 0;
+ if (!addedTextIndent || hasRemainingNegativeTextIndent) {
+ ti = textIndent.ceilToFloat();
+ childMin += ti;
+ firstLineMinWidth += ti;
+
+ // It the text indent negative and larger than the child minimum, we re-use the remainder
+ // in future minimum calculations, but using the negative value again on the maximum
+ // will lead to under-counting the max pref width.
+ if (!addedTextIndent) {
+ childMax += ti;
+ firstLineMaxWidth += ti;
+ addedTextIndent = true;
+ }
+
+ if (childMin < 0) {
+ textIndent = childMin;
+ hasRemainingNegativeTextIndent = true;
+ }
+ }
+
+ // If we have no breakable characters at all,
+ // then this is the easy case. We add ourselves to the current
+ // min and max and continue.
+ if (!hasBreakableChar) {
+ inlineMin += childMin;
+ } else {
+ if (hasBreakableStart) {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ } else {
+ inlineMin += firstLineMinWidth;
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ childMin -= ti;
+ }
+
+ inlineMin = childMin;
+
+ if (hasBreakableEnd) {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = 0;
+ shouldBreakLineAfterText = false;
+ } else {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ inlineMin = lastLineMinWidth;
+ shouldBreakLineAfterText = true;
+ }
+ }
+
+ if (hasBreak) {
+ inlineMax += firstLineMaxWidth;
+ updatePreferredWidth(maxLogicalWidth, inlineMax);
+ updatePreferredWidth(maxLogicalWidth, childMax);
+ inlineMax = lastLineMaxWidth;
+ addedTextIndent = true;
+ } else {
+ inlineMax += max<float>(0, childMax);
+ }
+ }
+
+ // Ignore spaces after a list marker.
+ if (child->isListMarker())
+ stripFrontSpaces = true;
+ } else {
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ updatePreferredWidth(maxLogicalWidth, inlineMax);
+ inlineMin = inlineMax = 0;
+ stripFrontSpaces = true;
+ trailingSpaceChild = 0;
+ addedTextIndent = true;
+ }
+
+ if (!child->isText() && child->isRenderInline())
+ isPrevChildInlineFlow = true;
+ else
+ isPrevChildInlineFlow = false;
+
+ oldAutoWrap = autoWrap;
+ }
+
+ if (styleToUse->collapseWhiteSpace())
+ stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
+
+ updatePreferredWidth(minLogicalWidth, inlineMin);
+ updatePreferredWidth(maxLogicalWidth, inlineMax);
+}
+
+void RenderBlockFlow::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, LayoutUnit afterEdge)
+{
RenderFlowThread* flowThread = flowThreadContainingBlock();
bool clearLinesForPagination = firstLineBox() && flowThread && !flowThread->hasRegions();
@@ -1752,25 +1687,17 @@ void RenderBlockFlow::layoutInlineChildren(bool relayoutChildren, LayoutUnit& re
// the replaced elements later. In partial layout mode, line boxes are not
// deleted and only dirtied. In that case, we can layout the replaced
// elements at the same time.
- bool hasInlineChild = false;
Vector<RenderBox*> replacedChildren;
for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
RenderObject* o = walker.current();
- LayoutRectRecorder recorder(*o, !o->isText());
-
- if (!hasInlineChild && o->isInline())
- hasInlineChild = true;
+ if (!layoutState.hasInlineChild() && o->isInline())
+ layoutState.setHasInlineChild(true);
if (o->isReplaced() || o->isFloating() || o->isOutOfFlowPositioned()) {
RenderBox* box = toRenderBox(o);
- if (relayoutChildren || box->hasRelativeDimensions())
- o->setChildNeedsLayout(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(MarkOnlyThis);
+ updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, box);
if (o->isOutOfFlowPositioned())
o->containingBlock()->insertPositionedObject(box);
@@ -1796,7 +1723,7 @@ void RenderBlockFlow::layoutInlineChildren(bool relayoutChildren, LayoutUnit& re
for (size_t i = 0; i < replacedChildren.size(); i++)
replacedChildren[i]->layoutIfNeeded();
- layoutRunsAndFloats(layoutState, hasInlineChild);
+ layoutRunsAndFloats(layoutState);
}
// Expand the last line to accommodate Ruby and emphasis marks.
@@ -1810,7 +1737,7 @@ void RenderBlockFlow::layoutInlineChildren(bool relayoutChildren, LayoutUnit& re
}
// Now add in the bottom border/padding.
- setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
+ setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + afterEdge);
if (!firstLineBox() && hasLineIfEmpty())
setLogicalHeight(logicalHeight() + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
@@ -1865,10 +1792,6 @@ RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutSt
size_t floatIndex = 0;
for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
if (paginated) {
- if (lineWidthForPaginatedLineChanged(curr, 0, layoutState.flowThread())) {
- curr->markDirty();
- break;
- }
paginationDelta -= curr->paginationStrut();
adjustLinePositionForPagination(curr, paginationDelta, layoutState.flowThread());
if (paginationDelta) {
@@ -1879,10 +1802,8 @@ RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutSt
}
layoutState.updateRepaintRangeFromBox(curr, paginationDelta);
- curr->adjustBlockDirectionPosition(paginationDelta);
+ curr->adjustBlockDirectionPosition(paginationDelta.toFloat());
}
- if (layoutState.flowThread())
- updateRegionForLine(curr);
}
// If a new float has been inserted before this line or before its last known float, just do a full layout.
@@ -1900,6 +1821,13 @@ RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutSt
}
if (layoutState.isFullLayout()) {
+ // If we encountered a new float and have inline children, mark ourself to force us to issue paint invalidations.
+ if (layoutState.hasInlineChild() && !selfNeedsLayout()) {
+ setNeedsLayoutAndFullPaintInvalidation(MarkOnlyThis);
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ setShouldDoFullPaintInvalidationAfterLayout(true);
+ }
+
// FIXME: This should just call deleteLineBoxTree, but that causes
// crashes for fast/repaint tests.
curr = firstRootBox();
@@ -2028,8 +1956,6 @@ bool RenderBlockFlow::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutS
adjustLinePositionForPagination(lineBox, lineDelta, layoutState.flowThread());
lineBox->setPaginationStrut(oldPaginationStrut);
}
- if (lineWidthForPaginatedLineChanged(lineBox, lineDelta, layoutState.flowThread()))
- return false;
}
}
@@ -2048,7 +1974,7 @@ bool RenderBlockFlow::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutS
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (logicalBottomForFloat(floatingObject) >= logicalTop && logicalBottomForFloat(floatingObject) < logicalBottom)
return false;
}
@@ -2070,7 +1996,7 @@ bool RenderBlockFlow::matchedEndLine(LineLayoutState& layoutState, const InlineB
RootInlineBox* originalEndLine = layoutState.endLine();
RootInlineBox* line = originalEndLine;
for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
- if (line->lineBreakObj() == resolver.position().object() && line->lineBreakPos() == resolver.position().m_pos) {
+ if (line->lineBreakObj() == resolver.position().object() && line->lineBreakPos() == resolver.position().offset()) {
// We have a match.
if (line->lineBreakBidiStatus() != resolver.status())
return false; // ...but the bidi state doesn't match.
@@ -2105,139 +2031,6 @@ bool RenderBlockFlow::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
return !it.atEnd();
}
-void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo,
- FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
-{
- while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) {
- RenderObject* object = resolver.position().object();
- if (object->isOutOfFlowPositioned()) {
- setStaticPositions(m_block, toRenderBox(object));
- if (object->style()->isOriginalDisplayInlineType()) {
- resolver.runs().addRun(createRun(0, 1, object, resolver));
- lineInfo.incrementRunsFromLeadingWhitespace();
- }
- } else if (object->isFloating())
- m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width);
- else if (object->isText() && object->style()->hasTextCombine() && object->isCombineText() && !toRenderCombineText(object)->isCombined()) {
- toRenderCombineText(object)->combineText();
- if (toRenderCombineText(object)->isCombined())
- continue;
- }
- resolver.position().increment(&resolver);
- }
- resolver.commitExplicitEmbedding();
-}
-
-void LineBreaker::reset()
-{
- m_positionedObjects.clear();
- m_hyphenated = false;
- m_clear = CNONE;
-}
-
-InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
-{
- ShapeInsideInfo* shapeInsideInfo = m_block->layoutShapeInsideInfo();
-
- if (!shapeInsideInfo || !shapeInsideInfo->lineOverlapsShapeBounds())
- return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
-
- InlineIterator end = resolver.position();
- InlineIterator oldEnd = end;
-
- if (!shapeInsideInfo->hasSegments()) {
- end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
- resolver.setPositionIgnoringNestedIsolates(oldEnd);
- return oldEnd;
- }
-
- const SegmentList& segments = shapeInsideInfo->segments();
- SegmentRangeList& segmentRanges = shapeInsideInfo->segmentRanges();
-
- for (unsigned i = 0; i < segments.size() && !end.atEnd(); i++) {
- const InlineIterator segmentStart = resolver.position();
- end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
-
- ASSERT(segmentRanges.size() == i);
- if (resolver.position().atEnd()) {
- segmentRanges.append(LineSegmentRange(segmentStart, end));
- break;
- }
- if (resolver.position() == end) {
- // Nothing fit this segment
- end = segmentStart;
- segmentRanges.append(LineSegmentRange(segmentStart, segmentStart));
- resolver.setPositionIgnoringNestedIsolates(segmentStart);
- } else {
- // Note that resolver.position is already skipping some of the white space at the beginning of the line,
- // so that's why segmentStart might be different than resolver.position().
- LineSegmentRange range(resolver.position(), end);
- segmentRanges.append(range);
- resolver.setPosition(end, numberOfIsolateAncestors(end));
-
- if (lineInfo.previousLineBrokeCleanly()) {
- // If we hit a new line break, just stop adding anything to this line.
- break;
- }
- }
- }
- resolver.setPositionIgnoringNestedIsolates(oldEnd);
- return end;
-}
-
-InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
-{
- reset();
-
- ASSERT(resolver.position().root() == m_block);
-
- bool appliedStartWidth = resolver.position().m_pos > 0;
-
- LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style()));
-
- skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width);
-
- if (resolver.position().atEnd())
- return resolver.position();
-
- BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloatFromPreviousLine, appliedStartWidth, m_block);
-
- while (context.currentObject()) {
- context.initializeForCurrentObject();
- if (context.currentObject()->isBR()) {
- context.handleBR(m_clear);
- } else if (context.currentObject()->isOutOfFlowPositioned()) {
- context.handleOutOfFlowPositioned(m_positionedObjects);
- } else if (context.currentObject()->isFloating()) {
- context.handleFloat();
- } else if (context.currentObject()->isRenderInline()) {
- context.handleEmptyInline();
- } else if (context.currentObject()->isReplaced()) {
- context.handleReplaced();
- } else if (context.currentObject()->isText()) {
- if (context.handleText(wordMeasurements, m_hyphenated)) {
- // We've hit a hard text line break. Our line break iterator is updated, so go ahead and early return.
- return context.lineBreak();
- }
- } else {
- ASSERT_NOT_REACHED();
- }
-
- if (context.atEnd())
- return context.handleEndOfLine();
-
- context.commitAndUpdateLineBreakIfNeeded();
-
- if (context.atEnd())
- return context.handleEndOfLine();
-
- context.increment();
- }
-
- context.clearLineBreakIfFitsOnLine();
-
- return context.handleEndOfLine();
-}
void RenderBlockFlow::addOverflowFromInlineChildren()
{
@@ -2262,7 +2055,7 @@ void RenderBlockFlow::deleteEllipsisLineBoxes()
curr->clearTruncation();
// Shift the line back where it belongs if we cannot accomodate an ellipsis.
- float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(curr->lineTop(), firstLine);
+ float logicalLeft = logicalLeftOffsetForLine(curr->lineTop(), firstLine).toFloat();
float availableLogicalWidth = logicalRightOffsetForLine(curr->lineTop(), false) - logicalLeft;
float totalLogicalWidth = curr->logicalWidth();
updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
@@ -2283,8 +2076,10 @@ void RenderBlockFlow::checkLinesForTextOverflow()
const Font& font = style()->font();
DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
const Font& firstLineFont = firstLineStyle()->font();
- int firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle()));
- int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
+ // FIXME: We should probably not hard-code the direction here. https://crbug.com/333004
+ TextDirection ellipsisDirection = LTR;
+ float firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle(), ellipsisDirection));
+ float ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style(), ellipsisDirection));
// 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
@@ -2294,12 +2089,10 @@ void RenderBlockFlow::checkLinesForTextOverflow()
ETextAlign textAlign = style()->textAlign();
bool firstLine = true;
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
- // FIXME: Use pixelSnappedLogicalRightOffsetForLine instead of snapping it ourselves once the column workaround in said method has been fixed.
- // https://bugs.webkit.org/show_bug.cgi?id=105461
float currLogicalLeft = curr->logicalLeft();
- int blockRightEdge = snapSizeToPixel(logicalRightOffsetForLine(curr->lineTop(), firstLine), currLogicalLeft);
- int blockLeftEdge = pixelSnappedLogicalLeftOffsetForLine(curr->lineTop(), firstLine);
- int lineBoxEdge = ltr ? snapSizeToPixel(currLogicalLeft + curr->logicalWidth(), currLogicalLeft) : snapSizeToPixel(currLogicalLeft, 0);
+ LayoutUnit blockRightEdge = logicalRightOffsetForLine(curr->lineTop(), firstLine);
+ LayoutUnit blockLeftEdge = logicalLeftOffsetForLine(curr->lineTop(), firstLine);
+ LayoutUnit lineBoxEdge = ltr ? currLogicalLeft + curr->logicalWidth() : currLogicalLeft;
if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
// This line spills out of our box in the appropriate direction. Now we need to see if the line
// can be truncated. In order for truncation to be possible, the line must have sufficient space to
@@ -2309,15 +2102,15 @@ void RenderBlockFlow::checkLinesForTextOverflow()
LayoutUnit width = firstLine ? firstLineEllipsisWidth : ellipsisWidth;
LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge;
if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)) {
- float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
+ float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge.toFloat(), blockRightEdge.toFloat(), width.toFloat());
float logicalLeft = 0; // We are only intersted in the delta from the base position.
- float truncatedWidth = pixelSnappedLogicalRightOffsetForLine(curr->lineTop(), firstLine);
- updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, totalLogicalWidth, truncatedWidth, 0);
+ float availableLogicalWidth = (blockRightEdge - blockLeftEdge).toFloat();
+ updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
if (ltr)
curr->adjustLogicalPosition(logicalLeft, 0);
else
- curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0);
+ curr->adjustLogicalPosition(logicalLeft - (availableLogicalWidth - totalLogicalWidth), 0);
}
}
firstLine = false;
@@ -2351,7 +2144,7 @@ bool RenderBlockFlow::positionNewFloatOnLine(FloatingObject* newFloat, FloatingO
FloatingObjectSetIterator begin = floatingObjectSet.begin();
while (it != begin) {
--it;
- FloatingObject* floatingObject = *it;
+ FloatingObject* floatingObject = it->get();
if (floatingObject == lastFloatFromPreviousLine)
break;
if (logicalTopForFloat(floatingObject) == logicalHeight() + lineInfo.floatPaginationStrut()) {
@@ -2386,7 +2179,7 @@ LayoutUnit RenderBlockFlow::startAlignedOffsetForLine(LayoutUnit position, bool
// updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
float totalLogicalWidth = 0;
- float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
+ float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false).toFloat();
float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
@@ -2395,27 +2188,4 @@ LayoutUnit RenderBlockFlow::startAlignedOffsetForLine(LayoutUnit position, bool
return logicalLeft;
}
-void RenderBlockFlow::layoutLineGridBox()
-{
- if (style()->lineGrid() == RenderStyle::initialLineGrid()) {
- setLineGridBox(0);
- return;
- }
-
- setLineGridBox(0);
-
- RootInlineBox* lineGridBox = new RootInlineBox(this);
- lineGridBox->setHasTextChildren(); // Needed to make the line ascent/descent actually be honored in quirks mode.
- lineGridBox->setConstructed();
- GlyphOverflowAndFallbackFontsMap textBoxDataMap;
- VerticalPositionCache verticalPositionCache;
- lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache);
-
- setLineGridBox(lineGridBox);
-
- // FIXME: If any of the characteristics of the box change compared to the old one, then we need to do a deep dirtying
- // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping
- // to this grid.
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderBox.cpp
index 9c960358ed5..93d89283c7b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBox.cpp
@@ -26,40 +26,40 @@
#include "config.h"
#include "core/rendering/RenderBox.h"
-#include <math.h>
-#include <algorithm>
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/editing/htmlediting.h"
+#include "core/frame/FrameHost.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/PinchViewport.h"
+#include "core/frame/Settings.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLFrameOwnerElement.h"
-#include "core/html/HTMLHtmlElement.h"
-#include "core/html/HTMLTextAreaElement.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
#include "core/page/AutoscrollController.h"
#include "core/page/EventHandler.h"
#include "core/page/Page.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
-#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderDeprecatedFlexibleBox.h"
#include "core/rendering/RenderFlexibleBox.h"
-#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderGrid.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderListBox.h"
#include "core/rendering/RenderListMarker.h"
-#include "core/rendering/RenderRegion.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+#include "platform/LengthFunctions.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
+#include <algorithm>
+#include <math.h>
using namespace std;
@@ -69,10 +69,9 @@ using namespace HTMLNames;
// Used by flexible boxes when flexing this element and by table cells.
typedef WTF::HashMap<const RenderBox*, LayoutUnit> OverrideSizeMap;
-static OverrideSizeMap* gOverrideHeightMap = 0;
-static OverrideSizeMap* gOverrideWidthMap = 0;
// Used by grid elements to properly size their grid items.
+// FIXME: Move these into RenderBoxRareData.
static OverrideSizeMap* gOverrideContainingBlockLogicalHeightMap = 0;
static OverrideSizeMap* gOverrideContainingBlockLogicalWidthMap = 0;
@@ -95,64 +94,13 @@ static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
RenderBox::RenderBox(ContainerNode* node)
: RenderBoxModelObject(node)
+ , m_intrinsicContentLogicalHeight(-1)
, m_minPreferredLogicalWidth(-1)
, m_maxPreferredLogicalWidth(-1)
- , m_intrinsicContentLogicalHeight(-1)
- , m_inlineBoxWrapper(0)
{
setIsBox();
}
-RenderBox::~RenderBox()
-{
-}
-
-LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
-{
- if (!region)
- return borderBoxRect();
-
- // Compute the logical width and placement in this region.
- RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(region, cacheFlag);
- if (!boxInfo)
- return borderBoxRect();
-
- // We have cached insets.
- LayoutUnit logicalWidth = boxInfo->logicalWidth();
- LayoutUnit logicalLeft = boxInfo->logicalLeft();
-
- // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
- // FIXME: Doesn't work right with perpendicular writing modes.
- const RenderBlock* currentBox = containingBlock();
- RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region);
- while (currentBoxInfo && currentBoxInfo->isShifted()) {
- if (currentBox->style()->direction() == LTR)
- logicalLeft += currentBoxInfo->logicalLeft();
- else
- logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
- currentBox = currentBox->containingBlock();
- region = currentBox->clampToStartAndEndRegions(region);
- currentBoxInfo = currentBox->renderBoxRegionInfo(region);
- }
-
- if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
- delete boxInfo;
-
- if (isHorizontalWritingMode())
- return LayoutRect(logicalLeft, 0, logicalWidth, height());
- return LayoutRect(0, logicalLeft, width(), logicalWidth);
-}
-
-void RenderBox::clearRenderBoxRegionInfo()
-{
- if (isRenderFlowThread())
- return;
-
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread)
- flowThread->removeRenderBoxRegionInfo(this);
-}
-
void RenderBox::willBeDestroyed()
{
clearOverrideSize();
@@ -160,7 +108,7 @@ void RenderBox::willBeDestroyed()
RenderBlock::removePercentHeightDescendantIfNeeded(this);
- ShapeOutsideInfo::removeInfo(this);
+ ShapeOutsideInfo::removeInfo(*this);
RenderBoxModelObject::willBeDestroyed();
}
@@ -192,33 +140,36 @@ void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
RenderBlock::removePositionedObject(this);
}
-void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
RenderStyle* oldStyle = style();
if (oldStyle) {
// The background of the root element or the body element could propagate up to
// the canvas. Just dirty the entire canvas when our style changes substantially.
- if (diff >= StyleDifferenceRepaint && node() &&
- (isHTMLHtmlElement(node()) || node()->hasTagName(bodyTag))) {
- view()->repaint();
+ if ((diff.needsRepaint() || diff.needsLayout()) && node()
+ && (isHTMLHtmlElement(*node()) || isHTMLBodyElement(*node()))) {
+ view()->paintInvalidationForWholeRenderer();
- if (oldStyle->hasEntirelyFixedBackground() != newStyle->hasEntirelyFixedBackground())
- view()->compositor()->rootFixedBackgroundsChanged();
+ if (oldStyle->hasEntirelyFixedBackground() != newStyle.hasEntirelyFixedBackground())
+ view()->compositor()->setNeedsUpdateFixedBackground();
}
// When a layout hint happens and an object's position style changes, we have to do a layout
// to dirty the render tree using the old position value now.
- if (diff == StyleDifferenceLayout && parent() && oldStyle->position() != newStyle->position()) {
+ if (diff.needsFullLayout() && parent() && oldStyle->position() != newStyle.position()) {
markContainingBlocksForLayout();
if (oldStyle->position() == StaticPosition)
- repaint();
- else if (newStyle->hasOutOfFlowPosition())
+ paintInvalidationForWholeRenderer();
+ else if (newStyle.hasOutOfFlowPosition())
parent()->setChildNeedsLayout();
- if (isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
+ if (isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
removeFloatingOrPositionedChildFromBlockLists();
}
- } else if (newStyle && isBody())
- view()->repaint();
+ // FIXME: This branch runs when !oldStyle, which means that layout was never called
+ // so what's the point in invalidating the whole view that we never painted?
+ } else if (isBody()) {
+ view()->paintInvalidationForWholeRenderer();
+ }
RenderBoxModelObject::styleWillChange(diff, newStyle);
}
@@ -244,7 +195,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
parent()->setChildNeedsLayout();
}
- if (RenderBlock::hasPercentHeightContainerMap() && firstChild()
+ if (RenderBlock::hasPercentHeightContainerMap() && slowFirstChild()
&& oldHorizontalWritingMode != isHorizontalWritingMode())
RenderBlock::clearPercentHeightDescendantsFrom(this);
@@ -262,7 +213,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
}
// Our opaqueness might have changed without triggering layout.
- if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrColorChange || diff == StyleDifferenceRepaintLayer) {
+ if (diff.needsRepaint()) {
RenderObject* parentToInvalidate = parent();
for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
parentToInvalidate->invalidateBackgroundObscurationStatus();
@@ -270,7 +221,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
}
}
- if (isRoot() || isBody())
+ if (isDocumentElement() || isBody())
document().view()->recalculateScrollbarOverlayStyle();
updateShapeOutsideInfoAfterStyleChange(*style(), oldStyle);
@@ -293,9 +244,9 @@ void RenderBox::updateShapeOutsideInfoAfterStyleChange(const RenderStyle& style,
return;
if (!shapeOutside)
- ShapeOutsideInfo::removeInfo(this);
+ ShapeOutsideInfo::removeInfo(*this);
else
- ShapeOutsideInfo::ensureInfo(this)->dirtyShapeSize();
+ ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty();
if (shapeOutside || shapeOutside != oldShapeOutside)
markShapeOutsideDependentsForLayout();
@@ -324,7 +275,7 @@ void RenderBox::updateFromStyle()
RenderBoxModelObject::updateFromStyle();
RenderStyle* styleToUse = style();
- bool isRootObject = isRoot();
+ bool isRootObject = isDocumentElement();
bool isViewObject = isRenderView();
// The root and the RenderView always paint their backgrounds/borders.
@@ -334,26 +285,26 @@ void RenderBox::updateFromStyle()
setFloating(!isOutOfFlowPositioned() && styleToUse->isFloating());
bool boxHasOverflowClip = false;
- // We also handle <body> and <html>, whose overflow applies to the viewport.
- // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
- if (styleToUse->overflowX() != OVISIBLE && !isRootObject && isRenderBlock()) {
- // Overflow on the body can propagate to the viewport under the following conditions.
- // (1) The root element is <html>.
- // (2) We are the primary <body> (can be checked by looking at document.body).
- // (3) The root element has visible overflow.
- if (isBody() && isHTMLHtmlElement(document().documentElement())
- && document().body() == node()
- && document().documentElement()->renderer()->style()->overflowX() == OVISIBLE) {
- boxHasOverflowClip = false;
- } else {
+ if (!styleToUse->isOverflowVisible() && isRenderBlock() && !isViewObject) {
+ // If overflow has been propagated to the viewport, it has no effect here.
+ if (node() != document().viewportDefiningElement()) {
boxHasOverflowClip = true;
if (!hasOverflowClip()) {
// If we are getting an overflow clip, preemptively erase any overflowing content.
// FIXME: This should probably consult RenderOverflow.
- repaint();
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ paintInvalidationForWholeRenderer();
}
}
}
+
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && (boxHasOverflowClip != hasOverflowClip())) {
+ // FIXME: This shouldn't be required if we tracked the visual overflow
+ // generated by positioned children or self painting layers. crbug.com/345403
+ for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling())
+ child->setShouldDoFullPaintInvalidationIfSelfPaintingLayer(true);
+ }
+
setHasOverflowClip(boxHasOverflowClip);
setHasTransform(styleToUse->hasTransformRelatedProperty());
@@ -364,21 +315,18 @@ void RenderBox::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
-
- RenderObject* child = firstChild();
+ RenderObject* child = slowFirstChild();
if (!child) {
clearNeedsLayout();
return;
}
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+ LayoutState state(*this, locationOffset());
while (child) {
child->layoutIfNeeded();
ASSERT(!child->needsLayout());
child = child->nextSibling();
}
- statePusher.pop();
invalidateBackgroundObscurationStatus();
clearNeedsLayout();
}
@@ -415,88 +363,65 @@ int RenderBox::pixelSnappedOffsetHeight() const
return snapSizeToPixel(offsetHeight(), y() + clientTop());
}
-bool RenderBox::canDetermineWidthWithoutLayout() const
-{
- // FIXME: This optimization is incorrect as written.
- // We need to be able to opt-in to this behavior only when
- // it's guarentted correct.
- // Until then disabling this optimization to be safe.
- return false;
-
- // FIXME: There are likely many subclasses of RenderBlockFlow which
- // cannot determine their layout just from style!
- // Perhaps we should create a "PlainRenderBlockFlow"
- // and move this optimization there?
- if (!isRenderBlockFlow()
- // Flexbox items can be expanded beyond their width.
- || isFlexItemIncludingDeprecated()
- // Table Layout controls cell size and can expand beyond width.
- || isTableCell())
- return false;
-
- RenderStyle* style = this->style();
- return style->width().isFixed()
- && style->minWidth().isFixed()
- && (style->maxWidth().isUndefined() || style->maxWidth().isFixed())
- && style->paddingLeft().isFixed()
- && style->paddingRight().isFixed()
- && style->boxSizing() == CONTENT_BOX;
-}
-
-LayoutUnit RenderBox::fixedOffsetWidth() const
-{
- ASSERT(canDetermineWidthWithoutLayout());
-
- RenderStyle* style = this->style();
-
- LayoutUnit width = std::max(LayoutUnit(style->minWidth().value()), LayoutUnit(style->width().value()));
- if (style->maxWidth().isFixed())
- width = std::min(LayoutUnit(style->maxWidth().value()), width);
-
- LayoutUnit borderLeft = style->borderLeft().nonZero() ? style->borderLeft().width() : 0;
- LayoutUnit borderRight = style->borderRight().nonZero() ? style->borderRight().width() : 0;
-
- return width + borderLeft + borderRight + style->paddingLeft().value() + style->paddingRight().value();
-}
-
-int RenderBox::scrollWidth() const
+LayoutUnit RenderBox::scrollWidth() const
{
if (hasOverflowClip())
return layer()->scrollableArea()->scrollWidth();
// For objects with visible overflow, this matches IE.
// FIXME: Need to work right with writing modes.
if (style()->isLeftToRightDirection())
- return snapSizeToPixel(max(clientWidth(), layoutOverflowRect().maxX() - borderLeft()), x() + clientLeft());
+ return max(clientWidth(), layoutOverflowRect().maxX() - borderLeft());
return clientWidth() - min<LayoutUnit>(0, layoutOverflowRect().x() - borderLeft());
}
-int RenderBox::scrollHeight() const
+LayoutUnit RenderBox::scrollHeight() const
{
if (hasOverflowClip())
return layer()->scrollableArea()->scrollHeight();
// For objects with visible overflow, this matches IE.
// FIXME: Need to work right with writing modes.
- return snapSizeToPixel(max(clientHeight(), layoutOverflowRect().maxY() - borderTop()), y() + clientTop());
+ return max(clientHeight(), layoutOverflowRect().maxY() - borderTop());
}
-int RenderBox::scrollLeft() const
+LayoutUnit RenderBox::scrollLeft() const
{
return hasOverflowClip() ? layer()->scrollableArea()->scrollXOffset() : 0;
}
-int RenderBox::scrollTop() const
+LayoutUnit RenderBox::scrollTop() const
{
return hasOverflowClip() ? layer()->scrollableArea()->scrollYOffset() : 0;
}
-void RenderBox::setScrollLeft(int newLeft)
+int RenderBox::pixelSnappedScrollWidth() const
+{
+ return snapSizeToPixel(scrollWidth(), x() + clientLeft());
+}
+
+int RenderBox::pixelSnappedScrollHeight() const
+{
+ if (hasOverflowClip())
+ return layer()->scrollableArea()->scrollHeight();
+ // For objects with visible overflow, this matches IE.
+ // FIXME: Need to work right with writing modes.
+ return snapSizeToPixel(scrollHeight(), y() + clientTop());
+}
+
+void RenderBox::setScrollLeft(LayoutUnit newLeft)
{
+ // This doesn't hit in any tests, but since the equivalent code in setScrollTop
+ // does, presumably this code does as well.
+ DisableCompositingQueryAsserts disabler;
+
if (hasOverflowClip())
layer()->scrollableArea()->scrollToXOffset(newLeft, ScrollOffsetClamped);
}
-void RenderBox::setScrollTop(int newTop)
+void RenderBox::setScrollTop(LayoutUnit newTop)
{
+ // Hits in compositing/overflow/do-not-assert-on-invisible-composited-layers.html
+ DisableCompositingQueryAsserts disabler;
+
if (hasOverflowClip())
layer()->scrollableArea()->scrollToYOffset(newTop, ScrollOffsetClamped);
}
@@ -504,6 +429,10 @@ void RenderBox::setScrollTop(int newTop)
void RenderBox::scrollToOffset(const IntSize& offset)
{
ASSERT(hasOverflowClip());
+
+ // This doesn't hit in any tests, but since the equivalent code in setScrollTop
+ // does, presumably this code does as well.
+ DisableCompositingQueryAsserts disabler;
layer()->scrollableArea()->scrollToOffset(offset, ScrollOffsetClamped);
}
@@ -527,6 +456,9 @@ static inline bool frameElementAndViewPermitScroll(HTMLFrameElementBase* frameEl
void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
{
+ // Presumably the same issue as in setScrollTop. See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
RenderBox* parentBox = 0;
LayoutRect newRect = rect;
@@ -547,7 +479,7 @@ void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignmen
if (ownerElement && ownerElement->renderer()) {
HTMLFrameElementBase* frameElementBase = 0;
- if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))
+ if (isHTMLFrameElement(*ownerElement) || isHTMLIFrameElement(*ownerElement))
frameElementBase = toHTMLFrameElementBase(ownerElement);
if (frameElementAndViewPermitScroll(frameElementBase, frameView)) {
@@ -572,9 +504,15 @@ void RenderBox::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignmen
}
}
} else {
- LayoutRect viewRect = frameView->visibleContentRect();
- LayoutRect r = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY);
- frameView->setScrollPosition(roundedIntPoint(r.location()));
+ if (frame()->settings()->pinchVirtualViewportEnabled()) {
+ PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
+ LayoutRect r = ScrollAlignment::getRectToExpose(LayoutRect(pinchViewport.visibleRectInDocument()), rect, alignX, alignY);
+ pinchViewport.scrollIntoView(r);
+ } else {
+ LayoutRect viewRect = frameView->visibleContentRect();
+ LayoutRect r = ScrollAlignment::getRectToExpose(viewRect, rect, alignX, alignY);
+ frameView->setScrollPosition(roundedIntPoint(r.location()));
+ }
}
}
}
@@ -593,22 +531,22 @@ void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumul
void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
- quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
+ quads.append(localToAbsoluteQuad(FloatRect(0, 0, width().toFloat(), height().toFloat()), 0 /* mode */, wasFixed));
}
-void RenderBox::updateLayerTransform()
+void RenderBox::updateLayerTransformAfterLayout()
{
// Transform-origin depends on box size, so we need to update the layer transform after layout.
if (hasLayer())
- layer()->updateTransform();
+ layer()->updateTransformationMatrix();
}
-LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region) const
+LayoutUnit RenderBox::constrainLogicalWidthByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb) const
{
RenderStyle* styleToUse = style();
if (!styleToUse->logicalMaxWidth().isUndefined())
- logicalWidth = min(logicalWidth, computeLogicalWidthInRegionUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb, region));
- return max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb, region));
+ logicalWidth = min(logicalWidth, computeLogicalWidthUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb));
+ return max(logicalWidth, computeLogicalWidthUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb));
}
LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
@@ -648,28 +586,6 @@ FloatQuad RenderBox::absoluteContentQuad() const
return localToAbsoluteQuad(FloatRect(rect));
}
-LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const
-{
- LayoutRect box = borderBoundingBox();
- adjustRectForOutlineAndShadow(box);
-
- if (repaintContainer != this) {
- FloatQuad containerRelativeQuad;
- if (geometryMap)
- containerRelativeQuad = geometryMap->mapToContainer(box, repaintContainer);
- else
- containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
-
- box = containerRelativeQuad.enclosingBoundingBox();
- }
-
- // FIXME: layoutDelta needs to be applied in parts before/after transforms and
- // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
- box.move(view()->layoutDelta());
-
- return box;
-}
-
void RenderBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*)
{
if (!size().isEmpty())
@@ -696,38 +612,13 @@ void RenderBox::computeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutP
rects.append(LayoutRect(layerOffset, size()));
}
-LayoutRect RenderBox::reflectionBox() const
-{
- LayoutRect result;
- if (!style()->boxReflect())
- return result;
- LayoutRect box = borderBoxRect();
- result = box;
- switch (style()->boxReflect()->direction()) {
- case ReflectionBelow:
- result.move(0, box.height() + reflectionOffset());
- break;
- case ReflectionAbove:
- result.move(0, -box.height() - reflectionOffset());
- break;
- case ReflectionLeft:
- result.move(-box.width() - reflectionOffset(), 0);
- break;
- case ReflectionRight:
- result.move(box.width() + reflectionOffset(), 0);
- break;
- }
- return result;
-}
-
int RenderBox::reflectionOffset() const
{
if (!style()->boxReflect())
return 0;
- RenderView* renderView = view();
if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
- return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width(), renderView);
- return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height(), renderView);
+ return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width());
+ return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height());
}
LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
@@ -788,20 +679,23 @@ int RenderBox::instrinsicScrollbarLogicalWidth() const
return 0;
}
-bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float delta)
{
+ // Presumably the same issue as in setScrollTop. See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
// Logical scroll is a higher level concept, all directions by here must be physical
ASSERT(!isLogical(direction));
if (!layer() || !layer()->scrollableArea())
return false;
- return layer()->scrollableArea()->scroll(direction, granularity, multiplier);
+ return layer()->scrollableArea()->scroll(direction, granularity, delta);
}
bool RenderBox::canBeScrolledAndHasScrollableArea() const
{
- return canBeProgramaticallyScrolled() && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth());
+ return canBeProgramaticallyScrolled() && (pixelSnappedScrollHeight() != pixelSnappedClientHeight() || pixelSnappedScrollWidth() != pixelSnappedClientWidth());
}
bool RenderBox::canBeProgramaticallyScrolled() const
@@ -827,7 +721,7 @@ bool RenderBox::usesCompositedScrolling() const
void RenderBox::autoscroll(const IntPoint& position)
{
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (!frame)
return;
@@ -918,7 +812,7 @@ static inline IntSize adjustedScrollDelta(const IntSize& delta)
void RenderBox::panScroll(const IntPoint& sourcePoint)
{
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (!frame)
return;
@@ -960,7 +854,7 @@ void RenderBox::scrollByRecursively(const IntSize& delta, ScrollOffsetClamping c
if (RenderBox* scrollableBox = enclosingScrollableBox())
scrollableBox->scrollByRecursively(remainingScrollOffset, clamp);
- Frame* frame = this->frame();
+ LocalFrame* frame = this->frame();
if (frame && frame->page())
frame->page()->autoscrollController().updateAutoscrollRenderer();
}
@@ -995,17 +889,21 @@ LayoutSize RenderBox::cachedSizeForOverflowClip() const
void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
{
+ flipForWritingMode(paintRect);
paintRect.move(-scrolledContentOffset()); // For overflow:auto/scroll/hidden.
// Do not clip scroll layer contents to reduce the number of repaints while scrolling.
- if (usesCompositedScrolling())
+ if (usesCompositedScrolling()) {
+ flipForWritingMode(paintRect);
return;
+ }
// height() is inaccurate if we're in the middle of a layout of this RenderBox, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
LayoutRect clipRect(LayoutPoint(), cachedSizeForOverflowClip());
paintRect = intersection(paintRect, clipRect);
+ flipForWritingMode(paintRect);
}
void RenderBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
@@ -1018,7 +916,7 @@ LayoutUnit RenderBox::minPreferredLogicalWidth() const
{
if (preferredLogicalWidthsDirty()) {
#ifndef NDEBUG
- SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
+ SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox&>(*this));
#endif
const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
}
@@ -1030,7 +928,7 @@ LayoutUnit RenderBox::maxPreferredLogicalWidth() const
{
if (preferredLogicalWidthsDirty()) {
#ifndef NDEBUG
- SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
+ SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox&>(*this));
#endif
const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
}
@@ -1040,38 +938,36 @@ LayoutUnit RenderBox::maxPreferredLogicalWidth() const
bool RenderBox::hasOverrideHeight() const
{
- return gOverrideHeightMap && gOverrideHeightMap->contains(this);
+ return m_rareData && m_rareData->m_overrideLogicalContentHeight != -1;
}
bool RenderBox::hasOverrideWidth() const
{
- return gOverrideWidthMap && gOverrideWidthMap->contains(this);
+ return m_rareData && m_rareData->m_overrideLogicalContentWidth != -1;
}
void RenderBox::setOverrideLogicalContentHeight(LayoutUnit height)
{
- if (!gOverrideHeightMap)
- gOverrideHeightMap = new OverrideSizeMap();
- gOverrideHeightMap->set(this, height);
+ ASSERT(height >= 0);
+ ensureRareData().m_overrideLogicalContentHeight = height;
}
void RenderBox::setOverrideLogicalContentWidth(LayoutUnit width)
{
- if (!gOverrideWidthMap)
- gOverrideWidthMap = new OverrideSizeMap();
- gOverrideWidthMap->set(this, width);
+ ASSERT(width >= 0);
+ ensureRareData().m_overrideLogicalContentWidth = width;
}
void RenderBox::clearOverrideLogicalContentHeight()
{
- if (gOverrideHeightMap)
- gOverrideHeightMap->remove(this);
+ if (m_rareData)
+ m_rareData->m_overrideLogicalContentHeight = -1;
}
void RenderBox::clearOverrideLogicalContentWidth()
{
- if (gOverrideWidthMap)
- gOverrideWidthMap->remove(this);
+ if (m_rareData)
+ m_rareData->m_overrideLogicalContentWidth = -1;
}
void RenderBox::clearOverrideSize()
@@ -1083,13 +979,13 @@ void RenderBox::clearOverrideSize()
LayoutUnit RenderBox::overrideLogicalContentWidth() const
{
ASSERT(hasOverrideWidth());
- return gOverrideWidthMap->get(this);
+ return m_rareData->m_overrideLogicalContentWidth;
}
LayoutUnit RenderBox::overrideLogicalContentHeight() const
{
ASSERT(hasOverrideHeight());
- return gOverrideHeightMap->get(this);
+ return m_rareData->m_overrideLogicalContentHeight;
}
LayoutUnit RenderBox::overrideContainingBlockContentLogicalWidth() const
@@ -1177,8 +1073,8 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
LayoutPoint adjustedLocation = accumulatedOffset + location();
// Check kids first.
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (!child->hasLayer() && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) {
+ for (RenderObject* child = slowLastChild(); child; child = child->previousSibling()) {
+ if ((!child->hasLayer() || !toRenderLayerModelObject(child)->layer()->isSelfPaintingLayer()) && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) {
updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
return true;
}
@@ -1186,7 +1082,7 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
// Check our bounds next. For this purpose always assume that we can only be hit in the
// foreground phase (which is true for replaced elements like images).
- LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
+ LayoutRect boundsRect = borderBoxRect();
boundsRect.moveBy(adjustedLocation);
if (visibleToHitTestRequest(request) && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
@@ -1205,7 +1101,7 @@ void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
// default implementation. Just pass paint through to the children
PaintInfo childInfo(paintInfo);
childInfo.updatePaintingRootForChildren(this);
- for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+ for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling())
child->paint(childInfo, adjustedPaintOffset);
}
@@ -1229,9 +1125,11 @@ BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsCo
const RenderStyle* style = this->style();
- if (!style->hasBackground() || !style->hasBorder() || !style->hasBorderRadius() || borderImageIsLoadedAndCanBeRendered())
+ if (!style->hasBackground() || !style->hasBorder() || !style->hasBorderRadius() || canRenderBorderImage())
return BackgroundBleedNone;
+ // FIXME: See crbug.com/382491. getCTM does not accurately reflect the scale at the time content is
+ // rasterized, and should not be relied on to make decisions about bleeding.
AffineTransform ctm = context->getCTM();
FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
@@ -1254,7 +1152,7 @@ BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsCo
if (!style->hasAppearance() && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
return BackgroundBleedBackgroundOverBorder;
- return BackgroundBleedUseTransparencyLayer;
+ return BackgroundBleedClipBackground;
}
void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -1262,7 +1160,7 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
if (!paintInfo.shouldPaintWithinRoot(this))
return;
- LayoutRect paintRect = borderBoxRectInRegion(paintInfo.renderRegion);
+ LayoutRect paintRect = borderBoxRect();
paintRect.moveBy(paintOffset);
paintBoxDecorationsWithRect(paintInfo, paintOffset, paintRect);
}
@@ -1277,20 +1175,13 @@ void RenderBox::paintBoxDecorationsWithRect(PaintInfo& paintInfo, const LayoutPo
paintBoxShadow(paintInfo, paintRect, style(), Normal);
GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
- if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
- // 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, view());
+ if (bleedAvoidance == BackgroundBleedClipBackground) {
stateSaver.save();
+ RoundedRect border = style()->getRoundedBorderFor(paintRect);
paintInfo.context->clipRoundedRect(border);
- paintInfo.context->beginTransparencyLayer(1);
}
paintBackgroundWithBorderAndBoxShadow(paintInfo, paintRect, bleedAvoidance);
-
- if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
- paintInfo.context->endLayer();
}
void RenderBox::paintBackgroundWithBorderAndBoxShadow(PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
@@ -1317,7 +1208,7 @@ void RenderBox::paintBackgroundWithBorderAndBoxShadow(PaintInfo& paintInfo, cons
void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
{
- if (isRoot()) {
+ if (isDocumentElement()) {
paintRootBoxFillLayers(paintInfo);
return;
}
@@ -1328,19 +1219,28 @@ void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& pa
paintFillLayers(paintInfo, resolveColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
}
-LayoutRect RenderBox::backgroundPaintedExtent() const
+bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const
{
ASSERT(hasBackground());
LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect());
Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
- if (backgroundColor.isValid() && backgroundColor.alpha())
- return backgroundRect;
- if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next())
- return backgroundRect;
+ if (backgroundColor.alpha()) {
+ paintedExtent = backgroundRect;
+ return true;
+ }
+
+ if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next()) {
+ paintedExtent = backgroundRect;
+ return true;
+ }
+
BackgroundImageGeometry geometry;
- const_cast<RenderBox*>(this)->calculateBackgroundImageGeometry(style()->backgroundLayers(), backgroundRect, geometry);
- return geometry.destRect();
+ calculateBackgroundImageGeometry(0, style()->backgroundLayers(), backgroundRect, geometry);
+ if (geometry.hasNonLocalGeometry())
+ return false;
+ paintedExtent = geometry.destRect();
+ return true;
}
bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
@@ -1349,7 +1249,7 @@ bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) c
return false;
Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
- if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
+ if (backgroundColor.hasAlpha())
return false;
// If the element has appearance, it might be painted by theme.
@@ -1411,7 +1311,7 @@ bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, u
{
if (!maxDepthToTest)
return false;
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling()) {
if (!child->isBox())
continue;
RenderBox* childBox = toRenderBox(child);
@@ -1445,12 +1345,14 @@ bool RenderBox::computeBackgroundIsKnownToBeObscured()
if (!hasBackground())
return false;
// Table and root background painting is special.
- if (isTable() || isRoot())
+ if (isTable() || isDocumentElement())
return false;
// FIXME: box-shadow is painted while background painting.
if (style()->boxShadow())
return false;
- LayoutRect backgroundRect = backgroundPaintedExtent();
+ LayoutRect backgroundRect;
+ if (!getBackgroundPaintedExtent(backgroundRect))
+ return false;
return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth);
}
@@ -1464,13 +1366,13 @@ bool RenderBox::backgroundHasOpaqueTopLayer() const
if (hasOverflowClip() && fillLayer->attachment() == LocalBackgroundAttachment)
return false;
- if (fillLayer->hasOpaqueImage(this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(this, style()->effectiveZoom()))
+ if (fillLayer->hasOpaqueImage(this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(*this, style()->effectiveZoom()))
return true;
// If there is only one layer and no image, check whether the background color is opaque
if (!fillLayer->next() && !fillLayer->hasImage()) {
Color bgColor = resolveColor(CSSPropertyBackgroundColor);
- if (bgColor.isValid() && bgColor.alpha() == 255)
+ if (bgColor.alpha() == 255)
return true;
}
@@ -1530,7 +1432,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa
}
if (allMaskImagesLoaded) {
- paintFillLayers(paintInfo, Color(), style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
+ paintFillLayers(paintInfo, Color::transparent, style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
}
@@ -1538,29 +1440,6 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa
paintInfo.context->endLayer();
}
-LayoutRect RenderBox::maskClipRect()
-{
- const NinePieceImage& maskBoxImage = style()->maskBoxImage();
- if (maskBoxImage.image()) {
- LayoutRect borderImageRect = borderBoxRect();
-
- // Apply outsets to the border box.
- borderImageRect.expand(style()->maskBoxImageOutsets());
- return borderImageRect;
- }
-
- LayoutRect result;
- LayoutRect borderBox = borderBoxRect();
- for (const FillLayer* maskLayer = style()->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
- if (maskLayer->image()) {
- BackgroundImageGeometry geometry;
- calculateBackgroundImageGeometry(maskLayer, borderBox, geometry);
- result.unite(geometry.destRect());
- }
- }
- return result;
-}
-
void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
{
@@ -1581,7 +1460,7 @@ void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, cons
shouldDrawBackgroundInSeparateBuffer = true;
// The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
- if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == blink::WebBlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+ if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(*this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == blink::WebBlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
break;
curLayer = curLayer->next();
}
@@ -1606,34 +1485,28 @@ void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const
paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
}
-static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers)
-{
- for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
- if (curLayer->image() && image == curLayer->image()->data())
- return true;
- }
-
- return false;
-}
-
void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
{
if (!parent())
return;
+ AllowPaintInvalidationScope scoper(frameView());
+
if ((style()->borderImage().image() && style()->borderImage().image()->data() == image) ||
(style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
- repaint();
+ paintInvalidationForWholeRenderer();
return;
}
+ ShapeValue* shapeOutsideValue = style()->shapeOutside();
+ if (!frameView()->isInPerformLayout() && isFloating() && shapeOutsideValue && shapeOutsideValue->image() && shapeOutsideValue->image()->data() == image) {
+ ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty();
+ markShapeOutsideDependentsForLayout();
+ }
+
bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
if (!didFullRepaint)
repaintLayerRectsForImage(image, style()->maskLayers(), false);
-
-
- if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers()))
- layer()->contentChanged(MaskImageChanged);
}
bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
@@ -1642,11 +1515,10 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
RenderBox* layerRenderer = 0;
for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
- if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style()->effectiveZoom())) {
- // Now that we know this image is being used, compute the renderer and the rect
- // if we haven't already
+ if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(*this, style()->effectiveZoom())) {
+ // Now that we know this image is being used, compute the renderer and the rect if we haven't already.
if (!layerRenderer) {
- bool drawingRootBackground = drawingBackground && (isRoot() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
+ bool drawingRootBackground = drawingBackground && (isDocumentElement() || (isBody() && !document().documentElement()->renderer()->hasBackground()));
if (drawingRootBackground) {
layerRenderer = view();
@@ -1671,8 +1543,15 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
}
BackgroundImageGeometry geometry;
- layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect, geometry);
- layerRenderer->repaintRectangle(geometry.destRect());
+ layerRenderer->calculateBackgroundImageGeometry(0, curLayer, rendererRect, geometry);
+ if (geometry.hasNonLocalGeometry()) {
+ // Rather than incur the costs of computing the paintContainer for renderers with fixed backgrounds
+ // in order to get the right destRect, just repaint the entire renderer.
+ layerRenderer->paintInvalidationForWholeRenderer();
+ return true;
+ }
+
+ layerRenderer->invalidatePaintRectangle(geometry.destRect());
if (geometry.destRect() == rendererRect)
return true;
}
@@ -1680,6 +1559,80 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
return false;
}
+void RenderBox::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
+{
+ // FIXME: Currently only using this logic for RenderBox and its ilk. Ideally, RenderBlockFlows with
+ // inline children should track a dirty rect in local coordinates for dirty lines instead of invalidating
+ // the world.
+ // FIXME: We should still be recursing through inline's children, as they can have boxes, but we don't
+ // appear to have tests for this?
+ // FIXME: SVG should probably also go through this unified paint invalidation system.
+
+ ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ ASSERT(!needsLayout());
+
+ if (!shouldCheckForPaintInvalidationAfterLayout())
+ return;
+
+ bool establishesNewPaintInvalidationContainer = isPaintInvalidationContainer();
+ const RenderLayerModelObject& newPaintInvalidationContainer = *adjustCompositedContainerForSpecialAncestors(establishesNewPaintInvalidationContainer ? this : &paintInvalidationContainer);
+ // FIXME: This assert should be re-enabled when we move paint invalidation to after compositing update. crbug.com/360286
+ // ASSERT(&newPaintInvalidationContainer == containerForPaintInvalidation());
+
+ const LayoutRect oldPaintInvalidationRect = previousPaintInvalidationRect();
+ const LayoutPoint oldPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
+ setPreviousPaintInvalidationRect(boundsRectForPaintInvalidation(&newPaintInvalidationContainer));
+ setPreviousPositionFromPaintInvalidationContainer(RenderLayer::positionFromPaintInvalidationContainer(this, &newPaintInvalidationContainer));
+
+ // If we are set to do a full paint invalidation that means the RenderView will be
+ // issue paint invalidations. We can then skip issuing of paint invalidations for the child
+ // renderers as they'll be covered by the RenderView.
+ if (view()->doingFullRepaint()) {
+ LayoutState state(*this, isTableRow() ? LayoutSize() : locationOffset());
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
+ return;
+ }
+
+ if ((onlyNeededPositionedMovementLayout() && compositingState() != PaintsIntoOwnBacking)
+ || (shouldDoFullPaintInvalidationIfSelfPaintingLayer()
+ && hasLayer()
+ && layer()->isSelfPaintingLayer())) {
+ setShouldDoFullPaintInvalidationAfterLayout(true);
+ }
+
+ const LayoutRect& newPaintInvalidationRect = previousPaintInvalidationRect();
+ const LayoutPoint& newPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
+ bool didFullPaintInvalidation = invalidatePaintAfterLayoutIfNeeded(&newPaintInvalidationContainer,
+ shouldDoFullPaintInvalidationAfterLayout(), oldPaintInvalidationRect, oldPositionFromPaintInvalidationContainer,
+ &newPaintInvalidationRect, &newPositionFromPaintInvalidationContainer);
+
+ if (!didFullPaintInvalidation)
+ invalidatePaintForOverflowIfNeeded();
+
+ // Issue paint invalidations for any scrollbars if there is a scrollable area for this renderer.
+ if (enclosingLayer()) {
+ if (RenderLayerScrollableArea* area = enclosingLayer()->scrollableArea()) {
+ if (area->hasVerticalBarDamage())
+ invalidatePaintRectangle(area->verticalBarDamage());
+ if (area->hasHorizontalBarDamage())
+ invalidatePaintRectangle(area->horizontalBarDamage());
+ area->resetScrollbarDamage();
+ }
+ }
+
+ // FIXME: LayoutState should be enabled for other paint invalidation containers than the RenderView. crbug.com/363834
+ if (establishesNewPaintInvalidationContainer && !isRenderView()) {
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
+ } else {
+ // FIXME: This concept of a tree walking state for fast lookups should be generalized away from
+ // just layout.
+ // FIXME: Table rows shouldn't be special-cased.
+ LayoutState state(*this, isTableRow() ? LayoutSize() : locationOffset());
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
+ }
+}
+
bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset, ContentsClipBehavior contentsClipBehavior)
{
if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
@@ -1691,7 +1644,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu
if (!isControlClip && !isOverflowClip)
return false;
- LayoutRect clipRect = isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion);
+ LayoutRect clipRect = isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset);
RoundedRect clipRoundedRect(0, 0, 0, 0);
bool hasBorderRadius = style()->hasBorderRadius();
if (hasBorderRadius)
@@ -1702,11 +1655,6 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu
if (contentsVisualOverflow.isEmpty())
return false;
- // FIXME: Get rid of this slop from here and elsewhere.
- // Instead, properly include the outline in visual overflow.
- if (RenderView* view = this->view())
- contentsVisualOverflow.inflate(view->maximalOutlineSize());
-
LayoutRect conservativeClipRect = clipRect;
if (hasBorderRadius)
conservativeClipRect.intersect(clipRoundedRect.radiusCenterRect());
@@ -1744,11 +1692,11 @@ void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase,
paintInfo.phase = originalPhase;
}
-LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy)
{
// FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
// here.
- LayoutRect clipRect = borderBoxRectInRegion(region);
+ LayoutRect clipRect = borderBoxRect();
clipRect.setLocation(location + clipRect.location() + LayoutSize(borderLeft(), borderTop()));
clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
@@ -1763,74 +1711,55 @@ LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion
return clipRect;
}
-LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region)
+LayoutRect RenderBox::clipRect(const LayoutPoint& location)
{
- LayoutRect borderBoxRect = borderBoxRectInRegion(region);
+ LayoutRect borderBoxRect = this->borderBoxRect();
LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
- RenderView* renderView = view();
if (!style()->clipLeft().isAuto()) {
- LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width(), renderView);
+ LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width());
clipRect.move(c, 0);
clipRect.contract(c, 0);
}
- // We don't use the region-specific border box's width and height since clip offsets are (stupidly) specified
- // 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() - valueForLength(style()->clipRight(), width(), renderView), 0);
+ clipRect.contract(width() - valueForLength(style()->clipRight(), width()), 0);
if (!style()->clipTop().isAuto()) {
- LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height(), renderView);
+ LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height());
clipRect.move(0, c);
clipRect.contract(0, c);
}
if (!style()->clipBottom().isAuto())
- clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height(), renderView));
+ clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height()));
return clipRect;
}
-LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb, RenderRegion* region) const
+static LayoutUnit portionOfMarginNotConsumedByFloat(LayoutUnit childMargin, LayoutUnit contentSide, LayoutUnit offset)
{
- RenderRegion* containingBlockRegion = 0;
- LayoutUnit logicalTopPosition = logicalTop();
- if (region) {
- LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
- logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
- containingBlockRegion = cb->clampToStartAndEndRegions(region);
- }
+ if (childMargin <= 0)
+ return 0;
+ LayoutUnit contentSideWithMargin = contentSide + childMargin;
+ if (offset > contentSideWithMargin)
+ return childMargin;
+ return offset - contentSide;
+}
- LayoutUnit result = cb->availableLogicalWidthForLineInRegion(logicalTopPosition, false, containingBlockRegion) - childMarginStart - childMarginEnd;
+LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb) const
+{
+ LayoutUnit logicalTopPosition = logicalTop();
+ LayoutUnit width = cb->availableLogicalWidthForLine(logicalTopPosition, false) - max<LayoutUnit>(0, childMarginStart) - max<LayoutUnit>(0, childMarginEnd);
// We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
// then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
// offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float
// doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was
// "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
- if (childMarginStart > 0) {
- LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion);
- LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart;
- LayoutUnit startOffset = cb->startOffsetForLineInRegion(logicalTopPosition, false, containingBlockRegion);
- if (startOffset > startContentSideWithMargin)
- result += childMarginStart;
- else
- result += startOffset - startContentSide;
- }
-
- if (childMarginEnd > 0) {
- LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion);
- LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd;
- LayoutUnit endOffset = cb->endOffsetForLineInRegion(logicalTopPosition, false, containingBlockRegion);
- if (endOffset > endContentSideWithMargin)
- result += childMarginEnd;
- else
- result += endOffset - endContentSide;
- }
-
- return result;
+ width += portionOfMarginNotConsumedByFloat(childMarginStart, cb->startOffsetForContent(), cb->startOffsetForLine(logicalTopPosition, false));
+ width += portionOfMarginNotConsumedByFloat(childMarginEnd, cb->endOffsetForContent(), cb->endOffsetForLine(logicalTopPosition, false));
+ return width;
}
LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const
@@ -1851,33 +1780,12 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForContent(AvailableLogicalHei
return cb->availableLogicalHeight(heightType);
}
-LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion* region) const
+LayoutUnit RenderBox::containingBlockAvailableLineWidth() const
{
- if (!region)
- return containingBlockLogicalWidthForContent();
-
RenderBlock* cb = containingBlock();
- RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
- // FIXME: It's unclear if a region's content should use the containing block's override logical width.
- // If it should, the following line should call containingBlockLogicalWidthForContent.
- LayoutUnit result = cb->availableLogicalWidth();
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
- if (!boxInfo)
- return result;
- return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
-}
-
-LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region) const
-{
- RenderBlock* cb = containingBlock();
- RenderRegion* containingBlockRegion = 0;
- LayoutUnit logicalTopPosition = logicalTop();
- if (region) {
- LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit();
- logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
- containingBlockRegion = cb->clampToStartAndEndRegions(region);
- }
- return cb->availableLogicalWidthForLineInRegion(logicalTopPosition, false, containingBlockRegion, availableLogicalHeight(IncludeMarginBorderPadding));
+ if (cb->isRenderBlockFlow())
+ return toRenderBlockFlow(cb)->availableLogicalWidthForLine(logicalTop(), false, availableLogicalHeight(IncludeMarginBorderPadding));
+ return 0;
}
LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
@@ -1909,9 +1817,9 @@ void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContain
return;
if (RenderView* v = view()) {
- if (v->layoutStateEnabled() && !repaintContainer) {
+ if (v->canMapUsingLayoutStateForContainer(repaintContainer)) {
LayoutState* layoutState = v->layoutState();
- LayoutSize offset = layoutState->m_paintOffset + locationOffset();
+ LayoutSize offset = layoutState->paintOffset() + locationOffset();
if (style()->hasInFlowPosition() && layer())
offset += layer()->offsetForInFlowPosition();
transformState.move(offset);
@@ -1962,7 +1870,7 @@ void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContain
void RenderBox::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
{
// We don't expect to be called during layout.
- ASSERT(!view() || !view()->layoutStateEnabled());
+ ASSERT(!view() || !view()->layoutStateCachedOffsetsEnabled());
bool isFixedPos = style()->position() == FixedPosition;
bool hasTransform = hasLayer() && layer()->transform();
@@ -1976,13 +1884,9 @@ void RenderBox::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState
RenderBoxModelObject::mapAbsoluteToLocalPoint(mode, transformState);
}
-LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+LayoutSize RenderBox::offsetFromContainer(const RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
- // A region "has" boxes inside it without being their container.
- // FIXME: change container() / containingBlock() to count for boxes being positioned relative to the region, not the
- // FlowThread. This requires a separate patch as a simple test with such a change in container() causes 129 out of
- // 337 regions tests to fail.
- ASSERT(o == container() || o->isRenderRegion());
+ ASSERT(o == container());
LayoutSize offset;
if (isInFlowPositioned())
@@ -1990,46 +1894,55 @@ LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& po
if (!isInline() || isReplaced()) {
if (!style()->hasOutOfFlowPosition() && o->hasColumns()) {
- RenderBlock* block = toRenderBlock(o);
+ const RenderBlock* block = toRenderBlock(o);
LayoutRect columnRect(frameRect());
block->adjustStartEdgeForWritingModeIncludingColumns(columnRect);
offset += toSize(columnRect.location());
LayoutPoint columnPoint = block->flipForWritingModeIncludingColumns(point + offset);
offset = toLayoutSize(block->flipForWritingModeIncludingColumns(toLayoutPoint(offset)));
- o->adjustForColumns(offset, columnPoint);
+ offset += o->columnOffset(columnPoint);
offset = block->flipForWritingMode(offset);
if (offsetDependsOnPoint)
*offsetDependsOnPoint = true;
- } else
+ } else {
offset += topLeftLocationOffset();
+ if (o->isRenderFlowThread()) {
+ // So far the point has been in flow thread coordinates (i.e. as if everything in
+ // the fragmentation context lived in one tall single column). Convert it to a
+ // visual point now.
+ LayoutPoint pointInContainer = point + offset;
+ offset += o->columnOffset(pointInContainer);
+ if (offsetDependsOnPoint)
+ *offsetDependsOnPoint = true;
+ }
+ }
}
if (o->hasOverflowClip())
offset -= toRenderBox(o)->scrolledContentOffset();
if (style()->position() == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
- offset += toRenderInline(o)->offsetForInFlowPositionedInline(this);
-
- if (offsetDependsOnPoint)
- *offsetDependsOnPoint |= o->isRenderFlowThread();
+ offset += toRenderInline(o)->offsetForInFlowPositionedInline(*this);
return offset;
}
InlineBox* RenderBox::createInlineBox()
{
- return new InlineBox(this);
+ return new InlineBox(*this);
}
void RenderBox::dirtyLineBoxes(bool fullLayout)
{
- if (m_inlineBoxWrapper) {
+ if (inlineBoxWrapper()) {
if (fullLayout) {
- m_inlineBoxWrapper->destroy();
- m_inlineBoxWrapper = 0;
- } else
- m_inlineBoxWrapper->dirtyLineBoxes();
+ inlineBoxWrapper()->destroy();
+ ASSERT(m_rareData);
+ m_rareData->m_inlineBoxWrapper = 0;
+ } else {
+ inlineBoxWrapper()->dirtyLineBoxes();
+ }
}
}
@@ -2042,8 +1955,8 @@ void RenderBox::positionLineBox(InlineBox* box)
// The value is cached in the xPos of the box. We only need this value if
// our object was inline originally, since otherwise it would have ended up underneath
// the inlines.
- RootInlineBox* root = box->root();
- root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), LayoutUnit::fromFloatRound(box->logicalLeft()));
+ RootInlineBox& root = box->root();
+ root.block().setStaticInlinePositionForChild(this, root.lineTopWithLeading(), LayoutUnit::fromFloatRound(box->logicalLeft()));
if (style()->hasStaticInlinePosition(box->isHorizontal()))
setChildNeedsLayout(MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
} else {
@@ -2057,7 +1970,7 @@ void RenderBox::positionLineBox(InlineBox* box)
}
// Nuke the box.
- box->remove();
+ box->remove(DontMarkLineBoxes);
box->destroy();
} else if (isReplaced()) {
setLocation(roundedLayoutPoint(box->topLeft()));
@@ -2067,42 +1980,34 @@ void RenderBox::positionLineBox(InlineBox* box)
void RenderBox::deleteLineBoxWrapper()
{
- if (m_inlineBoxWrapper) {
+ if (inlineBoxWrapper()) {
if (!documentBeingDestroyed())
- m_inlineBoxWrapper->remove();
- m_inlineBoxWrapper->destroy();
- m_inlineBoxWrapper = 0;
+ inlineBoxWrapper()->remove();
+ inlineBoxWrapper()->destroy();
+ ASSERT(m_rareData);
+ m_rareData->m_inlineBoxWrapper = 0;
}
}
-LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderBox::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+ if (style()->visibility() != VISIBLE && enclosingLayer()->subtreeIsInvisible())
return LayoutRect();
LayoutRect r = visualOverflowRect();
RenderView* v = view();
- if (v) {
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && v) {
// FIXME: layoutDelta needs to be applied in parts before/after transforms and
// repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
r.move(v->layoutDelta());
}
- if (style()) {
- // We have to use maximalOutlineSize() because a child might have an outline
- // that projects outside of our overflowRect.
- if (v) {
- ASSERT(style()->outlineSize() <= v->maximalOutlineSize());
- r.inflate(v->maximalOutlineSize());
- }
- }
-
- computeRectForRepaint(repaintContainer, r);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, r);
return r;
}
-void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+void RenderBox::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, bool fixed) const
{
// The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
// Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate
@@ -2110,12 +2015,12 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
// properly even during layout, since the rect remains flipped all the way until the end.
//
// RenderView::computeRectForRepaint then converts the rect to physical coordinates. We also convert to
- // physical when we hit a repaintContainer boundary. Therefore the final rect returned is always in the
- // physical coordinate space of the repaintContainer.
+ // physical when we hit a paintInvalidationContainer boundary. Therefore the final rect returned is always in the
+ // physical coordinate space of the paintInvalidationContainer.
RenderStyle* styleToUse = style();
if (RenderView* v = view()) {
// LayoutState is only valid for root-relative, non-fixed position repainting
- if (v->layoutStateEnabled() && !repaintContainer && styleToUse->position() != FixedPosition) {
+ if (v->canMapUsingLayoutStateForContainer(paintInvalidationContainer) && styleToUse->position() != FixedPosition) {
LayoutState* layoutState = v->layoutState();
if (layer() && layer()->transform())
@@ -2126,9 +2031,9 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
rect.move(layer()->offsetForInFlowPosition());
rect.moveBy(location());
- rect.move(layoutState->m_paintOffset);
- if (layoutState->m_clipped)
- rect.intersect(layoutState->m_clipRect);
+ rect.move(layoutState->paintOffset());
+ if (layoutState->isClipped())
+ rect.intersect(layoutState->clipRect());
return;
}
}
@@ -2136,14 +2041,14 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
if (hasReflection())
rect.unite(reflectedRect(rect));
- if (repaintContainer == this) {
- if (repaintContainer->style()->isFlippedBlocksWritingMode())
+ if (paintInvalidationContainer == this) {
+ if (paintInvalidationContainer->style()->isFlippedBlocksWritingMode())
flipForWritingMode(rect);
return;
}
bool containerSkipped;
- RenderObject* o = container(repaintContainer, &containerSkipped);
+ RenderObject* o = container(paintInvalidationContainer, &containerSkipped);
if (!o)
return;
@@ -2166,7 +2071,7 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
fixed = true;
if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline()) {
- topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this);
+ topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(*this);
} else if (styleToUse->hasInFlowPosition() && 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
@@ -2193,13 +2098,13 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
}
if (containerSkipped) {
- // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
- LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+ // If the paintInvalidationContainer is below o, then we need to map the rect into paintInvalidationContainer's coordinates.
+ LayoutSize containerOffset = paintInvalidationContainer->offsetFromAncestorContainer(o);
rect.move(-containerOffset);
return;
}
- o->computeRectForRepaint(repaintContainer, rect, fixed);
+ o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, fixed);
}
void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
@@ -2209,10 +2114,10 @@ void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
// The child moved. Invalidate the object's old and new positions. We have to do this
// since the object may not have gotten a layout.
m_frameRect = oldRect;
- repaint();
+ paintInvalidationForWholeRenderer();
repaintOverhangingFloats(true);
m_frameRect = newRect;
- repaint();
+ paintInvalidationForWholeRenderer();
repaintOverhangingFloats(true);
}
}
@@ -2224,7 +2129,7 @@ void RenderBox::repaintOverhangingFloats(bool)
void RenderBox::updateLogicalWidth()
{
LogicalExtentComputedValues computedValues;
- computeLogicalWidthInRegion(computedValues);
+ computeLogicalWidth(computedValues);
setLogicalWidth(computedValues.m_extent);
setLogicalLeft(computedValues.m_position);
@@ -2238,25 +2143,22 @@ static float getMaxWidthListMarker(const RenderBox* renderer)
ASSERT(renderer);
Node* parentNode = renderer->generatingNode();
ASSERT(parentNode);
- ASSERT(parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag));
+ ASSERT(isHTMLOListElement(parentNode) || isHTMLUListElement(parentNode));
ASSERT(renderer->style()->textAutosizingMultiplier() != 1);
#endif
float maxWidth = 0;
- for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = renderer->slowFirstChild(); child; child = child->nextSibling()) {
if (!child->isListItem())
continue;
RenderBox* listItem = toRenderBox(child);
- for (RenderObject* itemChild = listItem->firstChild(); itemChild; itemChild = itemChild->nextSibling()) {
+ for (RenderObject* itemChild = listItem->slowFirstChild(); itemChild; itemChild = itemChild->nextSibling()) {
if (!itemChild->isListMarker())
continue;
RenderBox* itemMarker = toRenderBox(itemChild);
- // FIXME: canDetermineWidthWithoutLayout expects us to use fixedOffsetWidth, which this code
- // does not do! This check is likely wrong.
- if (!itemMarker->canDetermineWidthWithoutLayout() && itemMarker->needsLayout()) {
- // Make sure to compute the autosized width.
+ // Make sure to compute the autosized width.
+ if (itemMarker->needsLayout())
itemMarker->layout();
- }
maxWidth = max<float>(maxWidth, toRenderListMarker(itemMarker)->logicalWidth().toFloat());
break;
}
@@ -2264,7 +2166,7 @@ static float getMaxWidthListMarker(const RenderBox* renderer)
return maxWidth;
}
-void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
+void RenderBox::computeLogicalWidth(LogicalExtentComputedValues& computedValues) const
{
computedValues.m_extent = logicalWidth();
computedValues.m_position = logicalLeft();
@@ -2274,7 +2176,7 @@ void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& compute
if (isOutOfFlowPositioned()) {
// FIXME: This calculation is not patched for block-flow yet.
// https://bugs.webkit.org/show_bug.cgi?id=46500
- computePositionedLogicalWidth(computedValues, region);
+ computePositionedLogicalWidth(computedValues);
return;
}
@@ -2301,16 +2203,15 @@ void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& compute
Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
RenderBlock* cb = containingBlock();
- LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region));
+ LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContent());
bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
if (isInline() && !isInlineBlockOrInlineTable()) {
// just calculate margins
- RenderView* renderView = view();
- computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
- computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
+ computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth);
+ computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth);
if (treatAsReplaced)
- computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
+ computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
return;
}
@@ -2321,24 +2222,13 @@ void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& compute
LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
if (hasPerpendicularContainingBlock)
containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
- LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, styleToUse->logicalWidth(), containerWidthInInlineDirection, cb, region);
- computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region);
+ LayoutUnit preferredWidth = computeLogicalWidthUsing(MainOrPreferredSize, styleToUse->logicalWidth(), containerWidthInInlineDirection, cb);
+ computedValues.m_extent = constrainLogicalWidthByMinMax(preferredWidth, containerWidthInInlineDirection, cb);
}
// Margin calculations.
- if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
- RenderView* renderView = view();
- computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
- computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
- } else {
- LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
- if (avoidsFloats() && cb->containsFloats())
- containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region);
- bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
- computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, computedValues.m_extent,
- hasInvertedDirection ? computedValues.m_margins.m_end : computedValues.m_margins.m_start,
- hasInvertedDirection ? computedValues.m_margins.m_start : computedValues.m_margins.m_end);
- }
+ computeMarginsForDirection(InlineDirection, cb, containerLogicalWidth, computedValues.m_extent, computedValues.m_margins.m_start,
+ computedValues.m_margins.m_end, style()->marginStart(), style()->marginEnd());
if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end)
&& !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated() && !cb->isRenderGrid()) {
@@ -2352,7 +2242,7 @@ void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& compute
if (styleToUse->textAutosizingMultiplier() != 1 && styleToUse->marginStart().type() == Fixed) {
Node* parentNode = generatingNode();
- if (parentNode && (parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag))) {
+ if (parentNode && (isHTMLOListElement(*parentNode) || isHTMLUListElement(*parentNode))) {
// Make sure the markers in a list are properly positioned (i.e. not chopped off) when autosized.
const float adjustedMargin = (1 - 1.0 / styleToUse->textAutosizingMultiplier()) * getMaxWidthListMarker(this);
bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
@@ -2373,13 +2263,12 @@ LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth) con
LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
{
- RenderView* renderView = view();
- marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
- marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
+ marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth);
+ marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth);
return availableLogicalWidth - marginStart - marginEnd;
}
-LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const
+LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(const Length& logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const
{
if (logicalWidthLength.type() == FillAvailable)
return fillAvailableMeasure(availableLogicalWidth);
@@ -2404,12 +2293,11 @@ LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLengt
return 0;
}
-LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth,
- const RenderBlock* cb, RenderRegion* region) const
+LayoutUnit RenderBox::computeLogicalWidthUsing(SizeType widthType, const Length& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock* cb) const
{
if (!logicalWidth.isIntrinsicOrAuto()) {
// FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
- return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth, view()));
+ return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth));
}
if (logicalWidth.isIntrinsic())
@@ -2420,9 +2308,9 @@ LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Lengt
LayoutUnit logicalWidthResult = fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
if (shrinkToAvoidFloats() && cb->containsFloats())
- logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb), region));
+ logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb)));
- if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(widthType))
+ if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(logicalWidth))
return max(minPreferredLogicalWidth(), min(maxPreferredLogicalWidth(), logicalWidthResult));
return logicalWidthResult;
}
@@ -2435,7 +2323,7 @@ static bool columnFlexItemHasStretchAlignment(const RenderObject* flexitem)
ASSERT(parent->style()->isColumnFlexDirection());
if (flexitem->style()->marginStart().isAuto() || flexitem->style()->marginEnd().isAuto())
return false;
- return flexitem->style()->alignSelf() == AlignStretch || (flexitem->style()->alignSelf() == AlignAuto && parent->style()->alignItems() == AlignStretch);
+ return flexitem->style()->alignSelf() == ItemPositionStretch || (flexitem->style()->alignSelf() == ItemPositionAuto && parent->style()->alignItems() == ItemPositionStretch);
}
static bool isStretchingColumnFlexItem(const RenderObject* flexitem)
@@ -2450,16 +2338,13 @@ static bool isStretchingColumnFlexItem(const RenderObject* flexitem)
return false;
}
-bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
+bool RenderBox::sizesLogicalWidthToFitContent(const Length& logicalWidth) const
{
// Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks,
// but they allow text to sit on the same line as the marquee.
if (isFloating() || (isInlineBlockOrInlineTable() && !isMarquee()))
return true;
- // This code may look a bit strange. Basically width:intrinsic should clamp the size when testing both
- // min-width and width. max-width is only clamped if it is also intrinsic.
- Length logicalWidth = (widthType == MaxSize) ? style()->logicalMaxWidth() : style()->logicalWidth();
if (logicalWidth.type() == Intrinsic)
return true;
@@ -2496,7 +2381,7 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
// stretching column flexbox.
// FIXME: Think about block-flow here.
// https://bugs.webkit.org/show_bug.cgi?id=46473
- if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(this) && autoWidthShouldFitContent())
+ if (logicalWidth.isAuto() && !isStretchingColumnFlexItem(this) && autoWidthShouldFitContent())
return true;
if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
@@ -2507,24 +2392,26 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
bool RenderBox::autoWidthShouldFitContent() const
{
- if (node() && (node()->hasTagName(inputTag) || node()->hasTagName(selectTag) || node()->hasTagName(buttonTag)
- || isHTMLTextAreaElement(node()) || node()->hasTagName(legendTag)))
- return true;
-
- return false;
+ return node() && (isHTMLInputElement(*node()) || isHTMLSelectElement(*node()) || isHTMLButtonElement(*node())
+ || isHTMLTextAreaElement(*node()) || (isHTMLLegendElement(*node()) && !style()->hasOutOfFlowPosition()));
}
-void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
+void RenderBox::computeMarginsForDirection(MarginDirection flowDirection, const RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd, Length marginStartLength, Length marginEndLength) const
{
- const RenderStyle* containingBlockStyle = containingBlock->style();
- Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
- Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
- RenderView* renderView = view();
+ if (flowDirection == BlockDirection || isFloating() || isInline()) {
+ if (isTableCell() && flowDirection == BlockDirection) {
+ // FIXME: Not right if we allow cells to have different directionality than the table. If we do allow this, though,
+ // we may just do it with an extra anonymous block inside the cell.
+ marginStart = 0;
+ marginEnd = 0;
+ return;
+ }
- if (isFloating() || isInline()) {
+ // Margins are calculated with respect to the logical width of
+ // the containing block (8.3)
// Inline blocks/tables and floats don't have their margins increased.
- marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
- marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
+ marginStart = minimumValueForLength(marginStartLength, containerWidth);
+ marginEnd = minimumValueForLength(marginEndLength, containerWidth);
return;
}
@@ -2538,129 +2425,53 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
marginEndLength.setValue(0);
}
- // Case One: The object is being centered in the containing block's available logical width.
- if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
- || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style()->textAlign() == WEBKIT_CENTER)) {
+ LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth);
+ LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth);
+
+ LayoutUnit availableWidth = containerWidth;
+ if (avoidsFloats() && containingBlock->containsFloats()) {
+ availableWidth = containingBlockAvailableLineWidth();
+ if (shrinkToAvoidFloats() && availableWidth < containerWidth) {
+ marginStart = max<LayoutUnit>(0, marginStartWidth);
+ marginEnd = max<LayoutUnit>(0, marginEndWidth);
+ }
+ }
+
+ // CSS 2.1 (10.3.3): "If 'width' is not 'auto' and 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width'
+ // (plus any of 'margin-left' or 'margin-right' that are not 'auto') is larger than the width of the containing block, then any 'auto'
+ // values for 'margin-left' or 'margin-right' are, for the following rules, treated as zero.
+ LayoutUnit marginBoxWidth = childWidth + (!style()->width().isAuto() ? marginStartWidth + marginEndWidth : LayoutUnit());
+
+ // CSS 2.1: "If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers the element
+ // with respect to the edges of the containing block."
+ const RenderStyle* containingBlockStyle = containingBlock->style();
+ if ((marginStartLength.isAuto() && marginEndLength.isAuto() && marginBoxWidth < availableWidth)
+ || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlockStyle->textAlign() == WEBKIT_CENTER)) {
// Other browsers center the margin box for align=center elements so we match them here.
- LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView);
- LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView);
- LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
+ LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (availableWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
marginStart = centeredMarginBoxStart + marginStartWidth;
- marginEnd = containerWidth - childWidth - marginStart + marginEndWidth;
+ marginEnd = availableWidth - childWidth - marginStart + marginEndWidth;
return;
}
- // Case Two: The object is being pushed to the start of the containing block's available logical width.
- if (marginEndLength.isAuto() && childWidth < containerWidth) {
- marginStart = valueForLength(marginStartLength, containerWidth, renderView);
- marginEnd = containerWidth - childWidth - marginStart;
+ // CSS 2.1: "If there is exactly one value specified as 'auto', its used value follows from the equality."
+ if (marginEndLength.isAuto() && marginBoxWidth < availableWidth) {
+ marginStart = marginStartWidth;
+ marginEnd = availableWidth - childWidth - marginStart;
return;
}
- // Case Three: The object is being pushed to the end of the containing block's available logical width.
bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
|| (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
- if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
- marginEnd = valueForLength(marginEndLength, containerWidth, renderView);
- marginStart = containerWidth - childWidth - marginEnd;
+ if ((marginStartLength.isAuto() && marginBoxWidth < availableWidth) || pushToEndFromTextAlign) {
+ marginEnd = marginEndWidth;
+ marginStart = availableWidth - childWidth - marginEnd;
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.
- marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
- marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
-}
-
-RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, RenderBoxRegionInfoFlags cacheFlag) const
-{
- // Make sure nobody is trying to call this with a null region.
- if (!region)
- return 0;
-
- // If we have computed our width in this region already, it will be cached, and we can
- // just return it.
- RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
- if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
- return boxInfo;
-
- // No cached value was found, so we have to compute our insets in this region.
- // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
- // support to cover all boxes.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (isRenderFlowThread() || !flowThread || !canHaveBoxInfoInRegion() || flowThread->style()->writingMode() != style()->writingMode())
- return 0;
-
- LogicalExtentComputedValues computedValues;
- computeLogicalWidthInRegion(computedValues, region);
-
- // Now determine the insets based off where this object is supposed to be positioned.
- RenderBlock* cb = containingBlock();
- RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
- RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion);
- LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
- LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
-
- LayoutUnit marginStartInRegion = computedValues.m_margins.m_start;
- LayoutUnit startMarginDelta = marginStartInRegion - marginStart();
- LayoutUnit logicalWidthInRegion = computedValues.m_extent;
- LayoutUnit logicalLeftInRegion = computedValues.m_position;
- LayoutUnit widthDelta = logicalWidthInRegion - logicalWidth();
- LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - logicalLeft() : startMarginDelta;
- LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
- LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth());
- LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
-
- LayoutUnit logicalLeftOffset = 0;
-
- if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
- LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region);
- if (cb->style()->isLeftToRightDirection())
- logicalLeftDelta += startPositionDelta;
- else
- logicalRightDelta += startPositionDelta;
- }
-
- if (cb->style()->isLeftToRightDirection())
- logicalLeftOffset += logicalLeftDelta;
- else
- logicalLeftOffset -= (widthDelta + logicalRightDelta);
-
- LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
- bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
- || (style()->isLeftToRightDirection() && logicalLeftOffset)
- || (!style()->isLeftToRightDirection() && logicalRightOffset);
-
- // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
- if (cacheFlag == CacheRenderBoxRegionInfo)
- return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
- return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
-}
-
-static bool shouldFlipBeforeAfterMargins(const RenderStyle* containingBlockStyle, const RenderStyle* childStyle)
-{
- ASSERT(containingBlockStyle->isHorizontalWritingMode() != childStyle->isHorizontalWritingMode());
- WritingMode childWritingMode = childStyle->writingMode();
- bool shouldFlip = false;
- switch (containingBlockStyle->writingMode()) {
- case TopToBottomWritingMode:
- shouldFlip = (childWritingMode == RightToLeftWritingMode);
- break;
- case BottomToTopWritingMode:
- shouldFlip = (childWritingMode == RightToLeftWritingMode);
- break;
- case RightToLeftWritingMode:
- shouldFlip = (childWritingMode == BottomToTopWritingMode);
- break;
- case LeftToRightWritingMode:
- shouldFlip = (childWritingMode == BottomToTopWritingMode);
- break;
- }
-
- if (!containingBlockStyle->isLeftToRightDirection())
- shouldFlip = !shouldFlip;
-
- return shouldFlip;
+ // Either no auto margins, or our margin box width is >= the container width, auto margins will just turn into 0.
+ marginStart = marginStartWidth;
+ marginEnd = marginEndWidth;
}
void RenderBox::updateLogicalHeight()
@@ -2690,23 +2501,20 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica
computePositionedLogicalHeight(computedValues);
else {
RenderBlock* cb = containingBlock();
- bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
- if (!hasPerpendicularContainingBlock) {
- bool shouldFlipBeforeAfter = cb->style()->writingMode() != style()->writingMode();
- computeBlockDirectionMargins(cb,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
- }
+ // If we are perpendicular to our containing block then we need to resolve our block-start and block-end margins so that if they
+ // are 'auto' we are centred or aligned within the inline flow containing block: this is done by computing the margins as though they are inline.
+ // Note that as this is the 'sizing phase' we are using our own writing mode rather than the containing block's. We use the containing block's
+ // writing mode when figuring out the block-direction margins for positioning in |computeAndSetBlockDirectionMargins| (i.e. margin collapsing etc.).
+ // See http://www.w3.org/TR/2014/CR-css-writing-modes-3-20140320/#orthogonal-flows
+ MarginDirection flowDirection = isHorizontalWritingMode() != cb->isHorizontalWritingMode() ? InlineDirection : BlockDirection;
// For tables, calculate margins only.
if (isTable()) {
- if (hasPerpendicularContainingBlock) {
- bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
- computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), computedValues.m_extent,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
- }
+ // FIXME: RenderTable::layout() calls updateLogicalHeight() when an empty table has no height yet, so auto margins can come out wrong here when
+ // we are perpendicular to our containing block.
+ computeMarginsForDirection(flowDirection, cb, containingBlockLogicalWidthForContent(), computedValues.m_extent, computedValues.m_margins.m_before,
+ computedValues.m_margins.m_after, style()->marginBefore(), style()->marginAfter());
return;
}
@@ -2733,8 +2541,7 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica
// Block children of horizontal flexible boxes fill the height of the box.
// FIXME: Account for block-flow in flexible boxes.
// https://bugs.webkit.org/show_bug.cgi?id=46418
- if (h.isAuto() && parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
- && parent()->isStretchingChildren()) {
+ if (h.isAuto() && inHorizontalBox && toRenderDeprecatedFlexibleBox(parent())->isStretchingChildren()) {
h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
checkMinMaxHeight = false;
}
@@ -2754,13 +2561,8 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica
}
computedValues.m_extent = heightResult;
-
- if (hasPerpendicularContainingBlock) {
- bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
- computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
- shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
- }
+ computeMarginsForDirection(flowDirection, cb, containingBlockLogicalWidthForContent(), computedValues.m_extent, computedValues.m_margins.m_before,
+ computedValues.m_margins.m_after, style()->marginBefore(), style()->marginAfter());
}
// WinIE quirk: The <html> block always fills the entire canvas in quirks mode. The <body> always fills the
@@ -2769,11 +2571,11 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica
// height since we don't set a height in RenderView when we're printing. So without this quirk, the
// height has nothing to be a percentage of, and it ends up being 0. That is bad.
bool paginatedContentNeedsBaseHeight = document().printing() && h.isPercent()
- && (isRoot() || (isBody() && document().documentElement()->renderer()->style()->logicalHeight().isPercent())) && !isInline();
+ && (isDocumentElement() || (isBody() && document().documentElement()->renderer()->style()->logicalHeight().isPercent())) && !isInline();
if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
- LayoutUnit visibleHeight = viewLogicalHeightForPercentages();
- if (isRoot())
+ LayoutUnit visibleHeight = view()->viewLogicalHeightForPercentages();
+ if (isDocumentElement())
computedValues.m_extent = max(computedValues.m_extent, visibleHeight - margins);
else {
LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
@@ -2782,13 +2584,6 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica
}
}
-LayoutUnit RenderBox::viewLogicalHeightForPercentages() const
-{
- if (document().printing())
- return static_cast<LayoutUnit>(view()->pageLogicalHeight());
- return view()->viewLogicalHeight();
-}
-
LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const
{
LayoutUnit logicalHeight = computeContentAndScrollbarLogicalHeightUsing(height, intrinsicContentHeight);
@@ -2805,7 +2600,7 @@ LayoutUnit RenderBox::computeContentLogicalHeight(const Length& height, LayoutUn
return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
}
-LayoutUnit RenderBox::computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const
+LayoutUnit RenderBox::computeIntrinsicLogicalContentHeightUsing(const Length& logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const
{
// FIXME(cbiesinger): The css-sizing spec is considering changing what min-content/max-content should resolve to.
// If that happens, this code will have to change.
@@ -2835,13 +2630,16 @@ LayoutUnit RenderBox::computeContentAndScrollbarLogicalHeightUsing(const Length&
return height.value();
if (height.isPercent())
return computePercentageLogicalHeight(height);
- if (height.isViewportPercentage())
- return valueForLength(height, 0, view());
return -1;
}
bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock) const
{
+ // Flow threads for multicol or paged overflow should be skipped. They are invisible to the DOM,
+ // and percent heights of children should be resolved against the multicol or paged container.
+ if (containingBlock->isRenderFlowThread())
+ return true;
+
// For quirks mode and anonymous blocks, we skip auto-height containingBlocks when computing percentages.
// For standards mode, we treat the percentage as auto if it has an auto-height containing block.
if (!document().inQuirksMode() && !containingBlock->isAnonymousBlock())
@@ -2858,13 +2656,13 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
const RenderBox* containingBlockChild = this;
LayoutUnit rootMarginBorderPaddingHeight = 0;
while (!cb->isRenderView() && skipContainingBlockForPercentHeightCalculation(cb)) {
- if (cb->isBody() || cb->isRoot())
+ if (cb->isBody() || cb->isDocumentElement())
rootMarginBorderPaddingHeight += cb->marginBefore() + cb->marginAfter() + cb->borderAndPaddingLogicalHeight();
skippedAutoHeightContainingBlock = true;
containingBlockChild = cb;
cb = cb->containingBlock();
- cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
}
+ cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
RenderStyle* cbstyle = cb->style();
@@ -2914,17 +2712,6 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
availableHeight = max<LayoutUnit>(0, contentBoxHeight);
}
- } else if (cbstyle->logicalHeight().isViewportPercentage()) {
- LayoutUnit heightWithScrollbar = valueForLength(cbstyle->logicalHeight(), 0, view());
- if (heightWithScrollbar != -1) {
- LayoutUnit contentBoxHeightWithScrollbar = cb->adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
- // We need to adjust for min/max height because this method does not
- // handle the min/max of the current block, its caller does. So the
- // return value from the recursive call will not have been adjusted
- // yet.
- LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
- availableHeight = max<LayoutUnit>(0, contentBoxHeight);
- }
} else if (isOutOfFlowPositionedWithSpecifiedHeight) {
// Don't allow this to affect the block' height() member variable, since this
// can get called while the block is still laying out its kids.
@@ -2932,7 +2719,7 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
cb->computeLogicalHeight(cb->logicalHeight(), 0, computedValues);
availableHeight = computedValues.m_extent - cb->borderAndPaddingLogicalHeight() - cb->scrollbarLogicalHeight();
} else if (cb->isRenderView())
- availableHeight = viewLogicalHeightForPercentages();
+ availableHeight = view()->viewLogicalHeightForPercentages();
if (availableHeight == -1)
return availableHeight;
@@ -2963,7 +2750,7 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUni
return max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
}
-LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) const
+LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(const Length& logicalWidth) const
{
switch (logicalWidth.type()) {
case Fixed:
@@ -2974,11 +2761,6 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) cons
LayoutUnit availableLogicalWidth = 0;
return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
}
- case ViewportPercentageWidth:
- case ViewportPercentageHeight:
- case ViewportPercentageMin:
- case ViewportPercentageMax:
- return adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, 0, view()));
case FitContent:
case FillAvailable:
case Percent:
@@ -2994,14 +2776,17 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) cons
return computeIntrinsicLogicalWidthUsing(logicalWidth, cw, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
if (cw > 0 || (!cw && (containerLogicalWidth.isFixed() || containerLogicalWidth.isPercent())))
return adjustContentBoxLogicalWidthForBoxSizing(minimumValueForLength(logicalWidth, cw));
+ return 0;
}
- // fall through
case Intrinsic:
case MinIntrinsic:
case Auto:
- case ExtendToZoom:
case Undefined:
return intrinsicLogicalWidth();
+ case ExtendToZoom:
+ case DeviceWidth:
+ case DeviceHeight:
+ break;
}
ASSERT_NOT_REACHED();
@@ -3020,7 +2805,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutU
return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
}
-LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) const
+LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(const Length& logicalHeight) const
{
switch (logicalHeight.type()) {
case Fixed:
@@ -3029,10 +2814,10 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co
case Calculated:
{
RenderObject* cb = isOutOfFlowPositioned() ? container() : containingBlock();
- while (cb->isAnonymous()) {
+ while (cb->isAnonymous())
cb = cb->containingBlock();
+ if (cb->isRenderBlock())
toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
- }
// FIXME: This calculation is not patched for block-flow yet.
// https://bugs.webkit.org/show_bug.cgi?id=46500
@@ -3072,11 +2857,6 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co
}
return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, availableHeight));
}
- case ViewportPercentageWidth:
- case ViewportPercentageHeight:
- case ViewportPercentageMin:
- case ViewportPercentageMax:
- return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, 0, view()));
case MinContent:
case MaxContent:
case FitContent:
@@ -3135,35 +2915,20 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogi
return availableHeight;
}
-void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const
-{
- if (isTableCell()) {
- // FIXME: Not right if we allow cells to have different directionality than the table. If we do allow this, though,
- // we may just do it with an extra anonymous block inside the cell.
- marginBefore = 0;
- marginAfter = 0;
- return;
- }
-
- // 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();
- marginBefore = minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView);
- marginAfter = minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView);
-}
-
void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock)
{
LayoutUnit marginBefore;
LayoutUnit marginAfter;
- computeBlockDirectionMargins(containingBlock, marginBefore, marginAfter);
+ computeMarginsForDirection(BlockDirection, containingBlock, containingBlockLogicalWidthForContent(), logicalHeight(), marginBefore, marginAfter,
+ style()->marginBeforeUsing(containingBlock->style()),
+ style()->marginAfterUsing(containingBlock->style()));
+ // Note that in this 'positioning phase' of the layout we are using the containing block's writing mode rather than our own when calculating margins.
+ // See http://www.w3.org/TR/2014/CR-css-writing-modes-3-20140320/#orthogonal-flows
containingBlock->setMarginBeforeForChild(this, marginBefore);
containingBlock->setMarginAfterForChild(this, marginAfter);
}
-LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, bool checkForPerpendicularWritingMode) const
+LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
{
if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
return containingBlockLogicalHeightForPositioned(containingBlock, false);
@@ -3177,30 +2942,8 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxMo
}
}
- if (containingBlock->isBox()) {
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (!flowThread)
- return toRenderBox(containingBlock)->clientLogicalWidth();
-
- const RenderBlock* cb = toRenderBlock(containingBlock);
- RenderBoxRegionInfo* boxInfo = 0;
- if (!region) {
- if (containingBlock->isRenderFlowThread() && !checkForPerpendicularWritingMode)
- return toRenderFlowThread(containingBlock)->contentLogicalWidthOfFirstRegion();
- if (isWritingModeRoot()) {
- LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage();
- RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
- if (cbRegion) {
- cbRegion = cb->clampToStartAndEndRegions(cbRegion);
- boxInfo = cb->renderBoxRegionInfo(cbRegion);
- }
- }
- } else if (region && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
- RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
- boxInfo = cb->renderBoxRegionInfo(containingBlockRegion);
- }
- return (boxInfo) ? max<LayoutUnit>(0, cb->clientLogicalWidth() - (cb->logicalWidth() - boxInfo->logicalWidth())) : cb->clientLogicalWidth();
- }
+ if (containingBlock->isBox())
+ return toRenderBox(containingBlock)->clientLogicalWidth();
ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
@@ -3228,7 +2971,7 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxMo
LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
{
if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
- return containingBlockLogicalWidthForPositioned(containingBlock, 0, false);
+ return containingBlockLogicalWidthForPositioned(containingBlock, false);
// Use viewport as container for top-level fixed-position elements.
if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
@@ -3240,12 +2983,9 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxM
}
if (containingBlock->isBox()) {
- const RenderBlock* cb = toRenderBlock(containingBlock);
- LayoutUnit result = cb->clientLogicalHeight();
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && containingBlock->isRenderFlowThread() && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode())
- return toRenderFlowThread(containingBlock)->contentLogicalHeightOfFirstRegion();
- return result;
+ const RenderBlock* cb = containingBlock->isRenderBlock() ?
+ toRenderBlock(containingBlock) : containingBlock->containingBlock();
+ return cb->clientLogicalHeight();
}
ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
@@ -3268,7 +3008,7 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxM
return heightResult;
}
-static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region)
+static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
{
if (!logicalLeft.isAuto() || !logicalRight.isAuto())
return;
@@ -3281,13 +3021,6 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh
staticPosition += toRenderBox(curr)->logicalLeft();
if (toRenderBox(curr)->isRelPositioned())
staticPosition += toRenderBox(curr)->relativePositionOffset().width();
- if (region && curr->isRenderBlock()) {
- const RenderBlock* cb = toRenderBlock(curr);
- region = cb->clampToStartAndEndRegions(region);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region);
- if (boxInfo)
- staticPosition += boxInfo->logicalLeft();
- }
} else if (curr->isInline()) {
if (curr->isRelPositioned()) {
if (!curr->style()->logicalLeft().isAuto())
@@ -3310,17 +3043,6 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh
}
if (curr == enclosingBox)
staticPosition -= enclosingBox->logicalWidth();
- if (region && curr->isRenderBlock()) {
- const RenderBlock* cb = toRenderBlock(curr);
- region = cb->clampToStartAndEndRegions(region);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region);
- if (boxInfo) {
- if (curr != containerBlock)
- staticPosition -= cb->logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth());
- if (curr == enclosingBox)
- staticPosition += enclosingBox->logicalWidth() - boxInfo->logicalWidth();
- }
- }
} else if (curr->isInline()) {
if (curr->isRelPositioned()) {
if (!curr->style()->logicalLeft().isAuto())
@@ -3336,11 +3058,9 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh
}
}
-void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues, RenderRegion* region) const
+void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues) const
{
if (isReplaced()) {
- // FIXME: Positioned replaced elements inside a flow thread are not working properly
- // with variable width regions (see https://bugs.webkit.org/show_bug.cgi?id=69896 ).
computePositionedLogicalWidthReplaced(computedValues);
return;
}
@@ -3365,7 +3085,7 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu
// relative positioned inline.
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
- const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region);
+ const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
// Use the container block's direction except when calculating the static distance
// This conforms with the reference results for abspos-replaced-width-margin-000.htm
@@ -3406,7 +3126,7 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu
// see FIXME 1
// Calculate the static distance if needed.
- computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
+ computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth);
// Calculate constraint equation values for 'width' case.
computePositionedLogicalWidthUsing(style()->logicalWidth(), containerBlock, containerDirection,
@@ -3449,25 +3169,6 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu
}
computedValues.m_extent += bordersPlusPadding;
-
- // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
- // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
- ASSERT(containerBlock->canHaveBoxInfoInRegion());
- LayoutUnit logicalLeftPos = computedValues.m_position;
- const RenderBlock* cb = toRenderBlock(containerBlock);
- LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage();
- RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
- if (cbRegion) {
- cbRegion = cb->clampToStartAndEndRegions(cbRegion);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion);
- if (boxInfo) {
- logicalLeftPos += boxInfo->logicalLeft();
- computedValues.m_position = logicalLeftPos;
- }
- }
- }
}
static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
@@ -3477,8 +3178,9 @@ static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const
if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
- } else
+ } else {
logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
+ }
}
void RenderBox::shrinkToFitWidth(const LayoutUnit availableSpace, const LayoutUnit logicalLeftValue, const LayoutUnit bordersPlusPadding, LogicalExtentComputedValues& computedValues) const
@@ -3492,8 +3194,8 @@ void RenderBox::shrinkToFitWidth(const LayoutUnit availableSpace, const LayoutUn
void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
- Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
- LogicalExtentComputedValues& computedValues) const
+ const Length& logicalLeft, const Length& logicalRight, const Length& marginLogicalLeft,
+ const Length& marginLogicalRight, LogicalExtentComputedValues& computedValues) const
{
if (logicalWidth.isIntrinsic())
logicalWidth = Length(computeIntrinsicLogicalWidthUsing(logicalWidth, containerLogicalWidth, bordersPlusPadding) - bordersPlusPadding, Fixed);
@@ -3504,12 +3206,11 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
LayoutUnit logicalLeftValue = 0;
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
bool logicalLeftIsAuto = logicalLeft.isAuto();
bool logicalRightIsAuto = logicalRight.isAuto();
- RenderView* renderView = view();
LayoutUnit& marginLogicalLeftValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
LayoutUnit& marginLogicalRightValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
@@ -3528,10 +3229,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 = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth));
- const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth) + bordersPlusPadding);
// Margins are now the only unknown
if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
@@ -3552,16 +3253,16 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
}
} else if (marginLogicalLeft.isAuto()) {
// Solve for left margin
- marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+ marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
} else if (marginLogicalRight.isAuto()) {
// Solve for right margin
- marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+ marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
} else {
// Over-constrained, solve for left if direction is RTL
- marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+ marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
// Use the containing block's direction rather than the parent block's
// per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
@@ -3611,8 +3312,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 = minimumValueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+ marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerRelativeLogicalWidth);
const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
@@ -3620,7 +3321,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 = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// FIXME: would it be better to have shrink-to-fit in one step?
LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
@@ -3630,24 +3331,24 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue);
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 3: (use shrink-to-fit for width, and no need solve of right)
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
} else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 4: (solve for left)
- computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
- logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView));
+ computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth));
+ logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth));
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 5: (solve for width)
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
if (autoWidthShouldFitContent())
shrinkToFitWidth(availableSpace, logicalLeftValue, bordersPlusPadding, computedValues);
else
- computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
+ computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth));
} else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 6: (no need solve for right)
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth));
}
}
@@ -3779,25 +3480,6 @@ void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& comp
// Set final height value.
computedValues.m_extent += bordersPlusPadding;
-
- // Adjust logicalTop if we need to for perpendicular writing modes in regions.
- // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
- ASSERT(containerBlock->canHaveBoxInfoInRegion());
- LayoutUnit logicalTopPos = computedValues.m_position;
- const RenderBlock* cb = toRenderBlock(containerBlock);
- LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
- RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
- if (cbRegion) {
- cbRegion = cb->clampToStartAndEndRegions(cbRegion);
- RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion);
- if (boxInfo) {
- logicalTopPos += boxInfo->logicalLeft();
- computedValues.m_position = logicalTopPos;
- }
- }
- }
}
static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight)
@@ -3824,8 +3506,8 @@ static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const R
void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, LayoutUnit logicalHeight,
- Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
- LogicalExtentComputedValues& computedValues) const
+ const Length& logicalTop, const Length& logicalBottom, const Length& marginBefore,
+ const Length& marginAfter, LogicalExtentComputedValues& computedValues) const
{
// 'top' and 'bottom' cannot both be 'auto' because 'top would of been
// converted to the static position in computePositionedLogicalHeight()
@@ -3834,14 +3516,13 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
LayoutUnit logicalHeightValue;
LayoutUnit contentLogicalHeight = logicalHeight - bordersPlusPadding;
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
LayoutUnit logicalTopValue = 0;
bool logicalHeightIsAuto = logicalHeightLength.isAuto();
bool logicalTopIsAuto = logicalTop.isAuto();
bool logicalBottomIsAuto = logicalBottom.isAuto();
- RenderView* renderView = view();
LayoutUnit resolvedLogicalHeight;
// Height is never unsolved for tables.
@@ -3852,7 +3533,7 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
if (logicalHeightLength.isIntrinsic())
resolvedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(logicalHeightLength, contentLogicalHeight, bordersPlusPadding);
else
- resolvedLogicalHeight = adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
+ resolvedLogicalHeight = adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeightLength, containerLogicalHeight));
}
if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
@@ -3868,9 +3549,9 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
// case because the value is not used for any further calculations.
logicalHeightValue = resolvedLogicalHeight;
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
- const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight) + bordersPlusPadding);
// Margins are now the only unknown
if (marginBefore.isAuto() && marginAfter.isAuto()) {
@@ -3880,16 +3561,16 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; // account for odd valued differences
} else if (marginBefore.isAuto()) {
// Solve for top margin
- computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth);
computedValues.m_margins.m_before = availableSpace - computedValues.m_margins.m_after;
} else if (marginAfter.isAuto()) {
// Solve for bottom margin
- computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth);
computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before;
} else {
// Over-constrained, (no need solve for bottom)
- computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth);
}
} else {
/*--------------------------------------------------------------------*\
@@ -3918,8 +3599,8 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+ computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerRelativeLogicalWidth);
+ computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerRelativeLogicalWidth);
const LayoutUnit availableSpace = containerLogicalHeight - (computedValues.m_margins.m_before + computedValues.m_margins.m_after + bordersPlusPadding);
@@ -3927,23 +3608,23 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 1: (height is content based, solve of top)
logicalHeightValue = contentLogicalHeight;
- logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
+ logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight));
} else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 3: (height is content based, no need solve of bottom)
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
logicalHeightValue = contentLogicalHeight;
} else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 4: (solve of top)
logicalHeightValue = resolvedLogicalHeight;
- logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
+ logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight));
} else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 5: (solve of height)
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)));
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight)));
} else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 6: (no need solve of bottom)
logicalHeightValue = resolvedLogicalHeight;
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
}
}
computedValues.m_extent = logicalHeightValue;
@@ -3966,7 +3647,7 @@ void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValue
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
// To match WinIE, in quirks mode use the parent's 'direction' property
// instead of the the container block's.
@@ -3998,7 +3679,7 @@ void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValue
* else if 'direction' is 'rtl', set 'right' to the static position.
\*-----------------------------------------------------------------------*/
// see FIXME 1
- computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, 0); // FIXME: Pass the region.
+ computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth);
/*-----------------------------------------------------------------------*\
* 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
@@ -4021,14 +3702,13 @@ void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValue
\*-----------------------------------------------------------------------*/
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 = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
if (difference > 0) {
@@ -4051,39 +3731,39 @@ void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValue
* that value.
\*-----------------------------------------------------------------------*/
} else if (logicalLeft.isAuto()) {
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// Solve for 'left'
logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
} else if (logicalRight.isAuto()) {
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
// Solve for 'right'
logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
} else if (marginLogicalLeft.isAuto()) {
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// Solve for 'margin-left'
marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
} else if (marginLogicalRight.isAuto()) {
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
// Solve for 'margin-right'
marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
} else {
// Nothing is 'auto', just calculate the values.
- marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
- marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
- logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
- logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
// 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 = computedValues.m_extent + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
@@ -4135,7 +3815,7 @@ void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValu
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
- const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, false);
+ const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
// Variables to solve.
Length marginBefore = style()->marginBefore();
@@ -4145,7 +3825,6 @@ void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValu
Length logicalTop = style()->logicalTop();
Length logicalBottom = style()->logicalBottom();
- RenderView* renderView = view();
/*-----------------------------------------------------------------------*\
* 1. The used value of 'height' is determined as for inline replaced
@@ -4189,8 +3868,8 @@ void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValu
// 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
// NOTE: This may result in negative values.
@@ -4202,39 +3881,39 @@ void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValu
* for that value.
\*-----------------------------------------------------------------------*/
} else if (logicalTop.isAuto()) {
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
// Solve for 'top'
logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
} else if (logicalBottom.isAuto()) {
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
// 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 = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
// Solve for 'margin-top'
marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
} else if (marginAfter.isAuto()) {
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
// Solve for 'margin-bottom'
marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
} else {
// Nothing is 'auto', just calculate the values.
- marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
- marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
- logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
+ marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
}
@@ -4267,10 +3946,10 @@ LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit
rect.move(LayoutSize(width() - caretWidth, 0));
if (box) {
- RootInlineBox* rootBox = box->root();
- LayoutUnit top = rootBox->lineTop();
+ RootInlineBox& rootBox = box->root();
+ LayoutUnit top = rootBox.lineTop();
rect.setY(top);
- rect.setHeight(rootBox->lineBottom() - top);
+ rect.setHeight(rootBox.lineBottom() - top);
}
// If height of box is smaller than font height, use the latter one,
@@ -4308,7 +3987,8 @@ LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit
PositionWithAffinity RenderBox::positionForPoint(const LayoutPoint& point)
{
// no children...return this render object's element, if there is one, and offset 0
- if (!firstChild())
+ RenderObject* firstChild = slowFirstChild();
+ if (!firstChild)
return createPositionWithAffinity(nonPseudoNode() ? firstPositionInOrBeforeNode(nonPseudoNode()) : Position());
if (isTable() && nonPseudoNode()) {
@@ -4329,8 +4009,8 @@ PositionWithAffinity RenderBox::positionForPoint(const LayoutPoint& point)
if (isTableRow())
adjustedPoint.moveBy(location());
- for (RenderObject* renderObject = firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
- if ((!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isRenderBlockFlow() )
+ for (RenderObject* renderObject = firstChild; renderObject; renderObject = renderObject->nextSibling()) {
+ if ((!renderObject->slowFirstChild() && !renderObject->isInline() && !renderObject->isRenderBlockFlow() )
|| renderObject->style()->visibility() != VISIBLE)
continue;
@@ -4403,9 +4083,18 @@ bool RenderBox::avoidsFloats() const
return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isFlexItemIncludingDeprecated();
}
+void RenderBox::markForPaginationRelayoutIfNeeded(SubtreeLayoutScope& layoutScope)
+{
+ ASSERT(!needsLayout());
+ // If fragmentation height has changed, we need to lay out. No need to enter the renderer if it
+ // is childless, though.
+ if (view()->layoutState()->pageLogicalHeightChanged() && slowFirstChild())
+ layoutScope.setChildNeedsLayout(this);
+}
+
void RenderBox::addVisualEffectOverflow()
{
- if (!style()->boxShadow() && !style()->hasBorderImageOutsets())
+ if (!style()->boxShadow() && !style()->hasBorderImageOutsets() && !style()->hasOutline())
return;
bool isFlipped = style()->isFlippedBlocksWritingMode();
@@ -4444,7 +4133,16 @@ void RenderBox::addVisualEffectOverflow()
overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top()));
}
- // Add in the final overflow with shadows and outsets combined.
+ if (style()->hasOutline()) {
+ LayoutUnit outlineSize = style()->outlineSize();
+
+ overflowMinX = min(overflowMinX, borderBox.x() - outlineSize);
+ overflowMaxX = max(overflowMaxX, borderBox.maxX() + outlineSize);
+ overflowMinY = min(overflowMinY, borderBox.y() - outlineSize);
+ overflowMaxY = max(overflowMaxY, borderBox.maxY() + outlineSize);
+ }
+
+ // Add in the final overflow with shadows, outsets and outline combined.
LayoutRect visualEffectOverflow(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY);
addVisualOverflow(visualEffectOverflow);
}
@@ -4494,13 +4192,6 @@ void RenderBox::addLayoutOverflow(const LayoutRect& rect)
hasTopOverflow = true;
}
- if (hasColumns() && style()->columnProgression() == ReverseColumnProgression) {
- if (isHorizontalWritingMode() ^ !style()->hasInlineColumnAxis())
- hasLeftOverflow = !hasLeftOverflow;
- else
- hasTopOverflow = !hasTopOverflow;
- }
-
if (!hasTopOverflow)
overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
else
@@ -4542,7 +4233,7 @@ void RenderBox::addContentsVisualOverflow(const LayoutRect& rect)
}
if (!m_overflow)
- m_overflow = adoptPtr(new RenderOverflow(clientBoxRect(), borderBoxRect()));
+ m_overflow = adoptPtr(new RenderOverflow(noOverflowRect(), borderBoxRect()));
m_overflow->addContentsVisualOverflow(rect);
}
@@ -4599,7 +4290,7 @@ bool RenderBox::percentageLogicalHeightIsResolvableFromBlock(const RenderBlock*
return percentageLogicalHeightIsResolvableFromBlock(cb->containingBlock(), cb->isOutOfFlowPositioned());
if (cb->isRenderView() || inQuirksMode || isOutOfFlowPositionedWithSpecifiedHeight)
return true;
- if (cb->isRoot() && isOutOfFlowPositioned) {
+ if (cb->isDocumentElement() && isOutOfFlowPositioned) {
// Match the positioned objects behavior, which is that positioned objects will fill their viewport
// always. Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block.
return true;
@@ -4742,14 +4433,16 @@ LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle)
LayoutRect RenderBox::noOverflowRect() const
{
- // Because of the special coodinate system used for overflow rectangles and many other
+ // Because of the special coordinate system used for overflow rectangles and many other
// rectangles (not quite logical, not quite physical), we need to flip the block progression
// coordinate in vertical-rl and horizontal-bt writing modes. In other words, the rectangle
// returned is physical, except for the block direction progression coordinate (y in horizontal
// writing modes, x in vertical writing modes), which is always "logical top". Apart from the
// flipping, this method does the same as clientBoxRect().
- LayoutUnit left = borderLeft() + (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? verticalScrollbarWidth() : 0);
+ const int scrollBarWidth = verticalScrollbarWidth();
+ const int scrollBarHeight = horizontalScrollbarHeight();
+ LayoutUnit left = borderLeft() + (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? scrollBarWidth : 0);
LayoutUnit top = borderTop();
LayoutUnit right = borderRight();
LayoutUnit bottom = borderBottom();
@@ -4765,9 +4458,9 @@ LayoutRect RenderBox::noOverflowRect() const
// clientBoxRect() or paddingBoxRect() in this method, rather than fiddling with the edges on
// our own.
if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
- rect.contract(0, horizontalScrollbarHeight());
+ rect.contract(0, scrollBarHeight);
else
- rect.contract(verticalScrollbarWidth(), horizontalScrollbarHeight());
+ rect.contract(scrollBarWidth, scrollBarHeight);
return rect;
}
@@ -4880,22 +4573,11 @@ LayoutSize RenderBox::topLeftLocationOffset() const
return LayoutSize(rect.x(), rect.y());
}
-bool RenderBox::hasRelativeDimensions() const
-{
- // FIXME: This should probably include viewport percentage heights as well.
- return style()->height().isPercent() || style()->width().isPercent()
- || style()->maxHeight().isPercent() || style()->maxWidth().isPercent()
- || style()->minHeight().isPercent() || style()->minWidth().isPercent();
-}
-
bool RenderBox::hasRelativeLogicalHeight() const
{
return style()->logicalHeight().isPercent()
|| style()->logicalMinHeight().isPercent()
- || style()->logicalMaxHeight().isPercent()
- || style()->logicalHeight().isViewportPercentage()
- || style()->logicalMinHeight().isViewportPercentage()
- || style()->logicalMaxHeight().isViewportPercentage();
+ || style()->logicalMaxHeight().isPercent();
}
static void markBoxForRelayoutAfterSplit(RenderBox* box)
@@ -4909,7 +4591,7 @@ static void markBoxForRelayoutAfterSplit(RenderBox* box)
} else if (box->isTableSection())
toRenderTableSection(box)->setNeedsCellRecalc();
- box->setNeedsLayoutAndPrefWidthsRecalc();
+ box->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild)
@@ -4918,7 +4600,7 @@ RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChil
while (beforeChild->parent() != this) {
RenderBox* boxToSplit = toRenderBox(beforeChild->parent());
- if (boxToSplit->firstChild() != beforeChild && boxToSplit->isAnonymous()) {
+ if (boxToSplit->slowFirstChild() != beforeChild && boxToSplit->isAnonymous()) {
didSplitParentAnonymousBoxes = true;
// We have to split the parent box into two boxes and move children
@@ -4928,7 +4610,7 @@ RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChil
RenderBox* parentBox = toRenderBox(boxToSplit->parent());
// We need to invalidate the |parentBox| before inserting the new node
// so that the table repainting logic knows the structure is dirty.
- // See for example RenderTableCell:clippedOverflowRectForRepaint.
+ // See for example RenderTableCell:clippedOverflowRectForPaintInvalidation.
markBoxForRelayoutAfterSplit(parentBox);
parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling());
boxToSplit->moveChildrenTo(postBox, beforeChild, 0, true);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBox.h b/chromium/third_party/WebKit/Source/core/rendering/RenderBox.h
index 350b640d75c..c9d967df7a5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBox.h
@@ -23,6 +23,7 @@
#ifndef RenderBox_h
#define RenderBox_h
+#include "core/animation/ActiveAnimations.h"
#include "core/rendering/RenderBoxModelObject.h"
#include "core/rendering/RenderOverflow.h"
#include "core/rendering/shapes/ShapeOutsideInfo.h"
@@ -30,13 +31,12 @@
namespace WebCore {
-class RenderBoxRegionInfo;
-class RenderRegion;
struct PaintInfo;
enum SizeType { MainOrPreferredSize, MinSize, MaxSize };
enum AvailableLogicalHeightType { ExcludeMarginBorderPadding, IncludeMarginBorderPadding };
enum OverlayScrollbarSizeRelevancy { IgnoreOverlayScrollbarSize, IncludeOverlayScrollbarSize };
+enum MarginDirection { BlockDirection, InlineDirection };
enum ShouldComputePreferred { ComputeActual, ComputePreferred };
@@ -47,14 +47,39 @@ enum ScrollOffsetClamping {
ScrollOffsetClamped
};
+struct RenderBoxRareData {
+ WTF_MAKE_NONCOPYABLE(RenderBoxRareData); WTF_MAKE_FAST_ALLOCATED;
+public:
+ RenderBoxRareData()
+ : m_inlineBoxWrapper(0)
+ , m_overrideLogicalContentHeight(-1)
+ , m_overrideLogicalContentWidth(-1)
+ {
+ }
+
+ // For inline replaced elements, the inline box that owns us.
+ InlineBox* m_inlineBoxWrapper;
+
+ LayoutUnit m_overrideLogicalContentHeight;
+ LayoutUnit m_overrideLogicalContentWidth;
+};
+
+
class RenderBox : public RenderBoxModelObject {
public:
explicit RenderBox(ContainerNode*);
- virtual ~RenderBox();
// hasAutoZIndex only returns true if the element is positioned or a flex-item since
// position:static elements that are not flex-items get their z-index coerced to auto.
- virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || createsGroup() || hasClipPath() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns() || !style()->hasAutoZIndex(); }
+ virtual LayerType layerTypeRequired() const OVERRIDE
+ {
+ if (isPositioned() || createsGroup() || hasClipPath() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns() || !style()->hasAutoZIndex() || style()->shouldCompositeForCurrentAnimations())
+ return NormalLayer;
+ if (hasOverflowClip())
+ return OverflowClipLayer;
+
+ return NoLayer;
+ }
virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const OVERRIDE;
@@ -87,7 +112,7 @@ public:
LayoutUnit logicalWidth() const { return style()->isHorizontalWritingMode() ? width() : height(); }
LayoutUnit logicalHeight() const { return style()->isHorizontalWritingMode() ? height() : width(); }
- LayoutUnit constrainLogicalWidthInRegionByMinMax(LayoutUnit, LayoutUnit, RenderBlock*, RenderRegion* = 0) const;
+ LayoutUnit constrainLogicalWidthByMinMax(LayoutUnit, LayoutUnit, RenderBlock*) const;
LayoutUnit constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const;
LayoutUnit constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const;
@@ -167,8 +192,6 @@ public:
// 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(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap*) const OVERRIDE FINAL;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
// Use this with caution! No type checking is done!
@@ -207,8 +230,9 @@ public:
void addOverflowFromChild(RenderBox* child) { addOverflowFromChild(child, child->locationOffset()); }
void addOverflowFromChild(RenderBox* child, const LayoutSize& delta);
void clearLayoutOverflow();
+ void clearAllOverflows() { m_overflow.clear(); }
- void updateLayerTransform();
+ void updateLayerTransformAfterLayout();
LayoutUnit contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
LayoutUnit contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
@@ -217,18 +241,15 @@ public:
// 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).
- virtual LayoutUnit offsetWidth() const { return width(); }
- virtual LayoutUnit offsetHeight() const { return height(); }
+ virtual LayoutUnit offsetWidth() const OVERRIDE { return width(); }
+ virtual LayoutUnit offsetHeight() const OVERRIDE { return height(); }
virtual int pixelSnappedOffsetWidth() const OVERRIDE FINAL;
virtual int pixelSnappedOffsetHeight() const OVERRIDE FINAL;
- bool canDetermineWidthWithoutLayout() const;
- LayoutUnit fixedOffsetWidth() const;
-
// More IE extensions. clientWidth and clientHeight represent the interior of an object
// excluding border and scrollbar. clientLeft/Top are just the borderLeftWidth and borderTopWidth.
- LayoutUnit clientLeft() const { return borderLeft(); }
+ LayoutUnit clientLeft() const { return borderLeft() + (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? verticalScrollbarWidth() : 0); }
LayoutUnit clientTop() const { return borderTop(); }
LayoutUnit clientWidth() const;
LayoutUnit clientHeight() const;
@@ -245,12 +266,14 @@ public:
// scrollLeft/Top return the current scroll position. These methods are virtual so that objects like
// textareas can scroll shadow content (but pretend that they are the objects that are
// scrolling).
- virtual int scrollLeft() const;
- virtual int scrollTop() const;
- virtual int scrollWidth() const;
- virtual int scrollHeight() const;
- virtual void setScrollLeft(int);
- virtual void setScrollTop(int);
+ virtual LayoutUnit scrollLeft() const;
+ virtual LayoutUnit scrollTop() const;
+ virtual LayoutUnit scrollWidth() const;
+ virtual LayoutUnit scrollHeight() const;
+ int pixelSnappedScrollWidth() const;
+ int pixelSnappedScrollHeight() const;
+ virtual void setScrollLeft(LayoutUnit);
+ virtual void setScrollTop(LayoutUnit);
void scrollToOffset(const IntSize&);
void scrollByRecursively(const IntSize& delta, ScrollOffsetClamping = ScrollOffsetUnclamped);
@@ -304,20 +327,19 @@ public:
virtual LayoutUnit collapsedMarginBefore() const { return marginBefore(); }
virtual LayoutUnit collapsedMarginAfter() const { return marginAfter(); }
- virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
- LayoutRect reflectionBox() const;
int reflectionOffset() const;
// Given a rect in the object's coordinate space, returns the corresponding rect in the reflection.
LayoutRect reflectedRect(const LayoutRect&) const;
- virtual void layout();
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void layout() OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual LayoutUnit minPreferredLogicalWidth() const;
- virtual LayoutUnit maxPreferredLogicalWidth() const;
+ virtual LayoutUnit minPreferredLogicalWidth() const OVERRIDE;
+ virtual LayoutUnit maxPreferredLogicalWidth() const OVERRIDE;
// FIXME: We should rename these back to overrideLogicalHeight/Width and have them store
// the border-box height/width like the regular height/width accessors on RenderBox.
@@ -342,7 +364,7 @@ public:
void clearContainingBlockOverrideSize();
void clearOverrideContainingBlockContentLogicalHeight();
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
+ virtual LayoutSize offsetFromContainer(const RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const OVERRIDE;
LayoutUnit adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit width) const;
LayoutUnit adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const;
@@ -364,17 +386,13 @@ public:
LayoutUnit m_position;
ComputedMarginValues m_margins;
};
- // Resolve auto margins in the inline direction of the containing block so that objects can be pushed to the start, middle or end
+ // Resolve auto margins in the chosen direction of the containing block so that objects can be pushed to the start, middle or end
// of the containing block.
- void computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const;
+ void computeMarginsForDirection(MarginDirection forDirection, const RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd, Length marginStartLength, Length marginStartEnd) const;
// Used to resolve margins in the containing block's block-flow direction.
- void computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const;
void computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock);
- enum RenderBoxRegionInfoFlags { CacheRenderBoxRegionInfo, DoNotCacheRenderBoxRegionInfo };
- LayoutRect borderBoxRectInRegion(RenderRegion*, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
- void clearRenderBoxRegionInfo();
virtual LayoutUnit offsetFromLogicalTopOfFirstPage() const;
void positionLineBox(InlineBox*);
@@ -385,51 +403,50 @@ public:
// For inline replaced elements, this function returns the inline box that owns us. Enables
// the replaced RenderObject to quickly determine what line it is contained on and to easily
// iterate over structures on the line.
- InlineBox* inlineBoxWrapper() const { return m_inlineBoxWrapper; }
+ InlineBox* inlineBoxWrapper() const { return m_rareData ? m_rareData->m_inlineBoxWrapper : 0; }
void setInlineBoxWrapper(InlineBox*);
void deleteLineBoxWrapper();
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
void repaintDuringLayoutIfMoved(const LayoutRect&);
virtual void repaintOverhangingFloats(bool paintAllDescendants);
- virtual LayoutUnit containingBlockLogicalWidthForContent() const;
+ virtual LayoutUnit containingBlockLogicalWidthForContent() const OVERRIDE;
LayoutUnit containingBlockLogicalHeightForContent(AvailableLogicalHeightType) const;
- LayoutUnit containingBlockLogicalWidthForContentInRegion(RenderRegion*) const;
- LayoutUnit containingBlockAvailableLineWidthInRegion(RenderRegion*) const;
+ LayoutUnit containingBlockAvailableLineWidth() const;
LayoutUnit perpendicularContainingBlockLogicalHeight() const;
virtual void updateLogicalWidth();
virtual void updateLogicalHeight();
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const;
- RenderBoxRegionInfo* renderBoxRegionInfo(RenderRegion*, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
- void computeLogicalWidthInRegion(LogicalExtentComputedValues&, RenderRegion* = 0) const;
+ void computeLogicalWidth(LogicalExtentComputedValues&) const;
bool stretchesToViewport() const
{
- return document().inQuirksMode() && style()->logicalHeight().isAuto() && !isFloatingOrOutOfFlowPositioned() && (isRoot() || isBody()) && !document().shouldDisplaySeamlesslyWithParent() && !isInline();
+ return document().inQuirksMode() && style()->logicalHeight().isAuto() && !isFloatingOrOutOfFlowPositioned() && (isDocumentElement() || isBody()) && !isInline();
}
virtual LayoutSize intrinsicSize() const { return LayoutSize(); }
LayoutUnit intrinsicLogicalWidth() const { return style()->isHorizontalWritingMode() ? intrinsicSize().width() : intrinsicSize().height(); }
LayoutUnit intrinsicLogicalHeight() const { return style()->isHorizontalWritingMode() ? intrinsicSize().height() : intrinsicSize().width(); }
+ virtual LayoutUnit intrinsicContentLogicalHeight() const { return m_intrinsicContentLogicalHeight; }
// Whether or not the element shrinks to its intrinsic width (rather than filling the width
// of a containing block). HTML4 buttons, <select>s, <input>s, legends, and floating/compact elements do this.
- bool sizesLogicalWidthToFitContent(SizeType) const;
+ bool sizesLogicalWidthToFitContent(const Length& logicalWidth) const;
- LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb, RenderRegion*) const;
+ LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlockFlow* cb) const;
- LayoutUnit computeLogicalWidthInRegionUsing(SizeType, Length logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*) const;
+ LayoutUnit computeLogicalWidthUsing(SizeType, const Length& logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock) const;
LayoutUnit computeLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const;
LayoutUnit computeContentLogicalHeight(const Length& height, LayoutUnit intrinsicContentHeight) const;
LayoutUnit computeContentAndScrollbarLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const;
- LayoutUnit computeReplacedLogicalWidthUsing(Length width) const;
+ LayoutUnit computeReplacedLogicalWidthUsing(const Length& width) const;
LayoutUnit computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, ShouldComputePreferred = ComputeActual) const;
- LayoutUnit computeReplacedLogicalHeightUsing(Length height) const;
+ LayoutUnit computeReplacedLogicalHeightUsing(const Length& height) const;
LayoutUnit computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const;
virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const;
@@ -452,7 +469,7 @@ public:
int horizontalScrollbarHeight() const;
int instrinsicScrollbarLogicalWidth() const;
int scrollbarLogicalHeight() const { return style()->isHorizontalWritingMode() ? horizontalScrollbarHeight() : verticalScrollbarWidth(); }
- virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1);
+ virtual bool scroll(ScrollDirection, ScrollGranularity, float delta = 1);
bool canBeScrolledAndHasScrollableArea() const;
virtual bool canBeProgramaticallyScrolled() const;
virtual void autoscroll(const IntPoint&);
@@ -467,8 +484,8 @@ public:
bool hasAutoHorizontalScrollbar() const { return hasOverflowClip() && (style()->overflowX() == OAUTO || style()->overflowX() == OOVERLAY); }
bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
- bool hasScrollableOverflowX() const { return scrollsOverflowX() && scrollWidth() != clientWidth(); }
- bool hasScrollableOverflowY() const { return scrollsOverflowY() && scrollHeight() != clientHeight(); }
+ bool hasScrollableOverflowX() const { return scrollsOverflowX() && pixelSnappedScrollWidth() != pixelSnappedClientWidth(); }
+ bool hasScrollableOverflowY() const { return scrollsOverflowY() && pixelSnappedScrollHeight() != pixelSnappedClientHeight(); }
virtual bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || hasAutoHorizontalScrollbar()); }
virtual bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || hasAutoVerticalScrollbar()); }
bool usesCompositedScrolling() const;
@@ -480,10 +497,10 @@ public:
bool hasUnsplittableScrollingOverflow() const;
bool isUnsplittableForPagination() const;
- virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
+ virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) OVERRIDE;
- virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
- LayoutRect clipRect(const LayoutPoint& location, RenderRegion*);
+ virtual LayoutRect overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
+ LayoutRect clipRect(const LayoutPoint& location);
virtual bool hasControlClip() const { return false; }
virtual LayoutRect controlClipRect(const LayoutPoint&) const { return LayoutRect(); }
bool pushContentsClip(PaintInfo&, const LayoutPoint& accumulatedOffset, ContentsClipBehavior);
@@ -493,7 +510,7 @@ public:
virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
virtual void paintMask(PaintInfo&, const LayoutPoint&);
virtual void paintClippingMask(PaintInfo&, const LayoutPoint&);
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
// Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted
// that just updates the object's position. If the size does change, the object remains dirty.
@@ -508,8 +525,6 @@ public:
return true;
}
- LayoutRect maskClipRect();
-
virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
void removeFloatingOrPositionedChildFromBlockLists();
@@ -522,14 +537,14 @@ public:
bool shrinkToAvoidFloats() const;
virtual bool avoidsFloats() const;
- virtual void markForPaginationRelayoutIfNeeded(SubtreeLayoutScope&) { }
+ virtual void markForPaginationRelayoutIfNeeded(SubtreeLayoutScope&);
bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); }
bool isDeprecatedFlexItem() const { return !isInline() && !isFloatingOrOutOfFlowPositioned() && parent() && parent()->isDeprecatedFlexibleBox(); }
bool isFlexItemIncludingDeprecated() const { return !isInline() && !isFloatingOrOutOfFlowPositioned() && parent() && parent()->isFlexibleBoxIncludingDeprecated(); }
- virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+ virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual LayoutUnit offsetLeft() const OVERRIDE;
@@ -557,13 +572,12 @@ public:
bool hasVisualOverflow() const { return m_overflow && !borderBoxRect().contains(m_overflow->visualOverflowRect()); }
virtual bool needsPreferredWidthsRecalculation() const;
- virtual void computeIntrinsicRatioInformation(FloatSize& /* intrinsicSize */, double& /* intrinsicRatio */, bool& /* isPercentageIntrinsicSize */) const { }
+ virtual void computeIntrinsicRatioInformation(FloatSize& /* intrinsicSize */, double& /* intrinsicRatio */) const { }
IntSize scrolledContentOffset() const;
LayoutSize cachedSizeForOverflowClip() const;
void applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const;
- virtual bool hasRelativeDimensions() const;
virtual bool hasRelativeLogicalHeight() const;
bool hasHorizontalLayoutOverflow() const
@@ -596,7 +610,7 @@ public:
ShapeOutsideInfo* shapeOutsideInfo() const
{
- return ShapeOutsideInfo::isEnabledFor(this) ? ShapeOutsideInfo::info(this) : 0;
+ return ShapeOutsideInfo::isEnabledFor(*this) ? ShapeOutsideInfo::info(*this) : 0;
}
void markShapeOutsideDependentsForLayout()
@@ -605,18 +619,21 @@ public:
removeFloatingOrPositionedChildFromBlockLists();
}
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE;
+
protected:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
virtual void updateFromStyle() OVERRIDE;
- LayoutRect backgroundPaintedExtent() const;
+ // Returns false if it could not cheaply compute the extent (e.g. fixed background), in which case the returned rect may be incorrect.
+ bool getBackgroundPaintedExtent(LayoutRect&) const;
virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const;
virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE;
- virtual void paintBackgroundWithBorderAndBoxShadow(PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance);
+ void paintBackgroundWithBorderAndBoxShadow(PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance);
void paintBackground(const PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, CompositeOperator, RenderObject* backgroundObject);
@@ -628,15 +645,15 @@ protected:
BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
bool backgroundHasOpaqueTopLayer() const;
- void computePositionedLogicalWidth(LogicalExtentComputedValues&, RenderRegion* = 0) const;
+ void computePositionedLogicalWidth(LogicalExtentComputedValues&) const;
- LayoutUnit computeIntrinsicLogicalWidthUsing(Length logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
- LayoutUnit computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const;
+ LayoutUnit computeIntrinsicLogicalWidthUsing(const Length& logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
+ LayoutUnit computeIntrinsicLogicalContentHeightUsing(const Length& logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const;
virtual bool shouldComputeSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
- virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
+ virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
void paintRootBoxFillLayers(const PaintInfo&);
@@ -645,6 +662,8 @@ protected:
virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE;
virtual void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const OVERRIDE;
+ void updateIntrinsicContentLogicalHeight(LayoutUnit intrinsicContentLogicalHeight) const { m_intrinsicContentLogicalHeight = intrinsicContentLogicalHeight; }
+
private:
void updateShapeOutsideInfoAfterStyleChange(const RenderStyle&, const RenderStyle* oldStyle);
void updateGridPositionAfterStyleChange(const RenderStyle*);
@@ -657,20 +676,18 @@ private:
bool skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock) const;
- LayoutUnit containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* = 0, bool checkForPerpendicularWritingMode = true) const;
+ LayoutUnit containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode = true) const;
LayoutUnit containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode = true) const;
- LayoutUnit viewLogicalHeightForPercentages() const;
-
void computePositionedLogicalHeight(LogicalExtentComputedValues&) const;
void computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
- Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
- LogicalExtentComputedValues&) const;
+ const Length& logicalLeft, const Length& logicalRight, const Length& marginLogicalLeft,
+ const Length& marginLogicalRight, LogicalExtentComputedValues&) const;
void computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, LayoutUnit logicalHeight,
- Length logicalTop, Length logicalBottom, Length marginLogicalTop, Length marginLogicalBottom,
- LogicalExtentComputedValues&) const;
+ const Length& logicalTop, const Length& logicalBottom, const Length& marginLogicalTop,
+ const Length& marginLogicalBottom, LogicalExtentComputedValues&) const;
void computePositionedLogicalHeightReplaced(LogicalExtentComputedValues&) const;
void computePositionedLogicalWidthReplaced(LogicalExtentComputedValues&) const;
@@ -687,10 +704,22 @@ private:
virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE FINAL { return frameRect(); }
+ RenderBoxRareData& ensureRareData()
+ {
+ if (!m_rareData)
+ m_rareData = adoptPtr(new RenderBoxRareData());
+ return *m_rareData.get();
+ }
+
private:
// The width/height of the contents + borders + padding. The x/y location is relative to our container (which is not always our parent).
LayoutRect m_frameRect;
+ // Our intrinsic height, used for min-height: min-content etc. Maintained by
+ // updateLogicalHeight. This is logicalHeight() before it is clamped to
+ // min/max.
+ mutable LayoutUnit m_intrinsicContentLogicalHeight;
+
protected:
LayoutBoxExtent m_marginBox;
@@ -700,16 +729,11 @@ protected:
// The preferred logical width of the element if it never breaks any lines at all.
LayoutUnit m_maxPreferredLogicalWidth;
- // Our intrinsic height, used for min-height: min-content etc. Maintained by
- // updateLogicalHeight. This is logicalHeight() before it is clamped to
- // min/max.
- LayoutUnit m_intrinsicContentLogicalHeight;
-
- // For inline replaced elements, the inline box that owns us.
- InlineBox* m_inlineBoxWrapper;
-
// Our overflow information.
OwnPtr<RenderOverflow> m_overflow;
+
+private:
+ OwnPtr<RenderBoxRareData> m_rareData;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderBox, isBox());
@@ -731,27 +755,27 @@ inline RenderBox* RenderBox::parentBox() const
inline RenderBox* RenderBox::firstChildBox() const
{
- return toRenderBox(firstChild());
+ return toRenderBox(slowFirstChild());
}
inline RenderBox* RenderBox::lastChildBox() const
{
- return toRenderBox(lastChild());
+ return toRenderBox(slowLastChild());
}
inline void RenderBox::setInlineBoxWrapper(InlineBox* boxWrapper)
{
if (boxWrapper) {
- ASSERT(!m_inlineBoxWrapper);
+ ASSERT(!inlineBoxWrapper());
// m_inlineBoxWrapper should already be 0. Deleting it is a safeguard against security issues.
// Otherwise, there will two line box wrappers keeping the reference to this renderer, and
// only one will be notified when the renderer is getting destroyed. The second line box wrapper
// will keep a stale reference.
- if (UNLIKELY(m_inlineBoxWrapper != 0))
+ if (UNLIKELY(inlineBoxWrapper() != 0))
deleteLineBoxWrapper();
}
- m_inlineBoxWrapper = boxWrapper;
+ ensureRareData().m_inlineBoxWrapper = boxWrapper;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.cpp
index caef81861c4..5e56efce625 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.cpp
@@ -26,23 +26,23 @@
#include "config.h"
#include "core/rendering/RenderBoxModelObject.h"
-#include "HTMLNames.h"
-#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/HTMLNames.h"
#include "core/frame/Settings.h"
+#include "core/html/HTMLFrameOwnerElement.h"
#include "core/page/scrolling/ScrollingConstraints.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/ImageQualityController.h"
#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerCompositor.h"
-#include "core/rendering/RenderNamedFlowThread.h"
#include "core/rendering/RenderRegion.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "core/rendering/style/ShadowList.h"
#include "platform/geometry/TransformState.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/graphics/Path.h"
#include "wtf/CurrentTime.h"
@@ -100,51 +100,9 @@ bool RenderBoxModelObject::hasAcceleratedCompositing() const
return view()->compositor()->hasAcceleratedCompositing();
}
-bool RenderBoxModelObject::startTransition(double timeOffset, CSSPropertyID propertyId, const RenderStyle* fromStyle, const RenderStyle* toStyle)
-{
- ASSERT(hasLayer());
- ASSERT(compositingState() == PaintsIntoOwnBacking);
- return layer()->compositedLayerMapping()->startTransition(timeOffset, propertyId, fromStyle, toStyle);
-}
-
-void RenderBoxModelObject::transitionPaused(double timeOffset, CSSPropertyID propertyId)
-{
- ASSERT(hasLayer());
- ASSERT(compositingState() == PaintsIntoOwnBacking);
- layer()->compositedLayerMapping()->transitionPaused(timeOffset, propertyId);
-}
-
-void RenderBoxModelObject::transitionFinished(CSSPropertyID propertyId)
-{
- ASSERT(hasLayer());
- ASSERT(compositingState() == PaintsIntoOwnBacking);
- layer()->compositedLayerMapping()->transitionFinished(propertyId);
-}
-
-bool RenderBoxModelObject::startAnimation(double timeOffset, const CSSAnimationData* animation, const KeyframeList& keyframes)
-{
- ASSERT(hasLayer());
- ASSERT(compositingState() == PaintsIntoOwnBacking);
- return layer()->compositedLayerMapping()->startAnimation(timeOffset, animation, keyframes);
-}
-
-void RenderBoxModelObject::animationPaused(double timeOffset, const String& name)
-{
- ASSERT(hasLayer());
- ASSERT(compositingState() == PaintsIntoOwnBacking);
- layer()->compositedLayerMapping()->animationPaused(timeOffset, name);
-}
-
-void RenderBoxModelObject::animationFinished(const String& name)
+InterpolationQuality RenderBoxModelObject::chooseInterpolationQuality(GraphicsContext* context, Image* image, const void* layer, const LayoutSize& size)
{
- ASSERT(hasLayer());
- ASSERT(compositingState() == PaintsIntoOwnBacking);
- layer()->compositedLayerMapping()->animationFinished(name);
-}
-
-bool RenderBoxModelObject::shouldPaintAtLowQuality(GraphicsContext* context, Image* image, const void* layer, const LayoutSize& size)
-{
- return ImageQualityController::imageQualityController()->shouldPaintAtLowQuality(context, this, image, layer, size);
+ return ImageQualityController::imageQualityController()->chooseInterpolationQuality(context, this, image, layer, size);
}
RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node)
@@ -170,12 +128,19 @@ void RenderBoxModelObject::willBeDestroyed()
RenderLayerModelObject::willBeDestroyed();
}
+bool RenderBoxModelObject::calculateHasBoxDecorations() const
+{
+ RenderStyle* styleToUse = style();
+ ASSERT(styleToUse);
+ return hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow();
+}
+
void RenderBoxModelObject::updateFromStyle()
{
RenderLayerModelObject::updateFromStyle();
RenderStyle* styleToUse = style();
- setHasBoxDecorations(hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow());
+ setHasBoxDecorations(calculateHasBoxDecorations());
setInline(styleToUse->isDisplayInlineType());
setPositionState(styleToUse->position());
setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
@@ -222,6 +187,11 @@ bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
if (cb->isTableCell())
return false;
+ // Match RenderBox::availableLogicalHeightUsing by special casing
+ // the render view. The available height is taken from the frame.
+ if (cb->isRenderView())
+ return false;
+
if (!cb->style()->logicalHeight().isAuto() || (!cb->style()->logicalTop().isAuto() && !cb->style()->logicalBottom().isAuto()))
return false;
@@ -240,11 +210,11 @@ LayoutSize RenderBoxModelObject::relativePositionOffset() const
// call availableWidth on our containing block.
if (!style()->left().isAuto()) {
if (!style()->right().isAuto() && !containingBlock->style()->isLeftToRightDirection())
- offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth(), view()));
+ offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth()));
else
- offset.expand(valueForLength(style()->left(), containingBlock->availableWidth(), view()), 0);
+ offset.expand(valueForLength(style()->left(), containingBlock->availableWidth()), 0);
} else if (!style()->right().isAuto()) {
- offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth(), view()), 0);
+ offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth()), 0);
}
// If the containing block of a relatively positioned element does not
@@ -257,13 +227,13 @@ LayoutSize RenderBoxModelObject::relativePositionOffset() const
&& (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
|| !style()->top().isPercent()
|| containingBlock->stretchesToViewport()))
- offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight(), view()));
+ offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight()));
else if (!style()->bottom().isAuto()
&& (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
|| !style()->bottom().isPercent()
|| containingBlock->stretchesToViewport()))
- offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight(), view()));
+ offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight()));
return offset;
}
@@ -276,7 +246,7 @@ LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const L
return LayoutPoint();
LayoutPoint referencePoint = startPoint;
- referencePoint.move(parent()->offsetForColumns(referencePoint));
+ referencePoint.move(parent()->columnOffset(referencePoint));
// 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
@@ -294,24 +264,17 @@ LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const L
else if (isStickyPositioned())
referencePoint.move(stickyPositionOffset());
- // CSS regions specification says that region flows should return the body element as their offsetParent.
- // Since we will bypass the body’s renderer anyway, just end the loop if we encounter a region flow (named flow thread).
- // See http://dev.w3.org/csswg/css-regions/#cssomview-offset-attributes
RenderObject* current;
- for (current = parent(); current != offsetParent && !current->isRenderNamedFlowThread() && current->parent(); current = current->parent()) {
+ for (current = parent(); current != offsetParent && current->parent(); current = current->parent()) {
// FIXME: What are we supposed to do inside SVG content?
if (!isOutOfFlowPositioned()) {
if (current->isBox() && !current->isTableRow())
referencePoint.moveBy(toRenderBox(current)->topLeftLocation());
- referencePoint.move(current->parent()->offsetForColumns(referencePoint));
+ referencePoint.move(current->parent()->columnOffset(referencePoint));
}
}
- // Compute the offset position for elements inside named flow threads for which the offsetParent was the body.
- // See https://code.google.com/p/chromium/issues/detail?id=242168
- if (current->isRenderNamedFlowThread())
- referencePoint = toRenderNamedFlowThread(current)->adjustedPositionRelativeToOffsetParent(*this, referencePoint);
- else if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
+ if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation());
}
}
@@ -319,7 +282,7 @@ LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const L
return referencePoint;
}
-void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewportConstraints& constraints, const FloatRect& viewportRect) const
+void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewportConstraints& constraints, const FloatRect& constrainingRect) const
{
RenderBlock* containingBlock = this->containingBlock();
@@ -328,10 +291,10 @@ void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo
// Sticky positioned element ignore any override logical width on the containing block (as they don't call
// containingBlockLogicalWidthForContent). It's unclear whether this is totally fine.
- LayoutBoxExtent minMargin(minimumValueForLength(style()->marginTop(), maxWidth, view()),
- minimumValueForLength(style()->marginRight(), maxWidth, view()),
- minimumValueForLength(style()->marginBottom(), maxWidth, view()),
- minimumValueForLength(style()->marginLeft(), maxWidth, view()));
+ LayoutBoxExtent minMargin(minimumValueForLength(style()->marginTop(), maxWidth),
+ minimumValueForLength(style()->marginRight(), maxWidth),
+ minimumValueForLength(style()->marginBottom(), maxWidth),
+ minimumValueForLength(style()->marginLeft(), maxWidth));
// Compute the container-relative area within which the sticky element is allowed to move.
containerContentRect.contract(minMargin);
@@ -347,40 +310,81 @@ void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo
// Map to the view to avoid including page scale factor.
FloatRect absContainerFrame = containingBlock->localToContainerQuad(FloatRect(FloatPoint(), containingBlock->size()), view()).boundingBox();
+ if (containingBlock->hasOverflowClip()) {
+ IntSize scrollOffset = containingBlock->layer()->scrollableArea()->adjustedScrollOffset();
+ stickyLocation -= scrollOffset;
+ }
+
// We can't call localToAbsolute on |this| because that will recur. FIXME: For now, assume that |this| is not transformed.
FloatRect absoluteStickyBoxRect(absContainerFrame.location() + stickyLocation, flippedStickyBoxRect.size());
constraints.setAbsoluteStickyBoxRect(absoluteStickyBoxRect);
- if (!style()->left().isAuto()) {
- constraints.setLeftOffset(valueForLength(style()->left(), viewportRect.width(), view()));
+ float horizontalOffsets = constraints.rightOffset() + constraints.leftOffset();
+ bool skipRight = false;
+ bool skipLeft = false;
+ if (!style()->left().isAuto() && !style()->right().isAuto()) {
+ if (horizontalOffsets > containerContentRect.width().toFloat()
+ || horizontalOffsets + containerContentRect.width().toFloat() > constrainingRect.width()) {
+ skipRight = style()->isLeftToRightDirection();
+ skipLeft = !skipRight;
+ }
+ }
+
+ if (!style()->left().isAuto() && !skipLeft) {
+ constraints.setLeftOffset(floatValueForLength(style()->left(), constrainingRect.width()));
constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
}
- if (!style()->right().isAuto()) {
- constraints.setRightOffset(valueForLength(style()->right(), viewportRect.width(), view()));
+ if (!style()->right().isAuto() && !skipRight) {
+ constraints.setRightOffset(floatValueForLength(style()->right(), constrainingRect.width()));
constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight);
}
+ bool skipBottom = false;
+ // FIXME(ostap): Exclude top or bottom edge offset depending on the writing mode when related
+ // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style/2014May/0286.html
+ float verticalOffsets = constraints.topOffset() + constraints.bottomOffset();
+ if (!style()->top().isAuto() && !style()->bottom().isAuto()) {
+ if (verticalOffsets > containerContentRect.height().toFloat()
+ || verticalOffsets + containerContentRect.height().toFloat() > constrainingRect.height()) {
+ skipBottom = true;
+ }
+ }
+
if (!style()->top().isAuto()) {
- constraints.setTopOffset(valueForLength(style()->top(), viewportRect.height(), view()));
+ constraints.setTopOffset(floatValueForLength(style()->top(), constrainingRect.height()));
constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
}
- if (!style()->bottom().isAuto()) {
- constraints.setBottomOffset(valueForLength(style()->bottom(), viewportRect.height(), view()));
+ if (!style()->bottom().isAuto() && !skipBottom) {
+ constraints.setBottomOffset(floatValueForLength(style()->bottom(), constrainingRect.height()));
constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom);
}
}
LayoutSize RenderBoxModelObject::stickyPositionOffset() const
{
- LayoutRect viewportRect = view()->frameView()->viewportConstrainedVisibleContentRect();
+ FloatRect constrainingRect;
+
+ ASSERT(hasLayer());
+ RenderLayer* enclosingClippingLayer = layer()->enclosingOverflowClipLayer(ExcludeSelf);
+ if (enclosingClippingLayer) {
+ RenderBox* enclosingClippingBox = toRenderBox(enclosingClippingLayer->renderer());
+ LayoutRect clipRect = enclosingClippingBox->overflowClipRect(LayoutPoint());
+ clipRect.move(enclosingClippingBox->paddingLeft(), enclosingClippingBox->paddingTop());
+ clipRect.contract(LayoutSize(enclosingClippingBox->paddingLeft() + enclosingClippingBox->paddingRight(),
+ enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom()));
+ constrainingRect = enclosingClippingBox->localToContainerQuad(FloatRect(clipRect), view()).boundingBox();
+ } else {
+ LayoutRect viewportRect = view()->frameView()->viewportConstrainedVisibleContentRect();
+ constrainingRect = viewportRect;
+ }
StickyPositionViewportConstraints constraints;
- computeStickyPositionConstraints(constraints, viewportRect);
+ computeStickyPositionConstraints(constraints, constrainingRect);
// The sticky offset is physical, so we can just return the delta computed in absolute coords (though it may be wrong with transforms).
- return LayoutSize(constraints.computeStickyOffset(viewportRect));
+ return LayoutSize(constraints.computeStickyOffset(constrainingRect));
}
LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const
@@ -418,24 +422,20 @@ int RenderBoxModelObject::pixelSnappedOffsetHeight() const
return snapSizeToPixel(offsetHeight(), offsetTop());
}
-LayoutUnit RenderBoxModelObject::computedCSSPadding(Length padding) const
+LayoutUnit RenderBoxModelObject::computedCSSPadding(const Length& padding) const
{
LayoutUnit w = 0;
- RenderView* renderView = 0;
if (padding.isPercent())
w = containingBlockLogicalWidthForContent();
- else if (padding.isViewportPercentage())
- renderView = view();
- return minimumValueForLength(padding, w, renderView);
+ return minimumValueForLength(padding, w);
}
RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, InlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
- RenderView* renderView = view();
- RoundedRect border = style()->getRoundedBorderFor(borderRect, renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedRect border = style()->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
if (box && (box->nextLineBox() || box->prevLineBox())) {
- RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0, inlineBoxWidth, inlineBoxHeight), renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0, inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightEdge);
border.setRadii(segmentBorder.radii());
}
@@ -474,6 +474,8 @@ void RenderBoxModelObject::clipRoundedInnerRect(GraphicsContext * context, const
}
}
+// FIXME: See crbug.com/382491. The use of getCTM in this context is incorrect because the matrix returned does not
+// include scales applied at raster time, such as the device zoom.
static LayoutRect shrinkRectByOnePixel(GraphicsContext* context, const LayoutRect& rect)
{
LayoutRect shrunkRect = rect;
@@ -510,8 +512,8 @@ static void applyBoxShadowForBackground(GraphicsContext* context, const RenderOb
if (boxShadow.style() != Normal)
continue;
FloatSize shadowOffset(boxShadow.x(), boxShadow.y());
- context->setShadow(shadowOffset, boxShadow.blur(), renderer->resolveColor(boxShadow.color()),
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
+ context->setShadow(shadowOffset, boxShadow.blur(), boxShadow.color(),
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha);
return;
}
}
@@ -529,11 +531,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
bool hasRoundedBorder = style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge);
bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer->attachment() == LocalBackgroundAttachment;
bool isBorderFill = bgLayer->clip() == BorderFillBox;
- bool isRoot = this->isRoot();
+ bool isRoot = this->isDocumentElement();
Color bgColor = color;
StyleImage* bgImage = bgLayer->image();
- bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(this, style()->effectiveZoom());
+ bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(*this, style()->effectiveZoom());
bool forceBackgroundToWhite = false;
if (document().printing()) {
@@ -552,14 +554,14 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
// while rendering.)
if (forceBackgroundToWhite) {
// Note that we can't reuse this variable below because the bgColor might be changed
- bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha();
+ bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.alpha();
if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
bgColor = Color::white;
shouldPaintBackgroundImage = false;
}
}
- bool colorVisible = bgColor.isValid() && bgColor.alpha();
+ bool colorVisible = bgColor.alpha();
// Fast path for drawing simple color backgrounds.
if (!isRoot && !clippedWithLocalScrolling && !shouldPaintBackgroundImage && isBorderFill && !bgLayer->next()) {
@@ -571,7 +573,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
if (boxShadowShouldBeAppliedToBackground)
applyBoxShadowForBackground(context, this);
- if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
+ if (hasRoundedBorder && bleedAvoidance != BackgroundBleedClipBackground) {
RoundedRect border = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge);
if (border.isRenderable())
context->fillRoundedRect(border, bgColor);
@@ -588,8 +590,8 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
return;
}
- // BorderFillBox radius clipping is taken care of by BackgroundBleedUseTransparencyLayer
- bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidance == BackgroundBleedUseTransparencyLayer);
+ // BorderFillBox radius clipping is taken care of by BackgroundBleedClipBackground
+ bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidance == BackgroundBleedClipBackground);
GraphicsContextStateSaver clipToBorderStateSaver(*context, clipToBorderRadius);
if (clipToBorderRadius) {
RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
@@ -614,7 +616,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
if (clippedWithLocalScrolling) {
// Clip to the overflow area.
RenderBox* thisBox = toRenderBox(this);
- context->clip(thisBox->overflowClipRect(rect.location(), paintInfo.renderRegion));
+ context->clip(thisBox->overflowClipRect(rect.location()));
// Adjust the paint rect to reflect a scrolled content box with borders at the ends.
IntSize offset = thisBox->scrolledContentOffset();
@@ -669,10 +671,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
bool isOpaqueRoot = false;
if (isRoot) {
isOpaqueRoot = true;
- if (!bgLayer->next() && !(bgColor.isValid() && bgColor.alpha() == 255) && view()->frameView()) {
+ if (!bgLayer->next() && bgColor.hasAlpha() && view()->frameView()) {
Element* ownerElement = document().ownerElement();
if (ownerElement) {
- if (!ownerElement->hasTagName(frameTag)) {
+ if (!isHTMLFrameElement(*ownerElement)) {
// Locate the <body> element using the DOM. This is easier than trying
// to crawl around a render tree with potential :before/:after content and
// anonymous blocks created by inline <body> tags etc. We can locate the <body>
@@ -698,7 +700,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
if (!bgLayer->next()) {
IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box);
- if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer->hasOpaqueImage(this) || !bgLayer->hasRepeatXY()) {
+ if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer->hasOpaqueImage(this) || !bgLayer->hasRepeatXY() || (isOpaqueRoot && !toRenderBox(this)->height())) {
if (!boxShadowShouldBeAppliedToBackground)
backgroundRect.intersect(paintInfo.rect);
@@ -730,17 +732,20 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
// no progressive loading of the background image
if (shouldPaintBackgroundImage) {
BackgroundImageGeometry geometry;
- calculateBackgroundImageGeometry(bgLayer, scrolledPaintRect, geometry, backgroundObject);
+ calculateBackgroundImageGeometry(paintInfo.paintContainer(), bgLayer, scrolledPaintRect, geometry, backgroundObject);
geometry.clip(paintInfo.rect);
if (!geometry.destRect().isEmpty()) {
CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geometry.tileSize());
- bool useLowQualityScaling = shouldPaintAtLowQuality(context, image.get(), bgLayer, geometry.tileSize());
+ InterpolationQuality interpolationQuality = chooseInterpolationQuality(context, image.get(), bgLayer, geometry.tileSize());
if (bgLayer->maskSourceType() == MaskLuminance)
context->setColorFilter(ColorFilterLuminanceToAlpha);
+ InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality();
+ context->setImageInterpolationQuality(interpolationQuality);
context->drawTiledImage(image.get(), geometry.destRect(), geometry.relativePhase(), geometry.tileSize(),
- compositeOp, useLowQualityScaling, bgLayer->blendMode(), geometry.spaceSize());
+ compositeOp, bgLayer->blendMode(), geometry.spaceSize());
+ context->setImageInterpolationQuality(previousInterpolationQuality);
}
}
@@ -754,11 +759,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
// Now draw the text into the mask. We do this by painting using a special paint phase that signals to
// InlineTextBoxes that they should just add their contents to the clip.
- PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForceBlackText, 0, paintInfo.renderRegion);
+ PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForceBlackText, 0);
context->setCompositeOperation(CompositeSourceOver);
if (box) {
- RootInlineBox* root = box->root();
- box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), root->lineTop(), root->lineBottom());
+ RootInlineBox& root = box->root();
+ box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), root.lineTop(), root.lineBottom());
} else {
LayoutSize localOffset = isBox() ? toRenderBox(this)->locationOffset() : LayoutSize();
paint(info, scrolledPaintRect.location() - localOffset);
@@ -829,18 +834,10 @@ IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* imag
FloatSize intrinsicRatio;
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.
+ ASSERT(!intrinsicWidth.isPercent());
+ ASSERT(!intrinsicHeight.isPercent());
- // 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);
- }
-
- IntSize resolvedSize(intrinsicWidth.isFixed() ? intrinsicWidth.value() : 0, intrinsicHeight.isFixed() ? intrinsicHeight.value() : 0);
+ IntSize resolvedSize(intrinsicWidth.value(), intrinsicHeight.value());
IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0);
if (shouldScaleOrNot == ScaleByEffectiveZoom)
resolvedSize.scale(style()->effectiveZoom());
@@ -880,7 +877,6 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer,
IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positioningAreaSize, ScaleByEffectiveZoom);
imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScaleFactor());
- RenderView* renderView = view();
switch (type) {
case SizeLength: {
LayoutSize tileSize = positioningAreaSize;
@@ -890,13 +886,13 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer,
if (layerWidth.isFixed())
tileSize.setWidth(layerWidth.value());
- else if (layerWidth.isPercent() || layerWidth.isViewportPercentage())
- tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.width(), renderView));
+ else if (layerWidth.isPercent())
+ tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.width()));
if (layerHeight.isFixed())
tileSize.setHeight(layerHeight.value());
- else if (layerHeight.isPercent() || layerHeight.isViewportPercentage())
- tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.height(), renderView));
+ else if (layerHeight.isPercent())
+ tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.height()));
applySubPixelHeuristicForTileSize(tileSize, positioningAreaSize);
@@ -972,7 +968,7 @@ IntPoint RenderBoxModelObject::BackgroundImageGeometry::relativePhase() const
bool RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates() const
{
- if (!isRoot())
+ if (!isDocumentElement())
return false;
if (view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
@@ -996,8 +992,8 @@ static inline int getSpace(int areaSize, int tileSize)
return space;
}
-void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fillLayer, const LayoutRect& paintRect,
- BackgroundImageGeometry& geometry, RenderObject* backgroundObject)
+void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer* fillLayer, const LayoutRect& paintRect,
+ BackgroundImageGeometry& geometry, RenderObject* backgroundObject) const
{
LayoutUnit left = 0;
LayoutUnit top = 0;
@@ -1006,17 +1002,18 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
// Determine the background positioning area and set destRect to the background painting area.
// destRect will be adjusted later if the background is non-repeating.
+ // FIXME: transforms spec says that fixed backgrounds behave like scroll inside transforms.
bool fixedAttachment = fillLayer->attachment() == FixedBackgroundAttachment;
-#if ENABLE(FAST_MOBILE_SCROLLING)
- if (view()->frameView() && view()->frameView()->canBlitOnScroll()) {
+ if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()
+ && view()->frameView()
+ && view()->frameView()->shouldAttemptToScrollUsingFastPath()) {
// As a side effect of an optimization to blit on scroll, we do not honor the CSS
// property "background-attachment: fixed" because it may result in rendering
// artifacts. Note, these artifacts only appear if we are blitting on scroll of
// a page that has fixed background images.
fixedAttachment = false;
}
-#endif
if (!fixedAttachment) {
geometry.setDestRect(snappedPaintRect);
@@ -1040,35 +1037,41 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
// The background of the box generated by the root element covers the entire canvas including
// its margins. Since those were added in already, we have to factor them out when computing
// the background positioning area.
- if (isRoot()) {
+ if (isDocumentElement()) {
positioningAreaSize = pixelSnappedIntSize(toRenderBox(this)->size() - LayoutSize(left + right, top + bottom), toRenderBox(this)->location());
left += marginLeft();
top += marginTop();
} else
positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutSize(left + right, top + bottom), paintRect.location());
} else {
+ geometry.setHasNonLocalGeometry();
+
IntRect viewportRect = pixelSnappedIntRect(viewRect());
if (fixedBackgroundPaintsInLocalCoordinates())
viewportRect.setLocation(IntPoint());
else if (FrameView* frameView = view()->frameView())
viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition()));
+ if (paintContainer) {
+ IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->localToAbsolute(FloatPoint()));
+ viewportRect.moveBy(-absoluteContainerOffset);
+ }
+
geometry.setDestRect(pixelSnappedIntRect(viewportRect));
positioningAreaSize = geometry.destRect().size();
}
- RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
+ const RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
IntSize fillTileSize = calculateFillTileSize(fillLayer, positioningAreaSize);
fillLayer->image()->setContainerSizeForRenderer(clientForBackgroundImage, fillTileSize, style()->effectiveZoom());
geometry.setTileSize(fillTileSize);
EFillRepeat backgroundRepeatX = fillLayer->repeatX();
EFillRepeat backgroundRepeatY = fillLayer->repeatY();
- RenderView* renderView = view();
int availableWidth = positioningAreaSize.width() - geometry.tileSize().width();
int availableHeight = positioningAreaSize.height() - geometry.tileSize().height();
- LayoutUnit computedXPosition = minimumValueForLength(fillLayer->xPosition(), availableWidth, renderView, true);
+ LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer->xPosition(), availableWidth);
if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fillTileSize.width() > 0) {
long nrTiles = max(1l, lroundf((float)positioningAreaSize.width() / fillTileSize.width()));
@@ -1082,7 +1085,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
geometry.setSpaceSize(IntSize());
}
- LayoutUnit computedYPosition = minimumValueForLength(fillLayer->yPosition(), availableHeight, renderView, true);
+ LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer->yPosition(), availableHeight);
if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > 0 && fillTileSize.height() > 0) {
long nrTiles = max(1l, lroundf((float)positioningAreaSize.height() / fillTileSize.height()));
@@ -1104,7 +1107,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
int actualWidth = geometry.tileSize().width() + space;
if (space >= 0) {
- computedXPosition = minimumValueForLength(Length(), availableWidth, renderView, true);
+ computedXPosition = roundedMinimumValueForLength(Length(), availableWidth);
geometry.setSpaceSize(IntSize(space, 0));
geometry.setPhaseX(actualWidth ? actualWidth - roundToInt(computedXPosition + left) % actualWidth : 0);
} else {
@@ -1125,7 +1128,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
int actualHeight = geometry.tileSize().height() + space;
if (space >= 0) {
- computedYPosition = minimumValueForLength(Length(), availableHeight, renderView, true);
+ computedYPosition = roundedMinimumValueForLength(Length(), availableHeight);
geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), space));
geometry.setPhaseY(actualHeight ? actualHeight - roundToInt(computedYPosition + top) % actualHeight : 0);
} else {
@@ -1145,13 +1148,13 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
geometry.setDestOrigin(geometry.destRect().location());
}
-static LayoutUnit computeBorderImageSide(const BorderImageLength& borderSlice, LayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent, RenderView* renderView)
+static LayoutUnit computeBorderImageSide(const BorderImageLength& borderSlice, LayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent)
{
if (borderSlice.isNumber())
return borderSlice.number() * borderSide;
if (borderSlice.length().isAuto())
return imageSide;
- return valueForLength(borderSlice.length(), boxExtent, renderView);
+ return valueForLength(borderSlice.length(), boxExtent);
}
bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, const LayoutRect& rect, const RenderStyle* style,
@@ -1164,7 +1167,7 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
if (!styleImage->isLoaded())
return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
- if (!styleImage->canRender(this, style->effectiveZoom()))
+ if (!styleImage->canRender(*this, style->effectiveZoom()))
return false;
// FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function
@@ -1180,21 +1183,20 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
int imageWidth = imageSize.width();
int imageHeight = imageSize.height();
- RenderView* renderView = view();
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;
+ int topSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().top(), imageHeight)) * imageScaleFactor;
+ int rightSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().right(), imageWidth)) * imageScaleFactor;
+ int bottomSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().bottom(), imageHeight)) * imageScaleFactor;
+ int leftSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().left(), imageWidth)) * imageScaleFactor;
ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
ENinePieceImageRule vRule = ninePieceImage.verticalRule();
- int topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height(), renderView);
- int rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width(), renderView);
- int bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height(), renderView);
- int leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width(), renderView);
+ int topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height());
+ int rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width());
+ int bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height());
+ int leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width());
// 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
@@ -1744,14 +1746,18 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
BorderEdge edges[4];
getBorderEdgeInfo(edges, style, includeLogicalLeftEdge, includeLogicalRightEdge);
- RoundedRect outerBorder = style->getRoundedBorderFor(rect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedRect outerBorder = style->getRoundedBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge);
RoundedRect innerBorder = style->getRoundedInnerBorderFor(borderInnerRectAdjustedForBleedAvoidance(graphicsContext, rect, bleedAvoidance), includeLogicalLeftEdge, includeLogicalRightEdge);
+ if (outerBorder.rect().isEmpty())
+ return;
+
bool haveAlphaColor = false;
bool haveAllSolidEdges = true;
bool haveAllDoubleEdges = true;
int numEdgesVisible = 4;
bool allEdgesShareColor = true;
+ bool allEdgesShareWidth = true;
int firstVisibleEdge = -1;
BorderEdgeFlags edgesToDraw = 0;
@@ -1764,18 +1770,23 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
if (currEdge.presentButInvisible()) {
--numEdgesVisible;
allEdgesShareColor = false;
+ allEdgesShareWidth = false;
continue;
}
- if (!currEdge.width) {
+ if (!currEdge.shouldRender()) {
--numEdgesVisible;
continue;
}
- if (firstVisibleEdge == -1)
+ if (firstVisibleEdge == -1) {
firstVisibleEdge = i;
- else if (currEdge.color != edges[firstVisibleEdge].color)
- allEdgesShareColor = false;
+ } else {
+ if (currEdge.color != edges[firstVisibleEdge].color)
+ allEdgesShareColor = false;
+ if (currEdge.width != edges[firstVisibleEdge].width)
+ allEdgesShareWidth = false;
+ }
if (currEdge.color.hasAlpha())
haveAlphaColor = true;
@@ -1795,11 +1806,19 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
// isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787
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)
+ if (outerBorder.isRounded() && allEdgesShareWidth) {
+
+ // Very fast path for single stroked round rect with circular corners
+
+ graphicsContext->fillBetweenRoundedRects(outerBorder, innerBorder, edges[firstVisibleEdge].color);
+ return;
+ }
+ if (outerBorder.isRounded() && bleedAvoidance != BackgroundBleedClipBackground)
path.addRoundedRect(outerBorder);
else
path.addRect(outerBorder.rect());
@@ -1832,12 +1851,12 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
innerThird.setRect(innerThirdRect);
outerThird.setRect(outerThirdRect);
- if (outerThird.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+ if (outerThird.isRounded() && bleedAvoidance != BackgroundBleedClipBackground)
path.addRoundedRect(outerThird);
else
path.addRect(outerThird.rect());
- if (innerThird.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+ if (innerThird.isRounded() && bleedAvoidance != BackgroundBleedClipBackground)
path.addRoundedRect(innerThird);
else
path.addRect(innerThird.rect());
@@ -1876,7 +1895,7 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
GraphicsContextStateSaver stateSaver(*graphicsContext, clipToOuterBorder);
if (clipToOuterBorder) {
// Clip to the inner and outer radii rects.
- if (bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+ if (bleedAvoidance != BackgroundBleedClipBackground)
graphicsContext->clipRoundedRect(outerBorder);
// isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787
// The inside will be clipped out later (in clipBorderSideForComplexInnerPath)
@@ -1982,7 +2001,7 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext,
{
GraphicsContextStateSaver stateSaver(*graphicsContext);
LayoutRect outerRect = borderRect;
- if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
+ if (bleedAvoidance == BackgroundBleedClipBackground) {
outerRect.inflate(1);
++outerBorderTopWidth;
++outerBorderBottomWidth;
@@ -2054,7 +2073,7 @@ void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContex
const LayoutRect& outerRect = outerBorder.rect();
const LayoutRect& innerRect = innerBorder.rect();
- FloatPoint centerPoint(innerRect.location().x() + static_cast<float>(innerRect.width()) / 2, innerRect.location().y() + static_cast<float>(innerRect.height()) / 2);
+ FloatPoint centerPoint(innerRect.location().x().toFloat() + innerRect.width().toFloat() / 2, innerRect.location().y().toFloat() + innerRect.height().toFloat() / 2);
// For each side, create a quad that encompasses all parts of that side that may draw,
// including areas inside the innerBorder.
@@ -2446,7 +2465,7 @@ bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedA
return false;
Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
- if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
+ if (backgroundColor.hasAlpha())
return false;
const FillLayer* lastBackgroundLayer = style()->backgroundLayers();
@@ -2476,11 +2495,11 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
return;
RoundedRect border = (shadowStyle == Inset) ? s->getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge)
- : s->getRoundedBorderFor(paintRect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
+ : s->getRoundedBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge);
bool hasBorderRadius = s->hasBorderRadius();
bool isHorizontal = s->isHorizontalWritingMode();
- bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255;
+ bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255;
GraphicsContextStateSaver stateSaver(*context, false);
@@ -2490,22 +2509,22 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
if (shadow.style() != shadowStyle)
continue;
- IntSize shadowOffset(shadow.x(), shadow.y());
- int shadowBlur = shadow.blur();
- int shadowSpread = shadow.spread();
+ FloatSize shadowOffset(shadow.x(), shadow.y());
+ float shadowBlur = shadow.blur();
+ float shadowSpread = shadow.spread();
if (shadowOffset.isZero() && !shadowBlur && !shadowSpread)
continue;
- const Color& shadowColor = resolveColor(shadow.color());
+ const Color& shadowColor = shadow.color();
if (shadow.style() == Normal) {
- RoundedRect fillRect = border;
+ FloatRect fillRect = border.rect();
fillRect.inflate(shadowSpread);
if (fillRect.isEmpty())
continue;
- IntRect shadowRect(border.rect());
+ FloatRect shadowRect(border.rect());
shadowRect.inflate(shadowBlur + shadowSpread);
shadowRect.move(shadowOffset);
@@ -2526,6 +2545,8 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
context->clipOutRoundedRect(rectToClipOut);
}
} else {
+ // This IntRect is correct even with fractional shadows, because it is used for the rectangle
+ // of the box itself, which is always pixel-aligned.
IntRect rectToClipOut = border.rect();
// If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
@@ -2535,6 +2556,8 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
if (hasOpaqueBackground) {
// FIXME: The function to decide on the policy based on the transform should be a named function.
// FIXME: It's not clear if this check is right. What about integral scale factors?
+ // FIXME: See crbug.com/382491. The use of getCTM may also be wrong because it does not include
+ // device zoom applied at raster time.
AffineTransform transform = context->getCTM();
if (transform.a() != 1 || (transform.d() != 1 && transform.d() != -1) || transform.b() || transform.c())
rectToClipOut.inflate(-1);
@@ -2547,26 +2570,31 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
}
// Draw only the shadow.
- DrawLooper drawLooper;
- drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor,
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
- context->setDrawLooper(drawLooper);
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
+ drawLooperBuilder->addShadow(shadowOffset, shadowBlur, shadowColor,
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha);
+ context->setDrawLooper(drawLooperBuilder.release());
if (hasBorderRadius) {
- RoundedRect influenceRect(shadowRect, border.radii());
+ RoundedRect influenceRect(pixelSnappedIntRect(LayoutRect(shadowRect)), border.radii());
influenceRect.expandRadii(2 * shadowBlur + shadowSpread);
if (allCornersClippedOut(influenceRect, info.rect))
- context->fillRect(fillRect.rect(), Color::black);
+ context->fillRect(fillRect, Color::black);
else {
- fillRect.expandRadii(shadowSpread);
- if (!fillRect.isRenderable())
- fillRect.adjustRadii();
- context->fillRoundedRect(fillRect, Color::black);
+ // TODO: support non-integer shadows - crbug.com/334829
+ RoundedRect roundedFillRect = border;
+ roundedFillRect.inflate(shadowSpread);
+
+ roundedFillRect.expandRadii(shadowSpread);
+ if (!roundedFillRect.isRenderable())
+ roundedFillRect.adjustRadii();
+ context->fillRoundedRect(roundedFillRect, Color::black);
}
} else {
- context->fillRect(fillRect.rect(), Color::black);
+ context->fillRect(fillRect, Color::black);
}
} else {
+ // The inset shadow case.
GraphicsContext::Edges clippedEdges = GraphicsContext::NoEdge;
if (!includeLogicalLeftEdge) {
if (isHorizontal)
@@ -2580,7 +2608,8 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
else
clippedEdges |= GraphicsContext::BottomEdge;
}
- context->drawInnerShadow(border, shadowColor, shadowOffset, shadowBlur, shadowSpread, clippedEdges);
+ // TODO: support non-integer shadows - crbug.com/334828
+ context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowOffset), shadowBlur, shadowSpread, clippedEdges);
}
}
}
@@ -2640,7 +2669,7 @@ void RenderBoxModelObject::setFirstLetterRemainingText(RenderTextFragment* remai
LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset)
{
- ASSERT(!firstChild());
+ ASSERT(!slowFirstChild());
// FIXME: This does not take into account either :first-line or :first-letter
// However, as soon as some content is entered, the line boxes will be
@@ -2708,30 +2737,22 @@ bool RenderBoxModelObject::shouldAntialiasLines(GraphicsContext* context)
{
// FIXME: We may want to not antialias when scaled by an integral value,
// and we may want to antialias when translated by a non-integral value.
+ // FIXME: See crbug.com/382491. getCTM does not include scale factors applied at raster time, such
+ // as device zoom.
return !context->getCTM().isIdentityOrTranslationOrFlipped();
}
void RenderBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
{
// We don't expect to be called during layout.
- ASSERT(!view() || !view()->layoutStateEnabled());
+ ASSERT(!view() || !view()->layoutStateCachedOffsetsEnabled());
RenderObject* o = container();
if (!o)
return;
- // The point inside a box that's inside a region has its coordinates relative to the region,
- // not the FlowThread that is its container in the RenderObject tree.
- if (o->isRenderFlowThread() && isRenderBlock()) {
- // FIXME: switch to Box instead of Block when we'll have range information for boxes as well, not just for blocks.
- RenderRegion* startRegion;
- RenderRegion* ignoredEndRegion;
- toRenderFlowThread(o)->getRegionRangeForBox(toRenderBlock(this), startRegion, ignoredEndRegion);
- // If there is no region to use the FlowThread, then there's no region range for the content in that FlowThread.
- // An API like elementFromPoint might crash without this check.
- if (startRegion)
- o = startRegion;
- }
+ if (o->isRenderFlowThread())
+ transformState.move(o->columnOffset(LayoutPoint(transformState.mappedPoint())));
o->mapAbsoluteToLocalPoint(mode, transformState);
@@ -2780,7 +2801,7 @@ const RenderObject* RenderBoxModelObject::pushMappingToContainer(const RenderLay
if (shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
- t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height());
+ t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustmentForSkippedAncestor.height().toFloat());
geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
} else {
containerOffset += adjustmentForSkippedAncestor;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.h b/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.h
index 31b318612b8..f308aec7ca8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderBoxModelObject.h
@@ -24,6 +24,7 @@
#ifndef RenderBoxModelObject_h
#define RenderBoxModelObject_h
+#include "core/animation/ActiveAnimations.h"
#include "core/rendering/RenderLayerModelObject.h"
#include "core/rendering/style/ShadowData.h"
#include "platform/geometry/LayoutRect.h"
@@ -38,20 +39,17 @@ typedef unsigned BorderEdgeFlags;
enum BackgroundBleedAvoidance {
BackgroundBleedNone,
BackgroundBleedShrinkBackground,
- BackgroundBleedUseTransparencyLayer,
+ BackgroundBleedClipBackground,
BackgroundBleedBackgroundOverBorder
};
enum ContentChangeType {
ImageChanged,
- MaskImageChanged,
CanvasChanged,
CanvasPixelsChanged,
- VideoChanged,
- FullScreenChanged
+ CanvasContextChanged
};
-class KeyframeList;
class RenderTextFragment;
class StickyPositionViewportConstraints;
@@ -66,7 +64,7 @@ public:
LayoutSize relativePositionOffset() const;
LayoutSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
- void computeStickyPositionConstraints(StickyPositionViewportConstraints&, const FloatRect& viewportRect) const;
+ void computeStickyPositionConstraints(StickyPositionViewportConstraints&, const FloatRect& constrainingRect) const;
LayoutSize stickyPositionOffset() const;
LayoutSize stickyPositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? stickyPositionOffset() : stickyPositionOffset().transposedSize(); }
@@ -86,8 +84,6 @@ public:
virtual void updateFromStyle() OVERRIDE;
- virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || createsGroup() || hasClipPath() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns(); }
-
// This will work on inlines to return the bounding box of all of the lines' border boxes.
virtual IntRect borderBoundingBox() const = 0;
@@ -121,6 +117,9 @@ public:
virtual int borderStart() const { return style()->borderStartWidth(); }
virtual int borderEnd() const { return style()->borderEndWidth(); }
+ int borderWidth() const { return borderLeft() + borderRight(); }
+ int borderHeight() const { return borderTop() + borderBottom(); }
+
LayoutUnit borderAndPaddingStart() const { return borderStart() + paddingStart(); }
LayoutUnit borderAndPaddingBefore() const { return borderBefore() + paddingBefore(); }
LayoutUnit borderAndPaddingAfter() const { return borderAfter() + paddingAfter(); }
@@ -176,30 +175,22 @@ public:
virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- void highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*);
-
- virtual void setSelectionState(SelectionState s);
-
- bool canHaveBoxInfoInRegion() const { return !isFloating() && !isReplaced() && !isInline() && !hasColumns() && !isTableCell() && isRenderBlock() && !isRenderSVGBlock(); }
+ virtual void setSelectionState(SelectionState) OVERRIDE;
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 CSSAnimationData*, const KeyframeList& keyframes);
- void animationPaused(double timeOffset, const String& name);
- void animationFinished(const String& name);
-
virtual void computeLayerHitTestRects(LayerHitTestRects&) const OVERRIDE;
protected:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
class BackgroundImageGeometry {
public:
+ BackgroundImageGeometry()
+ : m_hasNonLocalGeometry(false)
+ { }
+
IntPoint destOrigin() const { return m_destOrigin; }
void setDestOrigin(const IntPoint& destOrigin)
{
@@ -244,37 +235,43 @@ protected:
void useFixedAttachment(const IntPoint& attachmentPoint);
void clip(const IntRect&);
+
+ void setHasNonLocalGeometry(bool hasNonLocalGeometry = true) { m_hasNonLocalGeometry = hasNonLocalGeometry; }
+ bool hasNonLocalGeometry() const { return m_hasNonLocalGeometry; }
+
private:
IntRect m_destRect;
IntPoint m_destOrigin;
IntPoint m_phase;
IntSize m_tileSize;
IntSize m_repeatSpacing;
+ bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
};
LayoutPoint adjustedPositionRelativeToOffsetParent(const LayoutPoint&) const;
- void calculateBackgroundImageGeometry(const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&, RenderObject* = 0);
+ bool calculateHasBoxDecorations() const;
+ void calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&, RenderObject* = 0) const;
void getBorderEdgeInfo(class BorderEdge[], const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
bool borderObscuresBackground() const;
RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox*, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
LayoutRect borderInnerRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance) const;
- bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const LayoutSize&);
+ InterpolationQuality chooseInterpolationQuality(GraphicsContext*, Image*, const void*, const LayoutSize&);
RenderBoxModelObject* continuation() const;
void setContinuation(RenderBoxModelObject*);
LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset);
- static bool shouldAntialiasLines(GraphicsContext*);
-
static void clipRoundedInnerRect(GraphicsContext*, const LayoutRect&, const RoundedRect& clipRect);
bool hasAutoHeightOrContainingBlockWithAutoHeight() const;
public:
+ static bool shouldAntialiasLines(GraphicsContext*);
+
// For RenderBlocks and RenderInlines with m_style->styleType() == FIRST_LETTER, this tracks their remaining text fragments
RenderTextFragment* firstLetterRemainingText() const;
void setFirstLetterRemainingText(RenderTextFragment*);
@@ -293,7 +290,7 @@ public:
}
void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert = false)
{
- moveChildrenTo(toBoxModelObject, firstChild(), 0, beforeChild, fullRemoveInsert);
+ moveChildrenTo(toBoxModelObject, slowFirstChild(), 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.
@@ -303,17 +300,17 @@ public:
}
void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
+ enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom };
+ IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
+
private:
- LayoutUnit computedCSSPadding(Length) const;
+ LayoutUnit computedCSSPadding(const Length&) const;
virtual bool isBoxModelObject() const OVERRIDE FINAL { return true; }
virtual LayoutRect frameRectForStickyPositioning() const = 0;
IntSize calculateFillTileSize(const FillLayer*, const IntSize& scaledPositioningAreaSize) const;
- enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom };
- IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
-
RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderButton.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderButton.cpp
index ce1bec473ce..9b16c4af8a0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderButton.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderButton.cpp
@@ -63,7 +63,7 @@ void RenderButton::removeChild(RenderObject* oldChild)
m_inner->removeChild(oldChild);
}
-void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
if (m_inner) {
// RenderBlock::setStyle is going to apply a new style to the inner block, which
@@ -71,9 +71,9 @@ void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle* newS
// it right below. Here we change it back to 0 to avoid getting a spurious layout hint
// because of the difference. Same goes for the other properties.
// FIXME: Make this hack unnecessary.
- m_inner->style()->setFlexGrow(newStyle->initialFlexGrow());
- m_inner->style()->setMarginTop(newStyle->initialMargin());
- m_inner->style()->setMarginBottom(newStyle->initialMargin());
+ m_inner->style()->setFlexGrow(newStyle.initialFlexGrow());
+ m_inner->style()->setMarginTop(newStyle.initialMargin());
+ m_inner->style()->setMarginBottom(newStyle.initialMargin());
}
RenderBlock::styleWillChange(diff, newStyle);
}
@@ -97,6 +97,10 @@ void RenderButton::setupInnerStyle(RenderStyle* innerStyle)
innerStyle->setMarginTop(Length());
innerStyle->setMarginBottom(Length());
innerStyle->setFlexDirection(style()->flexDirection());
+ innerStyle->setJustifyContent(style()->justifyContent());
+ innerStyle->setFlexWrap(style()->flexWrap());
+ innerStyle->setAlignItems(style()->alignItems());
+ innerStyle->setAlignContent(style()->alignContent());
}
bool RenderButton::canHaveGeneratedChildren() const
@@ -104,7 +108,7 @@ bool RenderButton::canHaveGeneratedChildren() const
// Input elements can't have generated children, but button elements can. We'll
// write the code assuming any other button types that might emerge in the future
// can also have children.
- return !node()->hasTagName(inputTag);
+ return !isHTMLInputElement(*node());
}
LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderButton.h b/chromium/third_party/WebKit/Source/core/rendering/RenderButton.h
index 33df32be802..8aaed6266c9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderButton.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderButton.h
@@ -21,13 +21,11 @@
#ifndef RenderButton_h
#define RenderButton_h
-#include "HTMLNames.h"
+#include "core/html/HTMLInputElement.h"
#include "core/rendering/RenderFlexibleBox.h"
namespace WebCore {
-class RenderTextFragment;
-
// RenderButtons are just like normal flexboxes except that they will generate an anonymous block child.
// For inputs, they will also generate an anonymous RenderText and keep its style and content up
// to date as the button changes.
@@ -36,15 +34,16 @@ public:
explicit RenderButton(Element*);
virtual ~RenderButton();
- virtual const char* renderName() const { return "RenderButton"; }
- virtual bool isRenderButton() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderButton"; }
+ virtual bool isRenderButton() const OVERRIDE { return true; }
virtual bool canBeSelectionLeaf() const OVERRIDE { return node() && node()->rendererIsEditable(); }
+ virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return true; }
- virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
- virtual void removeChild(RenderObject*);
- virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
- virtual bool createsAnonymousWrapper() const { return true; }
+ virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject*) OVERRIDE;
+ virtual void removeLeftoverAnonymousBlock(RenderBlock*) OVERRIDE { }
+ virtual bool createsAnonymousWrapper() const OVERRIDE { return true; }
void setupInnerStyle(RenderStyle*);
@@ -52,16 +51,16 @@ public:
virtual bool canHaveWhitespaceChildren() const OVERRIDE { return true; }
virtual bool canHaveGeneratedChildren() const OVERRIDE;
- virtual bool hasControlClip() const { return true; }
- virtual LayoutRect controlClipRect(const LayoutPoint&) const;
+ virtual bool hasControlClip() const OVERRIDE { return true; }
+ virtual LayoutRect controlClipRect(const LayoutPoint&) const OVERRIDE;
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode) const OVERRIDE;
private:
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
- virtual bool hasLineIfEmpty() const { return node() && node()->hasTagName(HTMLNames::inputTag); }
+ virtual bool hasLineIfEmpty() const OVERRIDE { return isHTMLInputElement(node()); }
RenderBlock* m_inner;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.cpp
index 75ae66dec91..2e58c5f995b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.cpp
@@ -55,28 +55,31 @@ void RenderCombineText::setTextInternal(PassRefPtr<StringImpl> text)
m_needsFontUpdate = true;
}
-float RenderCombineText::width(unsigned from, unsigned length, const Font& font, float xPosition, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float RenderCombineText::width(unsigned from, unsigned length, const Font& font, float xPosition, TextDirection direction, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
+ if (!length)
+ return 0;
+
if (hasEmptyText())
return 0;
if (m_isCombined)
- return font.size();
+ return font.fontDescription().computedSize();
- return RenderText::width(from, length, font, xPosition, fallbackFonts, glyphOverflow);
+ return RenderText::width(from, length, font, xPosition, direction, fallbackFonts, glyphOverflow);
}
void RenderCombineText::adjustTextOrigin(FloatPoint& textOrigin, const FloatRect& boxRect) const
{
if (m_isCombined)
- textOrigin.move(boxRect.height() / 2 - ceilf(m_combinedTextWidth) / 2, style()->font().pixelSize());
+ textOrigin.move(boxRect.height() / 2 - ceilf(m_combinedTextWidth) / 2, style()->font().fontDescription().computedPixelSize());
}
void RenderCombineText::getStringToRender(int start, StringView& string, int& length) const
{
ASSERT(start >= 0);
if (m_isCombined) {
- string = StringView(originalText());
+ string = StringView(m_renderingText.impl());
length = string.length();
return;
}
@@ -96,7 +99,7 @@ void RenderCombineText::combineText()
if (style()->isHorizontalWritingMode())
return;
- TextRun run = RenderBlockFlow::constructTextRun(this, originalFont(), this, style());
+ TextRun run = RenderBlockFlow::constructTextRun(this, originalFont(), this, style(), style()->direction());
FontDescription description = originalFont().fontDescription();
float emWidth = description.computedSize() * textCombineMargin;
bool shouldUpdateFont = false;
@@ -114,7 +117,7 @@ void RenderCombineText::combineText()
static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth };
for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) {
description.setWidthVariant(widthVariants[i]);
- Font compressedFont = Font(description, style()->font().letterSpacing(), style()->font().wordSpacing());
+ Font compressedFont = Font(description);
compressedFont.update(fontSelector);
float runWidth = compressedFont.width(run);
if (runWidth <= emWidth) {
@@ -136,6 +139,7 @@ void RenderCombineText::combineText()
if (m_isCombined) {
DEFINE_STATIC_LOCAL(String, objectReplacementCharacterString, (&objectReplacementCharacter, 1));
+ m_renderingText = text();
RenderText::setTextInternal(objectReplacementCharacterString.impl());
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.h b/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.h
index ce196d4c360..d15bdd75447 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderCombineText.h
@@ -34,17 +34,18 @@ public:
void adjustTextOrigin(FloatPoint& textOrigin, const FloatRect& boxRect) const;
void getStringToRender(int, StringView&, int& length) const;
bool isCombined() const { return m_isCombined; }
- float combinedTextWidth(const Font& font) const { return font.size(); }
+ float combinedTextWidth(const Font& font) const { return font.fontDescription().computedSize(); }
const Font& originalFont() const { return parent()->style()->font(); }
private:
- virtual bool isCombineText() const { return true; }
- virtual float width(unsigned from, unsigned length, const Font&, float xPosition, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
- virtual const char* renderName() const { return "RenderCombineText"; }
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void setTextInternal(PassRefPtr<StringImpl>);
+ virtual bool isCombineText() const OVERRIDE { return true; }
+ virtual float width(unsigned from, unsigned length, const Font&, float xPosition, TextDirection, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const OVERRIDE;
+ virtual const char* renderName() const OVERRIDE { return "RenderCombineText"; }
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual void setTextInternal(PassRefPtr<StringImpl>) OVERRIDE;
float m_combinedTextWidth;
+ String m_renderingText;
bool m_isCombined : 1;
bool m_needsFontUpdate : 1;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.cpp
index 5aac629a947..6451d43ea54 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.cpp
@@ -22,7 +22,7 @@
#include "config.h"
#include "core/rendering/RenderCounter.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/ElementTraversal.h"
@@ -148,12 +148,12 @@ static bool planCounter(RenderObject& object, const AtomicString& identifier, bo
return true;
}
if (Node* e = object.node()) {
- if (e->hasTagName(olTag)) {
+ if (isHTMLOListElement(*e)) {
value = toHTMLOListElement(e)->start();
isReset = true;
return true;
}
- if (e->hasTagName(ulTag) || e->hasTagName(menuTag) || e->hasTagName(dirTag)) {
+ if (isHTMLUListElement(*e) || isHTMLMenuElement(*e) || isHTMLDirectoryElement(*e)) {
value = 0;
isReset = true;
return true;
@@ -189,8 +189,8 @@ static bool findPlaceForCounter(RenderObject& counterOwner, const AtomicString&
// towards the begining of the document for counters with the same identifier as the one
// we are trying to find a place for. This is the next renderer to be checked.
RenderObject* currentRenderer = previousInPreOrder(counterOwner);
- previousSibling = 0;
- RefPtr<CounterNode> previousSiblingProtector = 0;
+ previousSibling = nullptr;
+ RefPtr<CounterNode> previousSiblingProtector = nullptr;
while (currentRenderer) {
CounterNode* currentCounter = makeCounterNode(*currentRenderer, identifier, false);
@@ -216,7 +216,7 @@ static bool findPlaceForCounter(RenderObject& counterOwner, const AtomicString&
// In these cases the identified previousSibling will be invalid as its parent is different from
// our identified parent.
if (previousSiblingProtector->parent() != currentCounter)
- previousSiblingProtector = 0;
+ previousSiblingProtector = nullptr;
previousSibling = previousSiblingProtector.get();
return true;
@@ -307,8 +307,8 @@ static CounterNode* makeCounterNode(RenderObject& object, const AtomicString& id
if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter)
return 0;
- RefPtr<CounterNode> newParent = 0;
- RefPtr<CounterNode> newPreviousSibling = 0;
+ RefPtr<CounterNode> newParent = nullptr;
+ RefPtr<CounterNode> newPreviousSibling = nullptr;
RefPtr<CounterNode> newNode = CounterNode::create(object, isReset, value);
if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousSibling))
newParent->insertAfter(newNode.get(), newPreviousSibling.get(), identifier);
@@ -385,9 +385,9 @@ PassRefPtr<StringImpl> RenderCounter::originalText() const
RenderObject* beforeAfterContainer = parent();
while (true) {
if (!beforeAfterContainer)
- return 0;
+ return nullptr;
if (!beforeAfterContainer->isAnonymous() && !beforeAfterContainer->isPseudoElement())
- return 0; // RenderCounters are restricted to before and after pseudo elements
+ return nullptr; // RenderCounters are restricted to before and after pseudo elements
PseudoId containerStyle = beforeAfterContainer->style()->styleType();
if ((containerStyle == BEFORE) || (containerStyle == AFTER))
break;
@@ -425,7 +425,7 @@ void RenderCounter::invalidate()
ASSERT(!m_counterNode);
if (documentBeingDestroyed())
return;
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, CounterNode* node)
@@ -515,8 +515,8 @@ static void updateCounters(RenderObject& renderer)
makeCounterNode(renderer, it->key, false);
continue;
}
- RefPtr<CounterNode> newParent = 0;
- RefPtr<CounterNode> newPreviousSibling = 0;
+ RefPtr<CounterNode> newParent = nullptr;
+ RefPtr<CounterNode> newPreviousSibling = nullptr;
findPlaceForCounter(renderer, it->key, node->hasResetType(), newParent, newPreviousSibling);
if (node != counterMap->get(it->key))
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.h b/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.h
index 85cdff3b643..15d2b518cbb 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderCounter.h
@@ -43,12 +43,12 @@ public:
void updateCounter();
protected:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
private:
- virtual const char* renderName() const;
- virtual bool isCounter() const;
- virtual PassRefPtr<StringImpl> originalText() const;
+ virtual const char* renderName() const OVERRIDE;
+ virtual bool isCounter() const OVERRIDE;
+ virtual PassRefPtr<StringImpl> originalText() const OVERRIDE;
// Removes the reference to the CounterNode associated with this renderer.
// This is used to cause a counter display update when the CounterNode tree changes.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp
index 9babdc2aae7..6a4ca48a297 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp
@@ -26,6 +26,7 @@
#include "core/rendering/RenderDeprecatedFlexibleBox.h"
#include "core/frame/UseCounter.h"
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
@@ -182,10 +183,10 @@ static LayoutUnit contentHeightForChild(RenderBox* child)
return child->logicalHeight() - child->borderAndPaddingLogicalHeight();
}
-void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
RenderStyle* oldStyle = style();
- if (oldStyle && !oldStyle->lineClamp().isNone() && newStyle->lineClamp().isNone())
+ if (oldStyle && !oldStyle->lineClamp().isNone() && newStyle.lineClamp().isNone())
clearLineClamp();
RenderBlock::styleWillChange(diff, newStyle);
@@ -228,19 +229,21 @@ void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths()
ASSERT(preferredLogicalWidthsDirty());
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
- if (style()->width().isFixed() && style()->width().value() > 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+ RenderStyle* styleToUse = style();
+
+ if (styleToUse->width().isFixed() && styleToUse->width().value() > 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->width().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+ if (styleToUse->minWidth().isFixed() && styleToUse->minWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
}
- if (style()->maxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+ if (styleToUse->maxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
}
LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
@@ -250,60 +253,57 @@ void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths()
clearPreferredLogicalWidthsDirty();
}
-void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
+void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren)
{
ASSERT(needsLayout());
if (!relayoutChildren && simplifiedLayout())
return;
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout());
- // Regions changing widths can force us to relayout our children.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (logicalWidthChangedInRegions(flowThread))
- relayoutChildren = true;
- if (updateRegionsAndShapesLogicalSize(flowThread))
- relayoutChildren = true;
+ {
+ // LayoutState needs this deliberate scope to pop before repaint
+ LayoutState state(*this, locationOffset());
- LayoutSize previousSize = size();
+ LayoutSize previousSize = size();
- updateLogicalWidth();
- updateLogicalHeight();
+ updateLogicalWidth();
+ updateLogicalHeight();
- if (previousSize != size()
- || (parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
- && parent()->style()->boxAlign() == BSTRETCH))
- relayoutChildren = true;
+ FastTextAutosizer::LayoutScope fastTextAutosizerLayoutScope(this);
- setHeight(0);
+ if (previousSize != size()
+ || (parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
+ && parent()->style()->boxAlign() == BSTRETCH))
+ relayoutChildren = true;
- m_stretchingChildren = false;
+ setHeight(0);
- if (isHorizontal())
- layoutHorizontalBox(relayoutChildren);
- else
- layoutVerticalBox(relayoutChildren);
+ m_stretchingChildren = false;
- LayoutUnit oldClientAfterEdge = clientLogicalBottom();
- updateLogicalHeight();
+ if (isHorizontal())
+ layoutHorizontalBox(relayoutChildren);
+ else
+ layoutVerticalBox(relayoutChildren);
- if (previousSize.height() != height())
- relayoutChildren = true;
+ LayoutUnit oldClientAfterEdge = clientLogicalBottom();
+ updateLogicalHeight();
- layoutPositionedObjects(relayoutChildren || isRoot());
+ if (previousSize.height() != height())
+ relayoutChildren = true;
- computeRegionRangeForBlock(flowThread);
+ layoutPositionedObjects(relayoutChildren || isDocumentElement());
- computeOverflow(oldClientAfterEdge);
+ computeRegionRangeForBlock(flowThreadContainingBlock());
- statePusher.pop();
+ computeOverflow(oldClientAfterEdge);
+ }
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
if (view()->layoutState()->pageLogicalHeight())
- setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
+ setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(*this, logicalTop()));
// Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
@@ -374,7 +374,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
if (child->isOutOfFlowPositioned())
continue;
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
layoutScope.setChildNeedsLayout(child);
@@ -426,7 +426,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
if (child->isOutOfFlowPositioned()) {
child->containingBlock()->insertPositionedObject(child);
RenderLayer* childLayer = child->layer();
- childLayer->setStaticInlinePosition(xPos); // FIXME: Not right for regions.
+ childLayer->setStaticInlinePosition(xPos);
if (childLayer->staticBlockPosition() != yPos) {
childLayer->setStaticBlockPosition(yPos);
if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
@@ -442,7 +442,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
continue;
}
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
// We need to see if this child's height has changed, since we make block elements
// fill the height of a containing box by default.
@@ -501,7 +501,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
bool expanding = remainingSpace > 0;
unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
- for (unsigned int i = start; i <= end && remainingSpace; i++) {
+ for (unsigned i = start; i <= end && remainingSpace; i++) {
// Always start off by assuming the group can get all the remaining space.
LayoutUnit groupRemainingSpace = remainingSpace;
do {
@@ -664,7 +664,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
if (child->isOutOfFlowPositioned()) {
child->containingBlock()->insertPositionedObject(child);
RenderLayer* childLayer = child->layer();
- childLayer->setStaticInlinePosition(borderStart() + paddingStart()); // FIXME: Not right for regions.
+ childLayer->setStaticInlinePosition(borderStart() + paddingStart());
if (childLayer->staticBlockPosition() != height()) {
childLayer->setStaticBlockPosition(height());
if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
@@ -673,7 +673,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
continue;
}
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
layoutScope.setChildNeedsLayout(child);
@@ -755,7 +755,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
bool expanding = remainingSpace > 0;
unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
- for (unsigned int i = start; i <= end && remainingSpace; i++) {
+ for (unsigned i = start; i <= end && remainingSpace; i++) {
// Always start off by assuming the group can get all the remaining space.
LayoutUnit groupRemainingSpace = remainingSpace;
do {
@@ -945,36 +945,36 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool
const Font& font = style(numVisibleLines == 1)->font();
// Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
- LayoutUnit totalWidth;
+ float totalWidth;
InlineBox* anchorBox = lastLine->lastChild();
- if (anchorBox && anchorBox->renderer()->style()->isLink())
- totalWidth = anchorBox->logicalWidth() + font.width(RenderBlockFlow::constructTextRun(this, font, ellipsisAndSpace, 2, style()));
+ if (anchorBox && anchorBox->renderer().style()->isLink())
+ totalWidth = anchorBox->logicalWidth() + font.width(RenderBlockFlow::constructTextRun(this, font, ellipsisAndSpace, 2, style(), style()->direction()));
else {
anchorBox = 0;
- totalWidth = font.width(RenderBlockFlow::constructTextRun(this, font, &horizontalEllipsis, 1, style()));
+ totalWidth = font.width(RenderBlockFlow::constructTextRun(this, font, &horizontalEllipsis, 1, style(), style()->direction()));
}
// See if this width can be accommodated on the last visible line
- RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer());
- RenderBlock* srcBlock = toRenderBlock(lastLine->renderer());
+ RenderBlockFlow& destBlock = lastVisibleLine->block();
+ RenderBlockFlow& srcBlock = lastLine->block();
// FIXME: Directions of src/destBlock could be different from our direction and from one another.
- if (!srcBlock->style()->isLeftToRightDirection())
+ if (!srcBlock.style()->isLeftToRightDirection())
continue;
- bool leftToRight = destBlock->style()->isLeftToRightDirection();
+ bool leftToRight = destBlock.style()->isLeftToRightDirection();
if (!leftToRight)
continue;
- LayoutUnit blockRightEdge = destBlock->logicalRightOffsetForLine(lastVisibleLine->y(), false);
+ LayoutUnit blockRightEdge = destBlock.logicalRightOffsetForLine(lastVisibleLine->y(), false);
if (!lastVisibleLine->lineCanAccommodateEllipsis(leftToRight, blockRightEdge, lastVisibleLine->x() + lastVisibleLine->logicalWidth(), totalWidth))
continue;
// Let the truncation code kick in.
// FIXME: the text alignment should be recomputed after the width changes due to truncation.
- LayoutUnit blockLeftEdge = destBlock->logicalLeftOffsetForLine(lastVisibleLine->y(), false);
- lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsisStr, leftToRight, blockLeftEdge, blockRightEdge, totalWidth, anchorBox);
- destBlock->setHasMarkupTruncation(true);
+ LayoutUnit blockLeftEdge = destBlock.logicalLeftOffsetForLine(lastVisibleLine->y(), false);
+ lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsisStr, leftToRight, blockLeftEdge.toFloat(), blockRightEdge.toFloat(), totalWidth, anchorBox);
+ destBlock.setHasMarkupTruncation(true);
}
}
@@ -1002,13 +1002,16 @@ void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint
{
LayoutRect oldRect = child->frameRect();
+ // FIXME Investigate if this can be removed based on other flags. crbug.com/370010
+ child->setMayNeedPaintInvalidation(true);
+
// Place the child.
child->setLocation(location);
// If the child moved, we have to repaint it as well as any floating/positioned
// descendants. An exception is if we need a layout. In this case, we know we're going to
// repaint ourselves (and the child) anyway.
- if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ if (!selfNeedsLayout() && child->checkForPaintInvalidationDuringLayout())
child->repaintDuringLayoutIfMoved(oldRect);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.h b/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.h
index ff039dacb2b..f6576ab2c95 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderDeprecatedFlexibleBox.h
@@ -36,17 +36,17 @@ public:
static RenderDeprecatedFlexibleBox* createAnonymous(Document*);
- virtual const char* renderName() const;
+ virtual const char* renderName() const OVERRIDE;
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageHeight = 0);
+ virtual void layoutBlock(bool relayoutChildren) OVERRIDE;
void layoutHorizontalBox(bool relayoutChildren);
void layoutVerticalBox(bool relayoutChildren);
- virtual bool avoidsFloats() const { return true; }
- virtual bool isDeprecatedFlexibleBox() const { return true; }
- virtual bool isStretchingChildren() const { return m_stretchingChildren; }
+ virtual bool avoidsFloats() const OVERRIDE { return true; }
+ virtual bool isDeprecatedFlexibleBox() const OVERRIDE { return true; }
+ bool isStretchingChildren() const { return m_stretchingChildren; }
virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return false; }
void placeChild(RenderBox* child, const LayoutPoint& location);
@@ -64,12 +64,12 @@ protected:
bool m_stretchingChildren;
private:
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
void applyLineClamp(FlexBoxIterator&, bool relayoutChildren);
void clearLineClamp();
};
+DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderDeprecatedFlexibleBox, isDeprecatedFlexibleBox());
+
} // namespace WebCore
#endif // RenderDeprecatedFlexibleBox_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.cpp
index 68e6083489c..a793c342fa4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.cpp
@@ -21,8 +21,9 @@
#include "config.h"
#include "core/rendering/RenderDetailsMarker.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/Element.h"
+#include "core/html/HTMLElement.h"
#include "core/rendering/PaintInfo.h"
#include "platform/graphics/GraphicsContext.h"
@@ -106,8 +107,8 @@ Path RenderDetailsMarker::getCanonicalPath() const
Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
{
Path result = getCanonicalPath();
- result.transform(AffineTransform().scale(contentWidth(), contentHeight()));
- result.translate(FloatSize(origin.x(), origin.y()));
+ result.transform(AffineTransform().scale(contentWidth().toFloat(), contentHeight().toFloat()));
+ result.translate(FloatSize(origin.x().toFloat(), origin.y().toFloat()));
return result;
}
@@ -121,7 +122,6 @@ void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOf
LayoutPoint boxOrigin(paintOffset + location());
LayoutRect overflowRect(visualOverflowRect());
overflowRect.moveBy(boxOrigin);
- overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
return;
@@ -141,9 +141,9 @@ bool RenderDetailsMarker::isOpen() const
for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
if (!renderer->node())
continue;
- if (renderer->node()->hasTagName(detailsTag))
+ if (isHTMLDetailsElement(*renderer->node()))
return !toElement(renderer->node())->getAttribute(openAttr).isNull();
- if (renderer->node()->hasTagName(inputTag))
+ if (isHTMLInputElement(*renderer->node()))
return true;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.h b/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.h
index aa996c818a2..5b20924b5bc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderDetailsMarker.h
@@ -34,10 +34,9 @@ public:
Orientation orientation() const;
private:
- virtual const char* renderName() const { return "RenderDetailsMarker"; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual bool isDetailsMarker() const { return true; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual const char* renderName() const OVERRIDE { return "RenderDetailsMarker"; }
+ virtual bool isDetailsMarker() const OVERRIDE { return true; }
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
bool isOpen() const;
Path getCanonicalPath() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.cpp
index 376aab5c5d8..fdd906df36b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.cpp
@@ -24,14 +24,14 @@
#include "config.h"
#include "core/rendering/RenderEmbeddedObject.h"
-#include "CSSValueKeywords.h"
-#include "HTMLNames.h"
+#include "core/CSSValueKeywords.h"
+#include "core/HTMLNames.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLIFrameElement.h"
-#include "core/frame/Frame.h"
+#include "core/html/HTMLPlugInElement.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/plugins/PluginView.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
@@ -54,7 +54,6 @@ static const float replacementTextTextOpacity = 0.55f;
RenderEmbeddedObject::RenderEmbeddedObject(Element* element)
: RenderPart(element)
- , m_hasFallbackContent(false)
, m_showsUnavailablePluginIndicator(false)
{
view()->frameView()->setIsVisuallyNonEmpty();
@@ -64,17 +63,16 @@ RenderEmbeddedObject::~RenderEmbeddedObject()
{
}
-bool RenderEmbeddedObject::requiresLayer() const
+LayerType RenderEmbeddedObject::layerTypeRequired() const
{
- if (RenderPart::requiresLayer())
- return true;
-
- return allowsAcceleratedCompositing();
-}
-
-bool RenderEmbeddedObject::allowsAcceleratedCompositing() const
-{
- return widget() && widget()->isPluginView() && toPluginView(widget())->platformLayer();
+ // This can't just use RenderPart::layerTypeRequired, because RenderLayerCompositor
+ // doesn't loop through RenderEmbeddedObjects the way it does frames in order
+ // to update the self painting bit on their RenderLayer.
+ // Also, unlike iframes, embeds don't used the usesCompositing bit on RenderView
+ // in requiresAcceleratedCompositing.
+ if (requiresAcceleratedCompositing())
+ return NormalLayer;
+ return RenderPart::layerTypeRequired();
}
static String unavailablePluginReplacementText(Node* node, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
@@ -108,7 +106,7 @@ bool RenderEmbeddedObject::showsUnavailablePluginIndicator() const
void RenderEmbeddedObject::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
Element* element = toElement(node());
- if (!element || !element->isPluginElement())
+ if (!isHTMLPlugInElement(element))
return;
RenderPart::paintContents(paintInfo, paintOffset);
@@ -147,7 +145,7 @@ void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint
GraphicsContextStateSaver stateSaver(*context);
context->clip(contentRect);
- context->setAlpha(replacementTextRoundedRectOpacity);
+ context->setAlphaAsFloat(replacementTextRoundedRectOpacity);
context->setFillColor(Color::white);
context->fillPath(path);
@@ -156,7 +154,7 @@ void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint
float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - fontMetrics.height()) / 2 + fontMetrics.ascent());
TextRunPaintInfo runInfo(run);
runInfo.bounds = replacementTextRect;
- context->setAlpha(replacementTextTextOpacity);
+ context->setAlphaAsFloat(replacementTextTextOpacity);
context->setFillColor(Color::black);
context->drawBidiText(font, runInfo, FloatPoint(labelX, labelY));
}
@@ -174,8 +172,8 @@ bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumul
if (!settings)
return false;
fontDescription.setComputedSize(fontDescription.specifiedSize());
- font = Font(fontDescription, 0, 0);
- font.update(0);
+ font = Font(fontDescription);
+ font.update(nullptr);
run = TextRun(m_unavailablePluginReplacementText);
textWidth = font.width(run);
@@ -194,83 +192,37 @@ void RenderEmbeddedObject::layout()
{
ASSERT(needsLayout());
- LayoutSize oldSize = contentBoxRect().size();
- LayoutRectRecorder recorder(*this);
-
updateLogicalWidth();
updateLogicalHeight();
- RenderPart::layout();
-
m_overflow.clear();
addVisualEffectOverflow();
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
if (!widget() && frameView())
frameView()->addWidgetToUpdate(*this);
clearNeedsLayout();
-
- if (!canHaveChildren())
- return;
-
- // This code copied from RenderMedia::layout().
- RenderObject* child = m_children.firstChild();
-
- if (!child)
- return;
-
- RenderBox* childBox = toRenderBox(child);
-
- if (!childBox)
- return;
-
- LayoutSize newSize = contentBoxRect().size();
- if (newSize == oldSize && !childBox->needsLayout())
- return;
-
- // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or
- // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
- // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
-
- childBox->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
- childBox->style()->setHeight(Length(newSize.height(), Fixed));
- childBox->style()->setWidth(Length(newSize.width(), Fixed));
- childBox->forceLayout();
- clearNeedsLayout();
-
- statePusher.pop();
}
-void RenderEmbeddedObject::viewCleared()
+bool RenderEmbeddedObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float)
{
- // This is required for <object> elements whose contents are rendered by WebCore (e.g. src="foo.html").
- if (node() && widget() && widget()->isFrameView()) {
- FrameView* view = toFrameView(widget());
- int marginWidth = -1;
- int marginHeight = -1;
- if (node()->hasTagName(iframeTag)) {
- HTMLIFrameElement* frame = toHTMLIFrameElement(node());
- marginWidth = frame->marginWidth();
- marginHeight = frame->marginHeight();
- }
- if (marginWidth != -1)
- view->setMarginWidth(marginWidth);
- if (marginHeight != -1)
- view->setMarginHeight(marginHeight);
- }
+ return false;
}
-bool RenderEmbeddedObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float)
+CompositingReasons RenderEmbeddedObject::additionalCompositingReasons(CompositingTriggerFlags triggers) const
{
- return false;
+ if (requiresAcceleratedCompositing())
+ return CompositingReasonPlugin;
+ return CompositingReasonNone;
}
-bool RenderEmbeddedObject::canHaveChildren() const
+RenderBox* RenderEmbeddedObject::embeddedContentBox() const
{
- return false;
+ if (!node() || !widget() || !widget()->isFrameView())
+ return 0;
+ return toFrameView(widget())->embeddedContentBox();
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.h b/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.h
index 679658ec445..a33e28300b9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderEmbeddedObject.h
@@ -27,7 +27,6 @@
namespace WebCore {
-class MouseEvent;
class TextRun;
// Renderer for embeds and objects, often, but not always, rendered via plug-ins.
@@ -44,47 +43,32 @@ public:
void setPluginUnavailabilityReason(PluginUnavailabilityReason);
bool showsUnavailablePluginIndicator() const;
- // FIXME: This belongs on HTMLObjectElement.
- bool hasFallbackContent() const { return m_hasFallbackContent; }
- void setHasFallbackContent(bool hasFallbackContent) { m_hasFallbackContent = hasFallbackContent; }
-
- bool allowsAcceleratedCompositing() const;
-
protected:
virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
- const RenderObjectChildList* children() const { return &m_children; }
- RenderObjectChildList* children() { return &m_children; }
-
protected:
virtual void layout() OVERRIDE FINAL;
private:
- virtual const char* renderName() const { return "RenderEmbeddedObject"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderEmbeddedObject"; }
virtual bool isEmbeddedObject() const OVERRIDE FINAL { return true; }
+ virtual RenderBox* embeddedContentBox() const OVERRIDE FINAL;
void paintSnapshotImage(PaintInfo&, const LayoutPoint&, Image*);
virtual void paintContents(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
- virtual bool requiresLayer() const OVERRIDE FINAL;
-
- virtual void viewCleared() OVERRIDE FINAL;
+ virtual LayerType layerTypeRequired() const OVERRIDE FINAL;
virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier) OVERRIDE FINAL;
bool getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth) const;
- virtual bool canHaveChildren() const OVERRIDE FINAL;
- virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
-
- bool m_hasFallbackContent; // FIXME: This belongs on HTMLObjectElement.
+ virtual CompositingReasons additionalCompositingReasons(CompositingTriggerFlags) const OVERRIDE;
bool m_showsUnavailablePluginIndicator;
PluginUnavailabilityReason m_pluginUnavailabilityReason;
String m_unavailablePluginReplacementText;
- RenderObjectChildList m_children;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderEmbeddedObject, isEmbeddedObject());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.cpp
index b3962cf6f0a..bf1de947644 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.cpp
@@ -24,8 +24,9 @@
#include "config.h"
#include "core/rendering/RenderFieldset.h"
-#include "CSSPropertyNames.h"
-#include "HTMLNames.h"
+#include "core/CSSPropertyNames.h"
+#include "core/HTMLNames.h"
+#include "core/html/HTMLLegendElement.h"
#include "core/rendering/PaintInfo.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
@@ -43,7 +44,7 @@ RenderFieldset::RenderFieldset(Element* element)
void RenderFieldset::computePreferredLogicalWidths()
{
- RenderBlock::computePreferredLogicalWidths();
+ RenderBlockFlow::computePreferredLogicalWidths();
if (RenderBox* legend = findLegend()) {
int legendMinWidth = legend->minPreferredLogicalWidth();
@@ -65,7 +66,7 @@ RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren,
RenderBox* legend = findLegend();
if (legend) {
if (relayoutChildren)
- legend->setNeedsLayout();
+ legend->setNeedsLayoutAndFullPaintInvalidation();
legend->layoutIfNeeded();
LayoutUnit logicalLeft;
@@ -129,7 +130,7 @@ RenderBox* RenderFieldset::findLegend(FindLegendOption option) const
if (option == IgnoreFloatingOrOutOfFlow && legend->isFloatingOrOutOfFlowPositioned())
continue;
- if (legend->node() && (legend->node()->hasTagName(legendTag)))
+ if (isHTMLLegendElement(legend->node()))
return toRenderBox(legend);
}
return 0;
@@ -143,7 +144,7 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint
LayoutRect paintRect(paintOffset, size());
RenderBox* legend = findLegend();
if (!legend)
- return RenderBlock::paintBoxDecorations(paintInfo, paintOffset);
+ return RenderBlockFlow::paintBoxDecorations(paintInfo, paintOffset);
// FIXME: We need to work with "rl" and "bt" block flow directions. In those
// cases the legend is embedded in the right and bottom borders respectively.
@@ -194,7 +195,7 @@ void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOff
LayoutRect paintRect = LayoutRect(paintOffset, size());
RenderBox* legend = findLegend();
if (!legend)
- return RenderBlock::paintMask(paintInfo, paintOffset);
+ return RenderBlockFlow::paintMask(paintInfo, paintOffset);
// FIXME: We need to work with "rl" and "bt" block flow directions. In those
// cases the legend is embedded in the right and bottom borders respectively.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.h
index 944ab4c1dc6..0ebc486eca2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFieldset.h
@@ -36,18 +36,16 @@ public:
RenderBox* findLegend(FindLegendOption = IgnoreFloatingOrOutOfFlow) const;
private:
- virtual const char* renderName() const { return "RenderFieldSet"; }
- virtual bool isFieldset() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderFieldSet"; }
+ virtual bool isFieldset() const OVERRIDE { return true; }
- virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&);
+ virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) OVERRIDE;
- virtual void computePreferredLogicalWidths();
- virtual bool avoidsFloats() const { return true; }
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+ virtual bool avoidsFloats() const OVERRIDE { return true; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
- virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
- virtual void paintMask(PaintInfo&, const LayoutPoint&);
+ virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void paintMask(PaintInfo&, const LayoutPoint&) OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFieldset, isFieldset());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.cpp
index 80a822fe74c..9fd7784719c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.cpp
@@ -21,8 +21,7 @@
#include "config.h"
#include "core/rendering/RenderFileUploadControl.h"
-#include <math.h>
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/fileapi/FileList.h"
@@ -34,6 +33,7 @@
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/text/PlatformLocale.h"
#include "platform/text/TextRun.h"
+#include <math.h>
using namespace std;
@@ -73,7 +73,7 @@ void RenderFileUploadControl::updateFromElement()
FileList* files = input->files();
ASSERT(files);
if (files && files->isEmpty())
- repaint();
+ paintInvalidationForWholeRenderer();
}
static int nodeWidth(Node* node)
@@ -131,10 +131,9 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
else
textY = baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
TextRunPaintInfo textRunPaintInfo(textRun);
- textRunPaintInfo.bounds = FloatRect(textX,
- textY - style()->fontMetrics().ascent(),
- textWidth,
- style()->fontMetrics().height());
+ // FIXME: Shouldn't these offsets be rounded? crbug.com/350474
+ textRunPaintInfo.bounds = FloatRect(textX.toFloat(), textY.toFloat() - style()->fontMetrics().ascent(),
+ textWidth, style()->fontMetrics().height());
paintInfo.context->setFillColor(resolveColor(CSSPropertyColor));
@@ -143,7 +142,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
}
// Paint the children.
- RenderBlock::paintObject(paintInfo, paintOffset);
+ RenderBlockFlow::paintObject(paintInfo, paintOffset);
}
void RenderFileUploadControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
@@ -174,20 +173,21 @@ void RenderFileUploadControl::computePreferredLogicalWidths()
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
+ RenderStyle* styleToUse = style();
- if (style()->width().isFixed() && style()->width().value() > 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+ if (styleToUse->width().isFixed() && styleToUse->width().value() > 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->width().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+ if (styleToUse->minWidth().isFixed() && styleToUse->minWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
}
- if (style()->maxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+ if (styleToUse->maxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
}
int toAdd = borderAndPaddingWidth();
@@ -207,7 +207,7 @@ HTMLInputElement* RenderFileUploadControl::uploadButton() const
// FIXME: This should be on HTMLInputElement as an API like innerButtonElement().
HTMLInputElement* input = toHTMLInputElement(node());
Node* buttonNode = input->userAgentShadowRoot()->firstChild();
- return buttonNode && buttonNode->isHTMLElement() && buttonNode->hasTagName(inputTag) ? toHTMLInputElement(buttonNode) : 0;
+ return isHTMLInputElement(buttonNode) ? toHTMLInputElement(buttonNode) : 0;
}
String RenderFileUploadControl::buttonValue()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.h
index f83bb2a585d..5e2f70410a2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFileUploadControl.h
@@ -36,24 +36,22 @@ public:
RenderFileUploadControl(HTMLInputElement*);
virtual ~RenderFileUploadControl();
- virtual bool isFileUploadControl() const { return true; }
+ virtual bool isFileUploadControl() const OVERRIDE { return true; }
String buttonValue();
String fileTextValue() const;
private:
- virtual const char* renderName() const { return "RenderFileUploadControl"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderFileUploadControl"; }
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
- virtual void computePreferredLogicalWidths();
- virtual void paintObject(PaintInfo&, const LayoutPoint&);
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+ virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
int maxFilenameWidth() const;
- virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
+ virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
HTMLInputElement* uploadButton() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.cpp
index 65c82221b62..6114d5654cd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.cpp
@@ -31,11 +31,13 @@
#include "config.h"
#include "core/rendering/RenderFlexibleBox.h"
-#include <limits>
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
+#include "platform/LengthFunctions.h"
#include "wtf/MathExtras.h"
+#include <limits>
namespace WebCore {
@@ -141,8 +143,7 @@ int RenderFlexibleBox::baselinePosition(FontBaseline, bool, LineDirectionMode di
if (baseline == -1)
baseline = synthesizedBaselineFromContentBox(this, direction);
- int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
- return baseline + marginAscent;
+ return beforeMarginInLineDirection(direction) + baseline;
}
int RenderFlexibleBox::firstLineBoxBaseline() const
@@ -154,7 +155,7 @@ int RenderFlexibleBox::firstLineBoxBaseline() const
for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
if (child->isOutOfFlowPositioned())
continue;
- if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child)) {
+ if (alignmentForChild(child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(child)) {
baselineChild = child;
break;
}
@@ -195,37 +196,43 @@ int RenderFlexibleBox::inlineBlockBaseline(LineDirectionMode direction) const
return synthesizedBaselineFromContentBox(this, direction) + marginAscent;
}
-static EAlignItems resolveAlignment(const RenderStyle* parentStyle, const RenderStyle* childStyle)
+static ItemPosition resolveAlignment(const RenderStyle* parentStyle, const RenderStyle* childStyle)
{
- EAlignItems align = childStyle->alignSelf();
- if (align == AlignAuto)
+ ItemPosition align = childStyle->alignSelf();
+ if (align == ItemPositionAuto)
align = parentStyle->alignItems();
return align;
}
+void RenderFlexibleBox::removeChild(RenderObject* child)
+{
+ RenderBlock::removeChild(child);
+ m_intrinsicSizeAlongMainAxis.remove(child);
+}
+
void RenderFlexibleBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
- if (oldStyle && oldStyle->alignItems() == AlignStretch && diff == StyleDifferenceLayout) {
+ if (oldStyle && oldStyle->alignItems() == ItemPositionStretch && diff.needsFullLayout()) {
// Flex items that were previously stretching need to be relayed out so we can compute new available cross axis space.
// This is only necessary for stretching since other alignment values don't change the size of the box.
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
- EAlignItems previousAlignment = resolveAlignment(oldStyle, child->style());
- if (previousAlignment == AlignStretch && previousAlignment != resolveAlignment(style(), child->style()))
+ ItemPosition previousAlignment = resolveAlignment(oldStyle, child->style());
+ if (previousAlignment == ItemPositionStretch && previousAlignment != resolveAlignment(style(), child->style()))
child->setChildNeedsLayout(MarkOnlyThis);
}
}
}
-void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
+void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
{
ASSERT(needsLayout());
if (!relayoutChildren && simplifiedLayout())
return;
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout());
if (updateLogicalWidthAndColumnWidth())
relayoutChildren = true;
@@ -233,45 +240,36 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
LayoutUnit previousHeight = logicalHeight();
setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
-
- // Regions changing widths can force us to relayout our children.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (logicalWidthChangedInRegions(flowThread))
- relayoutChildren = true;
- if (updateRegionsAndShapesLogicalSize(flowThread))
- relayoutChildren = true;
-
- m_numberOfInFlowChildrenOnFirstLine = -1;
+ {
+ FastTextAutosizer::LayoutScope fastTextAutosizerLayoutScope(this);
+ LayoutState state(*this, locationOffset());
- RenderBlock::startDelayUpdateScrollInfo();
+ m_numberOfInFlowChildrenOnFirstLine = -1;
- prepareOrderIteratorAndMargins();
+ RenderBlock::startDelayUpdateScrollInfo();
- ChildFrameRects oldChildRects;
- appendChildFrameRects(oldChildRects);
+ prepareOrderIteratorAndMargins();
- Vector<LineContext> lineContexts;
- layoutFlexItems(relayoutChildren, lineContexts);
+ ChildFrameRects oldChildRects;
+ appendChildFrameRects(oldChildRects);
- updateLogicalHeight();
- repositionLogicalHeightDependentFlexItems(lineContexts);
+ layoutFlexItems(relayoutChildren);
- RenderBlock::finishDelayUpdateScrollInfo();
+ RenderBlock::finishDelayUpdateScrollInfo();
- if (logicalHeight() != previousHeight)
- relayoutChildren = true;
+ if (logicalHeight() != previousHeight)
+ relayoutChildren = true;
- layoutPositionedObjects(relayoutChildren || isRoot());
+ layoutPositionedObjects(relayoutChildren || isDocumentElement());
- computeRegionRangeForBlock(flowThread);
+ computeRegionRangeForBlock(flowThreadContainingBlock());
- repaintChildrenDuringLayoutIfMoved(oldChildRects);
- // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
- computeOverflow(clientLogicalBottomAfterRepositioning());
- statePusher.pop();
+ repaintChildrenDuringLayoutIfMoved(oldChildRects);
+ // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
+ computeOverflow(clientLogicalBottomAfterRepositioning());
+ }
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
@@ -300,7 +298,7 @@ void RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved(const ChildFrameRects
// If the child moved, we have to repaint it as well as any floating/positioned
// descendants. An exception is if we need a layout. In this case, we know we're going to
// repaint ourselves (and the child) anyway.
- if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ if (!selfNeedsLayout() && child->checkForPaintInvalidationDuringLayout())
child->repaintDuringLayoutIfMoved(oldChildRects[childIndex]);
++childIndex;
}
@@ -318,10 +316,6 @@ void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(Vector<LineCon
LayoutUnit crossAxisStartEdge = lineContexts.isEmpty() ? LayoutUnit() : lineContexts[0].crossAxisOffset;
alignFlexLines(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 updateLogicalHeight.
- if (!isMultiline() && lineContexts.size() == 1)
- lineContexts[0].crossAxisExtent = crossAxisContentExtent();
alignChildren(lineContexts);
if (style()->flexWrap() == FlexWrapReverse)
@@ -340,7 +334,7 @@ LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
LayoutUnit childLogicalBottom = logicalTopForChild(child) + logicalHeightForChild(child) + marginAfterForChild(child);
maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
}
- return std::max(clientLogicalBottom(), maxChildLogicalBottom);
+ return std::max(clientLogicalBottom(), maxChildLogicalBottom + paddingAfter());
}
bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox* child) const
@@ -381,17 +375,34 @@ Length RenderFlexibleBox::flexBasisForChild(RenderBox* child) const
return flexLength;
}
-void RenderFlexibleBox::setCrossAxisExtent(LayoutUnit extent)
+LayoutUnit RenderFlexibleBox::crossAxisExtentForChild(RenderBox* child) const
{
- if (isHorizontalFlow())
- setHeight(extent);
- else
- setWidth(extent);
+ return isHorizontalFlow() ? child->height() : child->width();
}
-LayoutUnit RenderFlexibleBox::crossAxisExtentForChild(RenderBox* child) const
+static inline LayoutUnit constrainedChildIntrinsicContentLogicalHeight(RenderBox* child)
{
- return isHorizontalFlow() ? child->height() : child->width();
+ LayoutUnit childIntrinsicContentLogicalHeight = child->intrinsicContentLogicalHeight();
+ return child->constrainLogicalHeightByMinMax(childIntrinsicContentLogicalHeight + child->borderAndPaddingLogicalHeight(), childIntrinsicContentLogicalHeight);
+}
+
+LayoutUnit RenderFlexibleBox::childIntrinsicHeight(RenderBox* child) const
+{
+ if (child->isHorizontalWritingMode() && needToStretchChildLogicalHeight(child))
+ return constrainedChildIntrinsicContentLogicalHeight(child);
+ return child->height();
+}
+
+LayoutUnit RenderFlexibleBox::childIntrinsicWidth(RenderBox* child) const
+{
+ if (!child->isHorizontalWritingMode() && needToStretchChildLogicalHeight(child))
+ return constrainedChildIntrinsicContentLogicalHeight(child);
+ return child->width();
+}
+
+LayoutUnit RenderFlexibleBox::crossAxisIntrinsicExtentForChild(RenderBox* child) const
+{
+ return isHorizontalFlow() ? childIntrinsicHeight(child) : childIntrinsicWidth(child);
}
LayoutUnit RenderFlexibleBox::mainAxisExtentForChild(RenderBox* child) const
@@ -439,9 +450,7 @@ LayoutUnit RenderFlexibleBox::computeMainAxisExtentForChild(RenderBox* child, Si
child->layoutIfNeeded();
return child->computeContentLogicalHeight(size, child->logicalHeight() - child->borderAndPaddingLogicalHeight());
}
- // FIXME: Figure out how this should work for regions and pass in the appropriate values.
- RenderRegion* region = 0;
- return child->computeLogicalWidthInRegionUsing(sizeType, size, contentLogicalWidth(), this, region) - child->borderAndPaddingLogicalWidth();
+ return child->computeLogicalWidthUsing(sizeType, size, contentLogicalWidth(), this) - child->borderAndPaddingLogicalWidth();
}
WritingMode RenderFlexibleBox::transformedWritingMode() const
@@ -584,22 +593,6 @@ LayoutUnit RenderFlexibleBox::flowAwareMarginBeforeForChild(RenderBox* child) co
return marginTop();
}
-LayoutUnit RenderFlexibleBox::flowAwareMarginAfterForChild(RenderBox* child) const
-{
- switch (transformedWritingMode()) {
- case TopToBottomWritingMode:
- return child->marginBottom();
- case BottomToTopWritingMode:
- return child->marginTop();
- case LeftToRightWritingMode:
- return child->marginRight();
- case RightToLeftWritingMode:
- return child->marginLeft();
- }
- ASSERT_NOT_REACHED();
- return marginBottom();
-}
-
LayoutUnit RenderFlexibleBox::crossAxisMarginExtentForChild(RenderBox* child) const
{
return isHorizontalFlow() ? child->marginHeight() : child->marginWidth();
@@ -628,54 +621,66 @@ LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox*
return isHorizontalFlow() ? child->borderAndPaddingWidth() : child->borderAndPaddingHeight();
}
-LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox* child) const
+static inline bool preferredMainAxisExtentDependsOnLayout(const Length& flexBasis, bool hasInfiniteLineLength)
+{
+ return flexBasis.isAuto() || (flexBasis.isFixed() && !flexBasis.value() && hasInfiniteLineLength);
+}
+
+bool RenderFlexibleBox::childPreferredMainAxisContentExtentRequiresLayout(RenderBox* child, bool hasInfiniteLineLength) const
{
- return isHorizontalFlow() ? child->verticalScrollbarWidth() : child->horizontalScrollbarHeight();
+ return preferredMainAxisExtentDependsOnLayout(flexBasisForChild(child), hasInfiniteLineLength) && hasOrthogonalFlow(child);
}
-LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* child, bool hasInfiniteLineLength)
+LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* child, bool hasInfiniteLineLength, bool relayoutChildren)
{
- bool hasOverrideSize = child->hasOverrideWidth() || child->hasOverrideHeight();
- if (hasOverrideSize)
- child->clearOverrideSize();
+ child->clearOverrideSize();
Length flexBasis = flexBasisForChild(child);
- if (flexBasis.isAuto() || (flexBasis.isFixed() && !flexBasis.value() && hasInfiniteLineLength)) {
+ if (preferredMainAxisExtentDependsOnLayout(flexBasis, hasInfiniteLineLength)) {
+ LayoutUnit mainAxisExtent;
if (hasOrthogonalFlow(child)) {
- if (hasOverrideSize)
- child->setChildNeedsLayout(MarkOnlyThis);
- child->layoutIfNeeded();
+ if (child->needsLayout() || relayoutChildren) {
+ m_intrinsicSizeAlongMainAxis.remove(child);
+ child->forceChildLayout();
+ m_intrinsicSizeAlongMainAxis.set(child, child->logicalHeight());
+ }
+ ASSERT(m_intrinsicSizeAlongMainAxis.contains(child));
+ mainAxisExtent = m_intrinsicSizeAlongMainAxis.get(child);
+ } else {
+ mainAxisExtent = child->maxPreferredLogicalWidth();
}
- LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth();
ASSERT(mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child) >= 0);
return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
}
return std::max(LayoutUnit(0), computeMainAxisExtentForChild(child, MainOrPreferredSize, flexBasis));
}
-void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren, Vector<LineContext>& lineContexts)
+void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren)
{
+ Vector<LineContext> lineContexts;
OrderedFlexItemList orderedChildren;
LayoutUnit sumFlexBaseSize;
double totalFlexGrow;
double totalWeightedFlexShrink;
LayoutUnit sumHypotheticalMainSize;
+ Vector<LayoutUnit, 16> childSizes;
+
m_orderIterator.first();
LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
bool hasInfiniteLineLength = false;
- while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalWeightedFlexShrink, sumHypotheticalMainSize, hasInfiniteLineLength)) {
+ while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalWeightedFlexShrink, sumHypotheticalMainSize, hasInfiniteLineLength, relayoutChildren)) {
LayoutUnit containerMainInnerSize = mainAxisContentExtent(sumHypotheticalMainSize);
LayoutUnit availableFreeSpace = containerMainInnerSize - sumFlexBaseSize;
FlexSign flexSign = (sumHypotheticalMainSize < containerMainInnerSize) ? PositiveFlexibility : NegativeFlexibility;
InflexibleFlexItemSize inflexibleItems;
- Vector<LayoutUnit> childSizes;
+ childSizes.reserveCapacity(orderedChildren.size());
while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, childSizes, hasInfiniteLineLength)) {
ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0);
ASSERT(inflexibleItems.size() > 0);
}
- layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, relayoutChildren, lineContexts);
+ layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, relayoutChildren, lineContexts, hasInfiniteLineLength);
}
if (hasLineIfEmpty()) {
// Even if computeNextFlexLine returns true, the flexbox might not have
@@ -688,6 +693,9 @@ void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren, Vector<LineContex
if (height() < minHeight)
setLogicalHeight(minHeight);
}
+
+ updateLogicalHeight();
+ repositionLogicalHeightDependentFlexItems(lineContexts);
}
LayoutUnit RenderFlexibleBox::autoMarginOffsetInMainAxis(const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace)
@@ -752,6 +760,13 @@ LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChild(LayoutUnit lineCro
return lineCrossAxisExtent - childCrossExtent;
}
+LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChildBeforeStretching(LayoutUnit lineCrossAxisExtent, RenderBox* child)
+{
+ ASSERT(!child->isOutOfFlowPositioned());
+ LayoutUnit childCrossExtent = crossAxisMarginExtentForChild(child) + crossAxisIntrinsicExtentForChild(child);
+ return lineCrossAxisExtent - childCrossExtent;
+}
+
bool RenderFlexibleBox::updateAutoMarginsInCrossAxis(RenderBox* child, LayoutUnit availableAlignmentSpace)
{
ASSERT(!child->isOutOfFlowPositioned());
@@ -814,17 +829,16 @@ LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox* child)
return ascent + flowAwareMarginBeforeForChild(child);
}
-LayoutUnit RenderFlexibleBox::computeChildMarginValue(Length margin, RenderView* view)
+LayoutUnit RenderFlexibleBox::computeChildMarginValue(Length margin)
{
// When resolving the margins, we use the content size for resolving percent and calc (for percents in calc expressions) margins.
// Fortunately, percent margins are always computed with respect to the block's width, even for margin-top and margin-bottom.
LayoutUnit availableSize = contentLogicalWidth();
- return minimumValueForLength(margin, availableSize, view);
+ return minimumValueForLength(margin, availableSize);
}
void RenderFlexibleBox::prepareOrderIteratorAndMargins()
{
- RenderView* renderView = view();
OrderIteratorPopulator populator(m_orderIterator);
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
@@ -836,11 +850,11 @@ void RenderFlexibleBox::prepareOrderIteratorAndMargins()
// Before running the flex algorithm, 'auto' has a margin of 0.
// Also, if we're not auto sizing, we don't do a layout that computes the start/end margins.
if (isHorizontalFlow()) {
- child->setMarginLeft(computeChildMarginValue(child->style()->marginLeft(), renderView));
- child->setMarginRight(computeChildMarginValue(child->style()->marginRight(), renderView));
+ child->setMarginLeft(computeChildMarginValue(child->style()->marginLeft()));
+ child->setMarginRight(computeChildMarginValue(child->style()->marginRight()));
} else {
- child->setMarginTop(computeChildMarginValue(child->style()->marginTop(), renderView));
- child->setMarginBottom(computeChildMarginValue(child->style()->marginBottom(), renderView));
+ child->setMarginTop(computeChildMarginValue(child->style()->marginTop()));
+ child->setMarginBottom(computeChildMarginValue(child->style()->marginBottom()));
}
}
}
@@ -861,7 +875,7 @@ LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, Layo
return std::max(childSize, minExtent);
}
-bool RenderFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool& hasInfiniteLineLength)
+bool RenderFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool& hasInfiniteLineLength, bool relayoutChildren)
{
orderedChildren.clear();
sumFlexBaseSize = 0;
@@ -882,7 +896,7 @@ bool RenderFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren
continue;
}
- LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(child, hasInfiniteLineLength);
+ LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(child, hasInfiniteLineLength, relayoutChildren);
LayoutUnit childMainAxisMarginBorderPadding = mainAxisBorderAndPaddingExtentForChild(child)
+ (isHorizontalFlow() ? child->marginWidth() : child->marginHeight());
LayoutUnit childFlexBaseSize = childMainAxisExtent + childMainAxisMarginBorderPadding;
@@ -916,9 +930,9 @@ void RenderFlexibleBox::freezeViolations(const Vector<Violation>& violations, La
}
// Returns true if we successfully ran the algorithm and sized the flex items.
-bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit>& childSizes, bool hasInfiniteLineLength)
+bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit, 16>& childSizes, bool hasInfiniteLineLength)
{
- childSizes.clear();
+ childSizes.resize(0);
LayoutUnit totalViolation = 0;
LayoutUnit usedFreeSpace = 0;
Vector<Violation> minViolations;
@@ -1006,7 +1020,7 @@ void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, Layout
LayoutUnit inlinePosition = isColumnFlow() ? crossAxisOffset : mainAxisOffset;
if (layoutMode == FlipForRowReverse && style()->flexDirection() == FlowRowReverse)
inlinePosition = mainAxisExtent() - mainAxisOffset;
- childLayer->setStaticInlinePosition(inlinePosition); // FIXME: Not right for regions.
+ childLayer->setStaticInlinePosition(inlinePosition);
LayoutUnit staticBlockPosition = isColumnFlow() ? mainAxisOffset : crossAxisOffset;
if (childLayer->staticBlockPosition() != staticBlockPosition) {
@@ -1016,18 +1030,18 @@ void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, Layout
}
}
-EAlignItems RenderFlexibleBox::alignmentForChild(RenderBox* child) const
+ItemPosition RenderFlexibleBox::alignmentForChild(RenderBox* child) const
{
- EAlignItems align = resolveAlignment(style(), child->style());
+ ItemPosition align = resolveAlignment(style(), child->style());
- if (align == AlignBaseline && hasOrthogonalFlow(child))
- align = AlignFlexStart;
+ if (align == ItemPositionBaseline && hasOrthogonalFlow(child))
+ align = ItemPositionFlexStart;
if (style()->flexWrap() == FlexWrapReverse) {
- if (align == AlignFlexStart)
- align = AlignFlexEnd;
- else if (align == AlignFlexEnd)
- align = AlignFlexStart;
+ if (align == ItemPositionFlexStart)
+ align = ItemPositionFlexEnd;
+ else if (align == ItemPositionFlexEnd)
+ align = ItemPositionFlexStart;
}
return align;
@@ -1044,22 +1058,33 @@ size_t RenderFlexibleBox::numberOfInFlowPositionedChildren(const OrderedFlexItem
return count;
}
-bool RenderFlexibleBox::needToStretchChild(RenderBox* child)
+void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox* child)
{
- if (alignmentForChild(child) != AlignStretch)
- return false;
-
- Length crossAxisLength = isHorizontalFlow() ? child->style()->height() : child->style()->width();
- return crossAxisLength.isAuto();
+ if (hasAutoMarginsInCrossAxis(child)) {
+ child->updateLogicalHeight();
+ if (isHorizontalFlow()) {
+ if (child->style()->marginTop().isAuto())
+ child->setMarginTop(0);
+ if (child->style()->marginBottom().isAuto())
+ child->setMarginBottom(0);
+ } else {
+ if (child->style()->marginLeft().isAuto())
+ child->setMarginLeft(0);
+ if (child->style()->marginRight().isAuto())
+ child->setMarginRight(0);
+ }
+ }
}
-void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox* child)
+bool RenderFlexibleBox::needToStretchChildLogicalHeight(RenderBox* child) const
{
- if (hasAutoMarginsInCrossAxis(child))
- child->updateLogicalHeight();
+ if (alignmentForChild(child) != ItemPositionStretch)
+ return false;
+
+ return isHorizontalFlow() && child->style()->height().isAuto();
}
-void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>& lineContexts)
+void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const Vector<LayoutUnit, 16>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>& lineContexts, bool hasInfiniteLineLength)
{
ASSERT(childSizes.size() == children.size());
@@ -1077,27 +1102,32 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons
bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow();
for (size_t i = 0; i < children.size(); ++i) {
RenderBox* child = children[i];
+
if (child->isOutOfFlowPositioned()) {
prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset, FlipForRowReverse);
continue;
}
+ // FIXME Investigate if this can be removed based on other flags. crbug.com/370010
+ child->setMayNeedPaintInvalidation(true);
+
LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
setLogicalOverrideSize(child, childPreferredSize);
- // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
- if (needToStretchChild(child) || childPreferredSize != mainAxisExtentForChild(child))
+ if (childPreferredSize != mainAxisExtentForChild(child)) {
child->setChildNeedsLayout(MarkOnlyThis);
- else {
+ } else {
// To avoid double applying margin changes in updateAutoMarginsInCrossAxis, we reset the margins here.
resetAutoMarginsAndLogicalTopInCrossAxis(child);
}
- updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
+ // We may have already forced relayout for orthogonal flowing children in preferredMainAxisContentExtentForChild.
+ bool forceChildRelayout = relayoutChildren && !childPreferredMainAxisContentExtentRequiresLayout(child, hasInfiniteLineLength);
+ updateBlockChildDirtyBitsBeforeLayout(forceChildRelayout, child);
child->layoutIfNeeded();
updateAutoMarginsInMainAxis(child, autoMarginOffset);
LayoutUnit childCrossAxisMarginBoxExtent;
- if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child)) {
+ if (alignmentForChild(child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(child)) {
LayoutUnit ascent = marginBoxAscentForChild(child);
LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent;
@@ -1105,8 +1135,9 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons
maxDescent = std::max(maxDescent, descent);
childCrossAxisMarginBoxExtent = maxAscent + maxDescent;
- } else
- childCrossAxisMarginBoxExtent = crossAxisExtentForChild(child) + crossAxisMarginExtentForChild(child);
+ } else {
+ childCrossAxisMarginBoxExtent = crossAxisIntrinsicExtentForChild(child) + crossAxisMarginExtentForChild(child);
+ }
if (!isColumnFlow())
setLogicalHeight(std::max(logicalHeight(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
maxChildCrossAxisExtent = std::max(maxChildCrossAxisExtent, childCrossAxisMarginBoxExtent);
@@ -1157,6 +1188,7 @@ void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children,
size_t seenInFlowPositionedChildren = 0;
for (size_t i = 0; i < children.size(); ++i) {
RenderBox* child = children[i];
+
if (child->isOutOfFlowPositioned()) {
child->layer()->setStaticBlockPosition(mainAxisOffset);
continue;
@@ -1175,6 +1207,8 @@ void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children,
static LayoutUnit initialAlignContentOffset(LayoutUnit availableFreeSpace, EAlignContent alignContent, unsigned numberOfLines)
{
+ if (numberOfLines <= 1)
+ return 0;
if (alignContent == AlignContentFlexEnd)
return availableFreeSpace;
if (alignContent == AlignContentCenter)
@@ -1201,7 +1235,15 @@ static LayoutUnit alignContentSpaceBetweenChildren(LayoutUnit availableFreeSpace
void RenderFlexibleBox::alignFlexLines(Vector<LineContext>& lineContexts)
{
- if (!isMultiline() || style()->alignContent() == AlignContentFlexStart)
+ // If we have a single line flexbox or a multiline line flexbox with only one flex line,
+ // 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 updateLogicalHeight.
+ if (lineContexts.size() == 1) {
+ lineContexts[0].crossAxisExtent = crossAxisContentExtent();
+ return;
+ }
+
+ if (style()->alignContent() == AlignContentFlexStart)
return;
LayoutUnit availableCrossAxisSpace = crossAxisContentExtent();
@@ -1260,25 +1302,25 @@ void RenderFlexibleBox::alignChildren(const Vector<LineContext>& lineContexts)
continue;
switch (alignmentForChild(child)) {
- case AlignAuto:
+ case ItemPositionAuto:
ASSERT_NOT_REACHED();
break;
- case AlignStretch: {
+ case ItemPositionStretch: {
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;
}
- case AlignFlexStart:
+ case ItemPositionFlexStart:
break;
- case AlignFlexEnd:
+ case ItemPositionFlexEnd:
adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
break;
- case AlignCenter:
+ case ItemPositionCenter:
adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
break;
- case AlignBaseline: {
+ case ItemPositionBaseline: {
// FIXME: If we get here in columns, we want the use the descent, except we currently can't get the ascent/descent of orthogonal children.
// https://bugs.webkit.org/show_bug.cgi?id=98076
LayoutUnit ascent = marginBoxAscentForChild(child);
@@ -1289,6 +1331,16 @@ void RenderFlexibleBox::alignChildren(const Vector<LineContext>& lineContexts)
minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
break;
}
+ case ItemPositionSelfStart:
+ case ItemPositionSelfEnd:
+ case ItemPositionStart:
+ case ItemPositionEnd:
+ case ItemPositionLeft:
+ case ItemPositionRight:
+ // FIXME: File a bug about implementing that. The extended grammar
+ // is not enabled by default so we shouldn't hit this codepath.
+ ASSERT_NOT_REACHED();
+ break;
}
}
minMarginAfterBaselines.append(minMarginAfterBaseline);
@@ -1304,7 +1356,7 @@ void RenderFlexibleBox::alignChildren(const Vector<LineContext>& lineContexts)
LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
ASSERT(child);
- if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child) && minMarginAfterBaseline)
+ if (alignmentForChild(child) == ItemPositionBaseline && !hasAutoMarginsInCrossAxis(child) && minMarginAfterBaseline)
adjustAlignmentForChild(child, minMarginAfterBaseline);
}
}
@@ -1315,9 +1367,10 @@ void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUni
if (!isColumnFlow() && child->style()->logicalHeight().isAuto()) {
// FIXME: If the child has orthogonal flow, then it already has an override height set, so use it.
if (!hasOrthogonalFlow(child)) {
- LayoutUnit stretchedLogicalHeight = child->logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
+ LayoutUnit heightBeforeStretching = needToStretchChildLogicalHeight(child) ? constrainedChildIntrinsicContentLogicalHeight(child) : child->logicalHeight();
+ LayoutUnit stretchedLogicalHeight = heightBeforeStretching + availableAlignmentSpaceForChildBeforeStretching(lineCrossAxisExtent, child);
ASSERT(!child->needsLayout());
- LayoutUnit desiredLogicalHeight = child->constrainLogicalHeightByMinMax(stretchedLogicalHeight, child->logicalHeight() - child->borderAndPaddingLogicalHeight());
+ LayoutUnit desiredLogicalHeight = child->constrainLogicalHeightByMinMax(stretchedLogicalHeight, heightBeforeStretching - child->borderAndPaddingLogicalHeight());
// FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
if (desiredLogicalHeight != child->logicalHeight()) {
@@ -1330,7 +1383,7 @@ void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUni
// FIXME: If the child doesn't have orthogonal flow, then it already has an override width set, so use it.
if (hasOrthogonalFlow(child)) {
LayoutUnit childWidth = std::max<LayoutUnit>(0, lineCrossAxisExtent - crossAxisMarginExtentForChild(child));
- childWidth = child->constrainLogicalWidthInRegionByMinMax(childWidth, childWidth, this);
+ childWidth = child->constrainLogicalWidthByMinMax(childWidth, childWidth, this);
if (childWidth != child->logicalWidth()) {
child->setOverrideLogicalContentWidth(childWidth - child->borderAndPaddingLogicalWidth());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.h
index c9297da7001..6a34e899c34 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFlexibleBox.h
@@ -47,8 +47,8 @@ public:
virtual bool isFlexibleBox() const OVERRIDE FINAL { return true; }
virtual bool avoidsFloats() const OVERRIDE FINAL { return true; }
- virtual bool canCollapseAnonymousBlockChild() const OVERRIDE FINAL { return false; }
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE FINAL;
+ virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return false; }
+ virtual void layoutBlock(bool relayoutChildren) OVERRIDE FINAL;
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual int firstLineBoxBaseline() const OVERRIDE;
@@ -61,9 +61,8 @@ public:
protected:
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual void removeChild(RenderObject*) OVERRIDE;
private:
enum FlexSign {
@@ -90,8 +89,10 @@ private:
bool isLeftToRightFlow() const;
bool isMultiline() const;
Length flexBasisForChild(RenderBox* child) const;
- void setCrossAxisExtent(LayoutUnit);
LayoutUnit crossAxisExtentForChild(RenderBox* child) const;
+ LayoutUnit crossAxisIntrinsicExtentForChild(RenderBox* child) const;
+ LayoutUnit childIntrinsicHeight(RenderBox* child) const;
+ LayoutUnit childIntrinsicWidth(RenderBox* child) const;
LayoutUnit mainAxisExtentForChild(RenderBox* child) const;
LayoutUnit crossAxisExtent() const;
LayoutUnit mainAxisExtent() const;
@@ -110,19 +111,19 @@ private:
LayoutUnit flowAwareMarginStartForChild(RenderBox* child) const;
LayoutUnit flowAwareMarginEndForChild(RenderBox* child) const;
LayoutUnit flowAwareMarginBeforeForChild(RenderBox* child) const;
- LayoutUnit flowAwareMarginAfterForChild(RenderBox* child) const;
LayoutUnit crossAxisMarginExtentForChild(RenderBox* child) const;
LayoutUnit crossAxisScrollbarExtent() const;
LayoutPoint flowAwareLocationForChild(RenderBox* child) const;
// FIXME: Supporting layout deltas.
void setFlowAwareLocationForChild(RenderBox* child, const LayoutPoint&);
void adjustAlignmentForChild(RenderBox* child, LayoutUnit);
- EAlignItems alignmentForChild(RenderBox* child) const;
+ ItemPosition alignmentForChild(RenderBox* child) const;
LayoutUnit mainAxisBorderAndPaddingExtentForChild(RenderBox* child) const;
- LayoutUnit mainAxisScrollbarExtentForChild(RenderBox* child) const;
- LayoutUnit preferredMainAxisContentExtentForChild(RenderBox* child, bool hasInfiniteLineLength);
+ LayoutUnit preferredMainAxisContentExtentForChild(RenderBox* child, bool hasInfiniteLineLength, bool relayoutChildren = false);
+ bool childPreferredMainAxisContentExtentRequiresLayout(RenderBox* child, bool hasInfiniteLineLength) const;
+ bool needToStretchChildLogicalHeight(RenderBox* child) const;
- void layoutFlexItems(bool relayoutChildren, Vector<LineContext>&);
+ void layoutFlexItems(bool relayoutChildren);
LayoutUnit autoMarginOffsetInMainAxis(const OrderedFlexItemList&, LayoutUnit& availableFreeSpace);
void updateAutoMarginsInMainAxis(RenderBox* child, LayoutUnit autoMarginOffset);
bool hasAutoMarginsInCrossAxis(RenderBox* child) const;
@@ -133,23 +134,23 @@ private:
void repaintChildrenDuringLayoutIfMoved(const ChildFrameRects&);
LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox*);
+ LayoutUnit availableAlignmentSpaceForChildBeforeStretching(LayoutUnit lineCrossAxisExtent, RenderBox*);
LayoutUnit marginBoxAscentForChild(RenderBox*);
- LayoutUnit computeChildMarginValue(Length margin, RenderView*);
+ LayoutUnit computeChildMarginValue(Length margin);
void prepareOrderIteratorAndMargins();
LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize);
// The hypothetical main size of an item is the flex base size clamped according to its min and max main size properties
- bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool& hasInfiniteLineLength);
+ bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool& hasInfiniteLineLength, bool relayoutChildren);
- bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit>& childSizes, bool hasInfiniteLineLength);
+ bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit, 16>& childSizes, bool hasInfiniteLineLength);
void freezeViolations(const Vector<Violation>&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, bool hasInfiniteLineLength);
void resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox*);
- bool needToStretchChild(RenderBox*);
void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode);
size_t numberOfInFlowPositionedChildren(const OrderedFlexItemList&) const;
- void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList&, const Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>&);
+ void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList&, const Vector<LayoutUnit, 16>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>&, bool hasInfiniteLineLength);
void layoutColumnReverse(const OrderedFlexItemList&, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace);
void alignFlexLines(Vector<LineContext>&);
void alignChildren(const Vector<LineContext>&);
@@ -157,6 +158,9 @@ private:
void flipForRightToLeftColumn();
void flipForWrapReverse(const Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
+ // This is used to cache the preferred size for orthogonal flow children so we don't have to relayout to get it
+ HashMap<const RenderObject*, LayoutUnit> m_intrinsicSizeAlongMainAxis;
+
mutable OrderIterator m_orderIterator;
int m_numberOfInFlowChildrenOnFirstLine;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.cpp
index 2e9bb88992a..f239e9e5467 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.cpp
@@ -35,9 +35,7 @@
#include "core/rendering/FlowThreadController.h"
#include "core/rendering/HitTestRequest.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
-#include "core/rendering/RenderBoxRegionInfo.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderRegion.h"
@@ -49,59 +47,13 @@ namespace WebCore {
RenderFlowThread::RenderFlowThread()
: RenderBlockFlow(0)
- , m_previousRegionCount(0)
- , m_autoLogicalHeightRegionsCount(0)
, m_regionsInvalidated(false)
- , m_regionsHaveUniformLogicalWidth(true)
, m_regionsHaveUniformLogicalHeight(true)
- , m_hasRegionsWithStyling(false)
- , m_dispatchRegionLayoutUpdateEvent(false)
- , m_dispatchRegionOversetChangeEvent(false)
, m_pageLogicalSizeChanged(false)
- , m_inConstrainedLayoutPhase(false)
- , m_needsTwoPhasesLayout(false)
{
setFlowThreadState(InsideOutOfFlowThread);
}
-PassRefPtr<RenderStyle> RenderFlowThread::createFlowThreadStyle(RenderStyle* parentStyle)
-{
- RefPtr<RenderStyle> newStyle(RenderStyle::create());
- newStyle->inheritFrom(parentStyle);
- newStyle->setDisplay(BLOCK);
- newStyle->setPosition(AbsolutePosition);
- newStyle->setZIndex(0);
- newStyle->setLeft(Length(0, Fixed));
- newStyle->setTop(Length(0, Fixed));
- newStyle->setWidth(Length(100, Percent));
- newStyle->setHeight(Length(100, Percent));
- newStyle->font().update(0);
-
- return newStyle.release();
-}
-
-void RenderFlowThread::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderBlock::styleDidChange(diff, oldStyle);
-
- if (oldStyle && oldStyle->writingMode() != style()->writingMode())
- invalidateRegions();
-}
-
-void RenderFlowThread::removeFlowChildInfo(RenderObject* child)
-{
- if (child->isBox())
- removeRenderBoxRegionInfo(toRenderBox(child));
- clearRenderObjectCustomStyle(child);
-}
-
-void RenderFlowThread::addRegionToThread(RenderRegion* renderRegion)
-{
- ASSERT(renderRegion);
- m_regionList.add(renderRegion);
- renderRegion->setIsValid(true);
-}
-
void RenderFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
{
ASSERT(renderRegion);
@@ -116,9 +68,7 @@ void RenderFlowThread::invalidateRegions()
}
m_regionRangeMap.clear();
- m_breakBeforeToRegionMap.clear();
- m_breakAfterToRegionMap.clear();
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
m_regionsInvalidated = true;
}
@@ -148,42 +98,24 @@ void RenderFlowThread::validateRegions()
{
if (m_regionsInvalidated) {
m_regionsInvalidated = false;
- m_regionsHaveUniformLogicalWidth = true;
m_regionsHaveUniformLogicalHeight = true;
if (hasRegions()) {
- LayoutUnit previousRegionLogicalWidth = 0;
LayoutUnit previousRegionLogicalHeight = 0;
bool firstRegionVisited = false;
for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
RenderRegion* region = *iter;
- ASSERT(!region->needsLayout() || region->isRenderRegionSet());
-
- region->deleteAllRenderBoxRegionInfo();
-
- // In the normal layout phase we need to initialize the computedAutoHeight for auto-height regions.
- // See initializeRegionsComputedAutoHeight for the explanation.
- // Also, if we have auto-height regions we can't assume m_regionsHaveUniformLogicalHeight to be true in the first phase
- // because the auto-height regions don't have their height computed yet.
- if (!inConstrainedLayoutPhase() && region->hasAutoLogicalHeight()) {
- region->setComputedAutoHeight(region->maxPageLogicalHeight());
- m_regionsHaveUniformLogicalHeight = false;
- }
-
- LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
LayoutUnit regionLogicalHeight = region->pageLogicalHeight();
if (!firstRegionVisited) {
firstRegionVisited = true;
} else {
- if (m_regionsHaveUniformLogicalWidth && previousRegionLogicalWidth != regionLogicalWidth)
- m_regionsHaveUniformLogicalWidth = false;
if (m_regionsHaveUniformLogicalHeight && previousRegionLogicalHeight != regionLogicalHeight)
m_regionsHaveUniformLogicalHeight = false;
}
- previousRegionLogicalWidth = regionLogicalWidth;
+ previousRegionLogicalHeight = regionLogicalHeight;
}
}
}
@@ -194,54 +126,12 @@ void RenderFlowThread::validateRegions()
void RenderFlowThread::layout()
{
- LayoutRectRecorder recorder(*this);
m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout();
- // In case this is the second pass of the normal phase we need to update the auto-height regions to their initial value.
- // If the region chain was invalidated this will happen anyway.
- if (!m_regionsInvalidated && !inConstrainedLayoutPhase())
- initializeRegionsComputedAutoHeight();
-
- validateRegions();
-
- // This is the first phase of the layout and because we have auto-height regions we'll need a second
- // pass to update the flow with the computed auto-height regions.
- m_needsTwoPhasesLayout = !inConstrainedLayoutPhase() && hasAutoLogicalHeightRegions();
-
CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
RenderBlockFlow::layout();
m_pageLogicalSizeChanged = false;
-
- if (lastRegion())
- lastRegion()->expandToEncompassFlowThreadContentsIfNeeded();
-
- if (shouldDispatchRegionLayoutUpdateEvent())
- dispatchRegionLayoutUpdateEvent();
-
- if (shouldDispatchRegionOversetChangeEvent())
- dispatchRegionOversetChangeEvent();
-}
-
-void RenderFlowThread::updateLogicalWidth()
-{
- LayoutUnit logicalWidth = initialLogicalWidth();
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- ASSERT(!region->needsLayout() || region->isRenderRegionSet());
- logicalWidth = max(region->pageLogicalWidth(), logicalWidth);
- }
- setLogicalWidth(logicalWidth);
-
- // If the regions have non-uniform logical widths, then insert inset information for the RenderFlowThread.
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
- if (regionLogicalWidth != logicalWidth) {
- LayoutUnit logicalLeft = style()->direction() == LTR ? LayoutUnit() : logicalWidth - regionLogicalWidth;
- region->setRenderBoxRegionInfo(this, logicalLeft, regionLogicalWidth, false);
- }
- }
}
void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
@@ -251,104 +141,15 @@ void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, L
for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
RenderRegion* region = *iter;
- ASSERT(!region->needsLayout() || region->isRenderRegionSet());
-
computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent();
}
}
-LayoutRect RenderFlowThread::computeRegionClippingRect(const LayoutPoint& offset, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect) const
-{
- LayoutRect regionClippingRect(offset + (flowThreadPortionOverflowRect.location() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size());
- if (style()->isFlippedBlocksWritingMode())
- regionClippingRect.move(flowThreadPortionRect.size() - flowThreadPortionOverflowRect.size());
- return regionClippingRect;
-}
-
-void RenderFlowThread::paintFlowThreadPortionInRegion(PaintInfo& paintInfo, RenderRegion* region, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& paintOffset) const
-{
- GraphicsContext* context = paintInfo.context;
- if (!context)
- return;
-
- // RenderFlowThread should start painting its content in a position that is offset
- // from the region rect's current position. The amount of offset is equal to the location of
- // the flow thread portion in the flow thread's local coordinates.
- // Note that we have to pixel snap the location at which we're going to paint, since this is necessary
- // to minimize the amount of incorrect snapping that would otherwise occur.
- // If we tried to paint by applying a non-integral translation, then all the
- // layout code that attempted to pixel snap would be incorrect.
- IntPoint adjustedPaintOffset;
- LayoutPoint portionLocation;
- if (style()->isFlippedBlocksWritingMode()) {
- LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
- flipForWritingMode(flippedFlowThreadPortionRect);
- portionLocation = flippedFlowThreadPortionRect.location();
- } else {
- portionLocation = flowThreadPortionRect.location();
- }
- adjustedPaintOffset = roundedIntPoint(paintOffset - portionLocation);
-
- // The clipping rect for the region is set up by assuming the flowThreadPortionRect is going to paint offset from adjustedPaintOffset.
- // Remember that we pixel snapped and moved the paintOffset and stored the snapped result in adjustedPaintOffset. Now we add back in
- // the flowThreadPortionRect's location to get the spot where we expect the portion to actually paint. This can be non-integral and
- // that's ok. We then pixel snap the resulting clipping rect to account for snapping that will occur when the flow thread paints.
- IntRect regionClippingRect = pixelSnappedIntRect(computeRegionClippingRect(adjustedPaintOffset + portionLocation, flowThreadPortionRect, flowThreadPortionOverflowRect));
-
- PaintInfo info(paintInfo);
- info.rect.intersect(regionClippingRect);
-
- if (!info.rect.isEmpty()) {
- context->save();
-
- context->clip(regionClippingRect);
-
- context->translate(adjustedPaintOffset.x(), adjustedPaintOffset.y());
- info.rect.moveBy(-adjustedPaintOffset);
-
- if (info.phase == PaintPhaseTextClip)
- info.paintBehavior = PaintBehaviorForceBlackText;
-
- layer()->paint(context, info.rect, info.paintBehavior, 0, region, PaintLayerTemporaryClipRects);
-
- context->restore();
- }
-}
-
bool RenderFlowThread::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
if (hitTestAction == HitTestBlockBackground)
return false;
- return RenderBlock::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction);
-}
-
-bool RenderFlowThread::hitTestFlowThreadPortionInRegion(RenderRegion* region, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
-{
- LayoutRect regionClippingRect = computeRegionClippingRect(accumulatedOffset, flowThreadPortionRect, flowThreadPortionOverflowRect);
- if (!regionClippingRect.contains(locationInContainer.point()))
- return false;
-
- LayoutSize renderFlowThreadOffset;
- if (style()->isFlippedBlocksWritingMode()) {
- LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
- flipForWritingMode(flippedFlowThreadPortionRect);
- renderFlowThreadOffset = accumulatedOffset - flippedFlowThreadPortionRect.location();
- } else {
- renderFlowThreadOffset = accumulatedOffset - flowThreadPortionRect.location();
- }
-
- // Always ignore clipping, since the RenderFlowThread has nothing to do with the bounds of the FrameView.
- HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
-
- // Make a new temporary HitTestLocation in the new region.
- HitTestLocation newHitTestLocation(locationInContainer, -renderFlowThreadOffset, region);
-
- bool isPointInsideFlowThread = layer()->hitTest(newRequest, newHitTestLocation, result);
-
- // FIXME: Should we set result.m_localPoint back to the RenderRegion's coordinate space or leave it in the RenderFlowThread's coordinate
- // space? Right now it's staying in the RenderFlowThread's coordinate space, which may end up being ok. We will know more when we get around to
- // patching positionForPoint.
- return isPointInsideFlowThread;
+ return RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction);
}
bool RenderFlowThread::shouldRepaint(const LayoutRect& r) const
@@ -364,7 +165,7 @@ void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect)
if (!shouldRepaint(repaintRect) || !hasValidRegionInfo())
return;
- LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the regions are somewhere else.
+ ForceHorriblySlowRectMapping slowRectMapping(*this); // We can't use layout state to repaint, since the regions are somewhere else.
// We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
// Let each region figure out the proper enclosing flow thread.
@@ -377,13 +178,10 @@ void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect)
}
}
-RenderRegion* RenderFlowThread::regionAtBlockOffset(LayoutUnit offset, bool extendLastRegion, RegionAutoGenerationPolicy autoGenerationPolicy)
+RenderRegion* RenderFlowThread::regionAtBlockOffset(LayoutUnit offset) const
{
ASSERT(!m_regionsInvalidated);
- if (autoGenerationPolicy == AllowRegionAutoGeneration)
- autoGenerateRegionsToBlockOffset(offset);
-
if (offset <= 0)
return m_regionList.isEmpty() ? 0 : m_regionList.first();
@@ -391,38 +189,12 @@ RenderRegion* RenderFlowThread::regionAtBlockOffset(LayoutUnit offset, bool exte
m_regionIntervalTree.allOverlapsWithAdapter<RegionSearchAdapter>(adapter);
// If no region was found, the offset is in the flow thread overflow.
- // The last region will contain the offset if extendLastRegion is set or if the last region is a set.
- if (!adapter.result() && !m_regionList.isEmpty() && (extendLastRegion || m_regionList.last()->isRenderRegionSet()))
+ if (!adapter.result() && !m_regionList.isEmpty())
return m_regionList.last();
return adapter.result();
}
-RenderRegion* RenderFlowThread::regionFromAbsolutePointAndBox(IntPoint absolutePoint, const RenderBox* flowedBox)
-{
- if (!flowedBox)
- return 0;
-
- RenderRegion* startRegion = 0;
- RenderRegion* endRegion = 0;
- getRegionRangeForBox(flowedBox, startRegion, endRegion);
-
- if (!startRegion)
- return 0;
-
- for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- IntRect regionAbsoluteRect(roundedIntPoint(region->localToAbsolute()), roundedIntSize(region->frameRect().size()));
- if (regionAbsoluteRect.contains(absolutePoint))
- return region;
-
- if (region == endRegion)
- break;
- }
-
- return 0;
-}
-
LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject& boxModelObject, const LayoutPoint& startPoint)
{
LayoutPoint referencePoint = startPoint;
@@ -430,9 +202,8 @@ LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
// FIXME: This needs to be adapted for different writing modes inside the flow thread.
RenderRegion* startRegion = regionAtBlockOffset(referencePoint.y());
if (startRegion) {
- RenderBoxModelObject* startRegionBox = startRegion->isRenderNamedFlowFragment() ? toRenderBoxModelObject(startRegion->parent()) : startRegion;
// Take into account the offset coordinates of the region.
- RenderObject* currObject = startRegionBox;
+ RenderObject* currObject = startRegion;
RenderObject* currOffsetParentRenderer;
Element* currOffsetParentElement;
while ((currOffsetParentElement = currObject->offsetParent()) && (currOffsetParentRenderer = currOffsetParentElement->renderer())) {
@@ -452,7 +223,7 @@ LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
// and is no longer valid) and recompute it using the region in which it flows as reference.
bool wasComputedRelativeToOtherRegion = false;
const RenderBlock* objContainingBlock = boxModelObject.containingBlock();
- while (objContainingBlock && !objContainingBlock->isRenderNamedFlowThread()) {
+ while (objContainingBlock) {
// Check if this object is in a different region.
RenderRegion* parentStartRegion = 0;
RenderRegion* parentEndRegion = 0;
@@ -465,12 +236,6 @@ LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
}
if (wasComputedRelativeToOtherRegion) {
- if (boxModelObject.isBox()) {
- // Use borderBoxRectInRegion to account for variations such as percentage margins.
- LayoutRect borderBoxRect = toRenderBox(&boxModelObject)->borderBoxRectInRegion(startRegion, RenderBox::DoNotCacheRenderBoxRegionInfo);
- referencePoint.move(borderBoxRect.location().x(), 0);
- }
-
// Get the logical top coordinate of the current object.
LayoutUnit top = 0;
if (boxModelObject.isRenderBlock()) {
@@ -489,7 +254,7 @@ LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
// and compute the object's top, relative to the region's top.
LayoutUnit regionLogicalTop = startRegion->pageLogicalTopForOffset(top);
LayoutUnit topRelativeToRegion = top - regionLogicalTop;
- referencePoint.setY(startRegionBox->offsetTop() + topRelativeToRegion);
+ referencePoint.setY(startRegion->offsetTop() + topRelativeToRegion);
// Since the top has been overriden, check if the
// relative/sticky positioning must be reconsidered.
@@ -501,7 +266,7 @@ LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
// Since we're looking for the offset relative to the body, we must also
// take into consideration the borders of the region.
- referencePoint.move(startRegionBox->borderLeft(), startRegionBox->borderTop());
+ referencePoint.move(startRegion->borderLeft(), startRegion->borderTop());
}
return referencePoint;
@@ -513,12 +278,6 @@ LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset)
return region ? region->pageLogicalTopForOffset(offset) : LayoutUnit();
}
-LayoutUnit RenderFlowThread::pageLogicalWidthForOffset(LayoutUnit offset)
-{
- RenderRegion* region = regionAtBlockOffset(offset, true);
- return region ? region->pageLogicalWidth() : contentLogicalWidth();
-}
-
LayoutUnit RenderFlowThread::pageLogicalHeightForOffset(LayoutUnit offset)
{
RenderRegion* region = regionAtBlockOffset(offset);
@@ -546,125 +305,6 @@ LayoutUnit RenderFlowThread::pageRemainingLogicalHeightForOffset(LayoutUnit offs
return remainingHeight;
}
-RenderRegion* RenderFlowThread::mapFromFlowToRegion(TransformState& transformState) const
-{
- if (!hasValidRegionInfo())
- return 0;
-
- LayoutRect boxRect = transformState.mappedQuad().enclosingBoundingBox();
- flipForWritingMode(boxRect);
-
- // FIXME: We need to refactor RenderObject::absoluteQuads to be able to split the quads across regions,
- // for now we just take the center of the mapped enclosing box and map it to a region.
- // Note: Using the center in order to avoid rounding errors.
-
- LayoutPoint center = boxRect.center();
- RenderRegion* renderRegion = const_cast<RenderFlowThread*>(this)->regionAtBlockOffset(isHorizontalWritingMode() ? center.y() : center.x(), true, DisallowRegionAutoGeneration);
- if (!renderRegion)
- return 0;
-
- LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect());
- flipForWritingMode(flippedRegionRect);
-
- transformState.move(renderRegion->contentBoxRect().location() - flippedRegionRect.location());
-
- return renderRegion;
-}
-
-void RenderFlowThread::removeRenderBoxRegionInfo(RenderBox* box)
-{
- if (!hasRegions())
- return;
-
- // If the region chain was invalidated the next layout will clear the box information from all the regions.
- if (m_regionsInvalidated) {
- ASSERT(selfNeedsLayout());
- return;
- }
-
- RenderRegion* startRegion;
- RenderRegion* endRegion;
- getRegionRangeForBox(box, startRegion, endRegion);
-
- for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- region->removeRenderBoxRegionInfo(box);
- if (region == endRegion)
- break;
- }
-
-#ifndef NDEBUG
- // 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;
- ASSERT(!region->renderBoxRegionInfo(box));
- }
-#endif
-
- m_regionRangeMap.remove(box);
-}
-
-bool RenderFlowThread::logicalWidthChangedInRegionsForBlock(const RenderBlock* block)
-{
- if (!hasRegions())
- return false;
-
- RenderRegion* startRegion;
- RenderRegion* endRegion;
- getRegionRangeForBox(block, startRegion, endRegion);
-
- // When the region chain is invalidated the box information is discarded so we must assume the width has changed.
- if (m_pageLogicalSizeChanged && !startRegion)
- return true;
-
- // Not necessary for the flow thread, since we already computed the correct info for it.
- if (block == this)
- return false;
-
- for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- ASSERT(!region->needsLayout() || region->isRenderRegionSet());
-
- OwnPtr<RenderBoxRegionInfo> oldInfo = region->takeRenderBoxRegionInfo(block);
- if (!oldInfo)
- continue;
-
- LayoutUnit oldLogicalWidth = oldInfo->logicalWidth();
- RenderBoxRegionInfo* newInfo = block->renderBoxRegionInfo(region);
- if (!newInfo || newInfo->logicalWidth() != oldLogicalWidth)
- return true;
-
- if (region == endRegion)
- break;
- }
-
- return false;
-}
-
-LayoutUnit RenderFlowThread::contentLogicalWidthOfFirstRegion() const
-{
- RenderRegion* firstValidRegionInFlow = firstRegion();
- if (!firstValidRegionInFlow)
- return 0;
- return isHorizontalWritingMode() ? firstValidRegionInFlow->contentWidth() : firstValidRegionInFlow->contentHeight();
-}
-
-LayoutUnit RenderFlowThread::contentLogicalHeightOfFirstRegion() const
-{
- RenderRegion* firstValidRegionInFlow = firstRegion();
- if (!firstValidRegionInFlow)
- return 0;
- return isHorizontalWritingMode() ? firstValidRegionInFlow->contentHeight() : firstValidRegionInFlow->contentWidth();
-}
-
-LayoutUnit RenderFlowThread::contentLogicalLeftOfFirstRegion() const
-{
- RenderRegion* firstValidRegionInFlow = firstRegion();
- if (!firstValidRegionInFlow)
- return 0;
- return isHorizontalWritingMode() ? firstValidRegionInFlow->flowThreadPortionRect().x() : firstValidRegionInFlow->flowThreadPortionRect().y();
-}
-
RenderRegion* RenderFlowThread::firstRegion() const
{
if (!hasValidRegionInfo())
@@ -679,44 +319,17 @@ RenderRegion* RenderFlowThread::lastRegion() const
return m_regionList.last();
}
-void RenderFlowThread::clearRenderObjectCustomStyle(const RenderObject* object,
- const RenderRegion* oldStartRegion, const RenderRegion* oldEndRegion,
- const RenderRegion* newStartRegion, const RenderRegion* newEndRegion)
-{
- // Clear the styles for the object in the regions.
- // The styles are not cleared for the regions that are contained in both ranges.
- bool insideOldRegionRange = false;
- bool insideNewRegionRange = false;
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
-
- if (oldStartRegion == region)
- insideOldRegionRange = true;
- if (newStartRegion == region)
- insideNewRegionRange = true;
-
- if (!(insideOldRegionRange && insideNewRegionRange))
- region->clearObjectStyleInRegion(object);
-
- if (oldEndRegion == region)
- insideOldRegionRange = false;
- if (newEndRegion == region)
- insideNewRegionRange = false;
- }
-}
-
void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit offsetFromLogicalTopOfFirstPage)
{
if (!hasRegions())
return;
// FIXME: Not right for differing writing-modes.
- RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage, true);
- RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage + box->logicalHeight(), true);
+ RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage);
+ RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage + box->logicalHeight());
RenderRegionRangeMap::iterator it = m_regionRangeMap.find(box);
if (it == m_regionRangeMap.end()) {
m_regionRangeMap.set(box, RenderRegionRange(startRegion, endRegion));
- clearRenderObjectCustomStyle(box);
return;
}
@@ -725,21 +338,6 @@ void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit off
if (range.startRegion() == startRegion && range.endRegion() == endRegion)
return;
- // Delete any info that we find before our new startRegion and after our new endRegion.
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- if (region == startRegion) {
- iter = m_regionList.find(endRegion);
- continue;
- }
-
- region->removeRenderBoxRegionInfo(box);
-
- if (region == range.endRegion())
- break;
- }
-
- clearRenderObjectCustomStyle(box, range.startRegion(), range.endRegion(), startRegion, endRegion);
range.setRange(startRegion, endRegion);
}
@@ -757,148 +355,15 @@ void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*&
ASSERT(m_regionList.contains(startRegion) && m_regionList.contains(endRegion));
}
-void RenderFlowThread::applyBreakAfterContent(LayoutUnit clientHeight)
-{
- // Simulate a region break at height. If it points inside an auto logical height region,
- // then it may determine the region computed autoheight.
- addForcedRegionBreak(clientHeight, this, false);
-}
-
-bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const
-{
- ASSERT(targetRegion);
-
- for (RenderRegionList::const_iterator it = m_regionList.find(const_cast<RenderRegion*>(startRegion)); it != m_regionList.end(); ++it) {
- const RenderRegion* currRegion = *it;
- if (targetRegion == currRegion)
- return true;
- if (currRegion == endRegion)
- break;
- }
-
- return false;
-}
-
-// Check if the content is flown into at least a region with region styling rules.
-void RenderFlowThread::checkRegionsWithStyling()
-{
- bool hasRegionsWithStyling = false;
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- if (region->hasCustomRegionStyle()) {
- hasRegionsWithStyling = true;
- break;
- }
- }
- m_hasRegionsWithStyling = hasRegionsWithStyling;
-}
-
-bool RenderFlowThread::objectInFlowRegion(const RenderObject* object, const RenderRegion* region) const
-{
- ASSERT(object);
- ASSERT(region);
-
- RenderFlowThread* flowThread = object->flowThreadContainingBlock();
- if (flowThread != this)
- return false;
- if (!m_regionList.contains(const_cast<RenderRegion*>(region)))
- return false;
-
- RenderBox* enclosingBox = object->enclosingBox();
- RenderRegion* enclosingBoxStartRegion = 0;
- RenderRegion* enclosingBoxEndRegion = 0;
- getRegionRangeForBox(enclosingBox, enclosingBoxStartRegion, enclosingBoxEndRegion);
- if (!regionInRange(region, enclosingBoxStartRegion, enclosingBoxEndRegion))
- return false;
-
- if (object->isBox())
- return true;
-
- LayoutRect objectABBRect = object->absoluteBoundingBoxRect(true);
- if (!objectABBRect.width())
- objectABBRect.setWidth(1);
- if (!objectABBRect.height())
- objectABBRect.setHeight(1);
- if (objectABBRect.intersects(region->absoluteBoundingBoxRect(true)))
- return true;
-
- if (region == lastRegion()) {
- // If the object does not intersect any of the enclosing box regions
- // then the object is in last region.
- for (RenderRegionList::const_iterator it = m_regionList.find(enclosingBoxStartRegion); it != m_regionList.end(); ++it) {
- const RenderRegion* currRegion = *it;
- if (currRegion == region)
- break;
- if (objectABBRect.intersects(currRegion->absoluteBoundingBoxRect(true)))
- return false;
- }
- return true;
- }
-
- return false;
-}
-
-#ifndef NDEBUG
-bool RenderFlowThread::isAutoLogicalHeightRegionsCountConsistent() const
-{
- unsigned autoLogicalHeightRegions = 0;
- for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- const RenderRegion* region = *iter;
- if (region->hasAutoLogicalHeight())
- autoLogicalHeightRegions++;
- }
-
- return autoLogicalHeightRegions == m_autoLogicalHeightRegionsCount;
-}
-#endif
-
-// During the normal layout phase of the named flow the regions are initialized with a height equal to their max-height.
-// This way unforced breaks are automatically placed when a region is full and the content height/position correctly estimated.
-// Also, the region where a forced break falls is exactly the region found at the forced break offset inside the flow content.
-void RenderFlowThread::initializeRegionsComputedAutoHeight(RenderRegion* startRegion)
-{
- ASSERT(!inConstrainedLayoutPhase());
- if (!hasAutoLogicalHeightRegions())
- return;
-
- RenderRegionList::iterator regionIter = startRegion ? m_regionList.find(startRegion) : m_regionList.begin();
- for (; regionIter != m_regionList.end(); ++regionIter) {
- RenderRegion* region = *regionIter;
- if (region->hasAutoLogicalHeight())
- region->setComputedAutoHeight(region->maxPageLogicalHeight());
- }
-}
-
-void RenderFlowThread::markAutoLogicalHeightRegionsForLayout()
+void RenderFlowThread::updateRegionsFlowThreadPortionRect()
{
- ASSERT(hasAutoLogicalHeightRegions());
-
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- if (!region->hasAutoLogicalHeight())
- continue;
-
- // FIXME: We need to find a way to avoid marking all the regions ancestors for layout
- // as we are already inside layout.
- region->setNeedsLayout();
- }
-}
-
-void RenderFlowThread::updateRegionsFlowThreadPortionRect(const RenderRegion* lastRegionWithContent)
-{
- ASSERT(!lastRegionWithContent || (!inConstrainedLayoutPhase() && hasAutoLogicalHeightRegions()));
LayoutUnit logicalHeight = 0;
- bool emptyRegionsSegment = false;
// FIXME: Optimize not to clear the interval all the time. This implies manually managing the tree nodes lifecycle.
m_regionIntervalTree.clear();
m_regionIntervalTree.initIfNeeded();
for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
RenderRegion* region = *iter;
- // If we find an empty auto-height region, clear the computedAutoHeight value.
- if (emptyRegionsSegment && region->hasAutoLogicalHeight())
- region->clearComputedAutoHeight();
-
LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
LayoutUnit regionLogicalHeight = std::min<LayoutUnit>(RenderFlowThread::maxLogicalHeight() - logicalHeight, region->logicalHeightOfAllFlowThreadContent());
@@ -909,104 +374,7 @@ void RenderFlowThread::updateRegionsFlowThreadPortionRect(const RenderRegion* la
m_regionIntervalTree.add(RegionIntervalTree::createInterval(logicalHeight, logicalHeight + regionLogicalHeight, region));
logicalHeight += regionLogicalHeight;
-
- // Once we find the last region with content the next regions are considered empty.
- if (lastRegionWithContent == region)
- emptyRegionsSegment = true;
}
-
- ASSERT(!lastRegionWithContent || emptyRegionsSegment);
-}
-
-// Even if we require the break to occur at offsetBreakInFlowThread, because regions may have min/max-height values,
-// it is possible that the break will occur at a different offset than the original one required.
-// offsetBreakAdjustment measures the different between the requested break offset and the current break offset.
-bool RenderFlowThread::addForcedRegionBreak(LayoutUnit offsetBreakInFlowThread, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment)
-{
- // We take breaks into account for height computation for auto logical height regions
- // only in the layout phase in which we lay out the flows threads unconstrained
- // and we use the content breaks to determine the computedAutoHeight for
- // auto logical height regions.
- if (inConstrainedLayoutPhase())
- return false;
-
- // Breaks can come before or after some objects. We need to track these objects, so that if we get
- // multiple breaks for the same object (for example because of multiple layouts on the same object),
- // we need to invalidate every other region after the old one and start computing from fresh.
- RenderObjectToRegionMap& mapToUse = isBefore ? m_breakBeforeToRegionMap : m_breakAfterToRegionMap;
- RenderObjectToRegionMap::iterator iter = mapToUse.find(breakChild);
- if (iter != mapToUse.end()) {
- RenderRegionList::iterator regionIter = m_regionList.find(iter->value);
- ASSERT_WITH_SECURITY_IMPLICATION(regionIter != m_regionList.end());
- ASSERT((*regionIter)->hasAutoLogicalHeight());
- initializeRegionsComputedAutoHeight(*regionIter);
-
- // We need to update the regions flow thread portion rect because we are going to process
- // a break on these regions.
- updateRegionsFlowThreadPortionRect();
- }
-
- // Simulate a region break at offsetBreakInFlowThread. If it points inside an auto logical height region,
- // then it determines the region computed auto height.
- RenderRegion* region = regionAtBlockOffset(offsetBreakInFlowThread);
- if (!region)
- return false;
-
- bool lastBreakAfterContent = breakChild == this;
- bool hasComputedAutoHeight = false;
-
- LayoutUnit currentRegionOffsetInFlowThread = isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x();
- LayoutUnit offsetBreakInCurrentRegion = offsetBreakInFlowThread - currentRegionOffsetInFlowThread;
-
- if (region->hasAutoLogicalHeight()) {
- // A forced break can appear only in an auto-height region that didn't have a forced break before.
- // This ASSERT is a good-enough heuristic to verify the above condition.
- ASSERT(region->maxPageLogicalHeight() == region->computedAutoHeight());
-
- mapToUse.set(breakChild, region);
-
- hasComputedAutoHeight = true;
-
- // Compute the region height pretending that the offsetBreakInCurrentRegion is the logicalHeight for the auto-height region.
- LayoutUnit regionComputedAutoHeight = region->constrainContentBoxLogicalHeightByMinMax(offsetBreakInCurrentRegion, -1);
-
- // The new height of this region needs to be smaller than the initial value, the max height. A forced break is the only way to change the initial
- // height of an auto-height region besides content ending.
- ASSERT(regionComputedAutoHeight <= region->maxPageLogicalHeight());
-
- region->setComputedAutoHeight(regionComputedAutoHeight);
-
- currentRegionOffsetInFlowThread += regionComputedAutoHeight;
- } else {
- currentRegionOffsetInFlowThread += isHorizontalWritingMode() ? region->flowThreadPortionRect().height() : region->flowThreadPortionRect().width();
- }
-
- // If the break was found inside an auto-height region its size changed so we need to recompute the flow thread portion rectangles.
- // Also, if this is the last break after the content we need to clear the computedAutoHeight value on the last empty regions.
- if (hasAutoLogicalHeightRegions() && lastBreakAfterContent)
- updateRegionsFlowThreadPortionRect(region);
- else if (hasComputedAutoHeight)
- updateRegionsFlowThreadPortionRect();
-
- if (offsetBreakAdjustment)
- *offsetBreakAdjustment = max<LayoutUnit>(0, currentRegionOffsetInFlowThread - offsetBreakInFlowThread);
-
- return hasComputedAutoHeight;
-}
-
-void RenderFlowThread::incrementAutoLogicalHeightRegions()
-{
- if (!m_autoLogicalHeightRegionsCount)
- view()->flowThreadController()->incrementFlowThreadsWithAutoLogicalHeightRegions();
- ++m_autoLogicalHeightRegionsCount;
-}
-
-void RenderFlowThread::decrementAutoLogicalHeightRegions()
-{
- ASSERT(m_autoLogicalHeightRegionsCount > 0);
- --m_autoLogicalHeightRegionsCount;
- if (!m_autoLogicalHeightRegionsCount)
- view()->flowThreadController()->decrementFlowThreadsWithAutoLogicalHeightRegions();
}
void RenderFlowThread::collectLayerFragments(LayerFragments& layerFragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
@@ -1070,18 +438,18 @@ const RenderBox* RenderFlowThread::currentStatePusherRenderBox() const
return 0;
}
-void RenderFlowThread::pushFlowThreadLayoutState(const RenderObject* object)
+void RenderFlowThread::pushFlowThreadLayoutState(const RenderObject& object)
{
if (const RenderBox* currentBoxDescendant = currentStatePusherRenderBox()) {
LayoutState* layoutState = currentBoxDescendant->view()->layoutState();
if (layoutState && layoutState->isPaginated()) {
ASSERT(layoutState->renderer() == currentBoxDescendant);
- LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
+ LayoutSize offsetDelta = layoutState->layoutOffset() - layoutState->pageOffset();
setOffsetFromLogicalTopOfFirstRegion(currentBoxDescendant, currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width());
}
}
- m_statePusherObjectsStack.add(object);
+ m_statePusherObjectsStack.add(&object);
}
void RenderFlowThread::popFlowThreadLayoutState()
@@ -1109,7 +477,7 @@ LayoutUnit RenderFlowThread::offsetFromLogicalTopOfFirstRegion(const RenderBlock
LayoutState* layoutState = view()->layoutState();
ASSERT(layoutState->renderer() == currentBlock);
ASSERT(layoutState && layoutState->isPaginated());
- LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
+ LayoutSize offsetDelta = layoutState->layoutOffset() - layoutState->pageOffset();
return currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
}
@@ -1148,17 +516,6 @@ void RenderFlowThread::RegionSearchAdapter::collectIfNeeded(const RegionInterval
m_result = interval.data();
}
-void RenderFlowThread::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
-{
- if (this == repaintContainer)
- return;
-
- if (RenderRegion* region = mapFromFlowToRegion(transformState)) {
- // FIXME: The cast below is probably not the best solution, we may need to find a better way.
- static_cast<const RenderObject*>(region)->mapLocalToContainer(region->containerForRepaint(), transformState, mode, wasFixed);
- }
-}
-
CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowThread* renderFlowThread)
: m_renderFlowThread(renderFlowThread)
, m_previousRenderFlowThread(0)
@@ -1167,7 +524,6 @@ CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowT
return;
RenderView* view = m_renderFlowThread->view();
m_previousRenderFlowThread = view->flowThreadController()->currentRenderFlowThread();
- ASSERT(!m_previousRenderFlowThread || !renderFlowThread->isRenderNamedFlowThread());
view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.h
index 7986768361e..12c92fb627b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFlowThread.h
@@ -41,7 +41,6 @@ namespace WebCore {
struct LayerFragment;
typedef Vector<LayerFragment, 1> LayerFragments;
class RenderFlowThread;
-class RenderStyle;
class RenderRegion;
typedef ListHashSet<RenderRegion*> RenderRegionList;
@@ -58,117 +57,58 @@ public:
virtual ~RenderFlowThread() { };
virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; }
+ virtual bool isRenderMultiColumnFlowThread() const { return false; }
- virtual void layout() OVERRIDE FINAL;
+ virtual void layout() OVERRIDE;
// Always create a RenderLayer for the RenderFlowThread so that we
// can easily avoid drawing the children directly.
- virtual bool requiresLayer() const OVERRIDE FINAL { return true; }
+ virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NormalLayer; }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
- void removeFlowChildInfo(RenderObject*);
-#ifndef NDEBUG
- bool hasChildInfo(RenderObject* child) const { return child && child->isBox() && m_regionRangeMap.contains(toRenderBox(child)); }
-#endif
-
- virtual void addRegionToThread(RenderRegion*);
+ virtual void addRegionToThread(RenderRegion*) = 0;
virtual void removeRegionFromThread(RenderRegion*);
const RenderRegionList& renderRegionList() const { return m_regionList; }
- virtual void updateLogicalWidth() OVERRIDE FINAL;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- void paintFlowThreadPortionInRegion(PaintInfo&, RenderRegion*, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint&) const;
- bool hitTestFlowThreadPortionInRegion(RenderRegion*, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
-
bool hasRegions() const { return m_regionList.size(); }
- // Check if the content is flown into at least a region with region styling rules.
- bool hasRegionsWithStyling() const { return m_hasRegionsWithStyling; }
- void checkRegionsWithStyling();
- virtual void regionChangedWritingMode(RenderRegion*) { }
void validateRegions();
void invalidateRegions();
bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_regionList.isEmpty(); }
- static PassRefPtr<RenderStyle> createFlowThreadStyle(RenderStyle* parentStyle);
-
- void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
void repaintRectangleInRegions(const LayoutRect&) const;
LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject&, const LayoutPoint&);
LayoutUnit pageLogicalTopForOffset(LayoutUnit);
- LayoutUnit pageLogicalWidthForOffset(LayoutUnit);
LayoutUnit pageLogicalHeightForOffset(LayoutUnit);
LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary);
virtual void setPageBreak(LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { }
virtual void updateMinimumPageHeight(LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { }
- enum RegionAutoGenerationPolicy {
- AllowRegionAutoGeneration,
- DisallowRegionAutoGeneration,
- };
- RenderRegion* regionAtBlockOffset(LayoutUnit, bool extendLastRegion = false, RegionAutoGenerationPolicy = AllowRegionAutoGeneration);
-
- RenderRegion* regionFromAbsolutePointAndBox(IntPoint, const RenderBox* flowedBox);
+ virtual RenderRegion* regionAtBlockOffset(LayoutUnit) const;
- bool regionsHaveUniformLogicalWidth() const { return m_regionsHaveUniformLogicalWidth; }
bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLogicalHeight; }
- RenderRegion* mapFromFlowToRegion(TransformState&) const;
-
- void removeRenderBoxRegionInfo(RenderBox*);
- bool logicalWidthChangedInRegionsForBlock(const RenderBlock*);
-
- LayoutUnit contentLogicalWidthOfFirstRegion() const;
- LayoutUnit contentLogicalHeightOfFirstRegion() const;
- LayoutUnit contentLogicalLeftOfFirstRegion() const;
-
RenderRegion* firstRegion() const;
RenderRegion* lastRegion() const;
- bool previousRegionCountChanged() const { return m_previousRegionCount != m_regionList.size(); }
- void updatePreviousRegionCount() { m_previousRegionCount = m_regionList.size(); }
-
void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopOfFirstPage);
void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, RenderRegion*& endRegion) const;
- void clearRenderObjectCustomStyle(const RenderObject*,
- const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion = 0,
- const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion = 0);
-
- // Check if the object is in region and the region is part of this flow thread.
- bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
-
- void markAutoLogicalHeightRegionsForLayout();
-
- bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0);
- void applyBreakAfterContent(LayoutUnit);
+ virtual bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0) { return false; }
+ virtual bool isPageLogicalHeightKnown() const { return true; }
bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
- bool hasAutoLogicalHeightRegions() const { ASSERT(isAutoLogicalHeightRegionsCountConsistent()); return m_autoLogicalHeightRegionsCount; }
- void incrementAutoLogicalHeightRegions();
- void decrementAutoLogicalHeightRegions();
-
-#ifndef NDEBUG
- bool isAutoLogicalHeightRegionsCountConsistent() const;
-#endif
-
void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox);
- void setInConstrainedLayoutPhase(bool value) { m_inConstrainedLayoutPhase = value; }
- bool inConstrainedLayoutPhase() const { return m_inConstrainedLayoutPhase; }
-
- bool needsTwoPhasesLayout() const { return m_needsTwoPhasesLayout; }
- void clearNeedsTwoPhasesLayout() { m_needsTwoPhasesLayout = false; }
-
- void pushFlowThreadLayoutState(const RenderObject*);
+ void pushFlowThreadLayoutState(const RenderObject&);
void popFlowThreadLayoutState();
LayoutUnit offsetFromLogicalTopOfFirstRegion(const RenderBlock*) const;
@@ -178,31 +118,8 @@ public:
protected:
virtual const char* renderName() const = 0;
- // Overridden by columns/pages to set up an initial logical width of the page width even when
- // no regions have been generated yet.
- virtual LayoutUnit initialLogicalWidth() const { return 0; };
-
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
-
- void updateRegionsFlowThreadPortionRect(const RenderRegion* = 0);
+ void updateRegionsFlowThreadPortionRect();
bool shouldRepaint(const LayoutRect&) const;
- bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const;
-
- LayoutRect computeRegionClippingRect(const LayoutPoint&, const LayoutRect&, const LayoutRect&) const;
-
- void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; }
- bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; }
-
- void setDispatchRegionOversetChangeEvent(bool value) { m_dispatchRegionOversetChangeEvent = value; }
- bool shouldDispatchRegionOversetChangeEvent() const { return m_dispatchRegionOversetChangeEvent; }
-
- // Override if the flow thread implementation supports dispatching events when the flow layout is updated (e.g. for named flows)
- virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdateEvent = false; }
- virtual void dispatchRegionOversetChangeEvent() { m_dispatchRegionOversetChangeEvent = false; }
-
- void initializeRegionsComputedAutoHeight(RenderRegion* = 0);
-
- virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) { };
bool cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit&) const;
void setOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit);
@@ -211,7 +128,6 @@ protected:
const RenderBox* currentStatePusherRenderBox() const;
RenderRegionList m_regionList;
- unsigned short m_previousRegionCount;
class RenderRegionRange {
public:
@@ -265,10 +181,6 @@ protected:
typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap;
RenderRegionRangeMap m_regionRangeMap;
- typedef HashMap<RenderObject*, RenderRegion*> RenderObjectToRegionMap;
- RenderObjectToRegionMap m_breakBeforeToRegionMap;
- RenderObjectToRegionMap m_breakAfterToRegionMap;
-
// Stack of objects that pushed a LayoutState object on the RenderView. The
// objects on the stack are the ones that are curently in the process of being
// laid out.
@@ -276,23 +188,11 @@ protected:
typedef HashMap<const RenderBox*, LayoutUnit> RenderBoxToOffsetMap;
RenderBoxToOffsetMap m_boxesToOffsetMap;
- unsigned m_autoLogicalHeightRegionsCount;
-
RegionIntervalTree m_regionIntervalTree;
bool m_regionsInvalidated : 1;
- bool m_regionsHaveUniformLogicalWidth : 1;
bool m_regionsHaveUniformLogicalHeight : 1;
- bool m_hasRegionsWithStyling : 1;
- bool m_dispatchRegionLayoutUpdateEvent : 1;
- bool m_dispatchRegionOversetChangeEvent : 1;
bool m_pageLogicalSizeChanged : 1;
- bool m_inConstrainedLayoutPhase : 1;
- bool m_needsTwoPhasesLayout : 1;
-
-private:
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.cpp
index 329ae3422b4..3468cc3af7c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.cpp
@@ -47,21 +47,4 @@ void RenderFrame::updateFromElement()
toRenderFrameSet(parent())->notifyFrameEdgeInfoChanged();
}
-void RenderFrame::viewCleared()
-{
- HTMLFrameElement* element = toHTMLFrameElement(node());
- if (!element || !widget() || !widget()->isFrameView())
- return;
-
- FrameView* view = toFrameView(widget());
-
- int marginWidth = element->marginWidth();
- int marginHeight = element->marginHeight();
-
- if (marginWidth != -1)
- view->setMarginWidth(marginWidth);
- if (marginHeight != -1)
- view->setMarginHeight(marginHeight);
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.h
index 55391b98bd9..8d953191ad9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFrame.h
@@ -37,12 +37,10 @@ public:
FrameEdgeInfo edgeInfo() const;
private:
- virtual const char* renderName() const { return "RenderFrame"; }
- virtual bool isFrame() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderFrame"; }
+ virtual bool isFrame() const OVERRIDE { return true; }
- virtual void updateFromElement();
-
- virtual void viewCleared();
+ virtual void updateFromElement() OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFrame, isFrame());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.cpp
index a0bf472cac3..afae324b731 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.cpp
@@ -26,13 +26,11 @@
#include "core/dom/Document.h"
#include "core/events/MouseEvent.h"
-#include "core/events/ThreadLocalEventNames.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLDimension.h"
#include "core/html/HTMLFrameSetElement.h"
#include "core/page/EventHandler.h"
-#include "core/frame/Frame.h"
#include "core/rendering/GraphicsContextAnnotator.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderFrame.h"
#include "core/rendering/RenderView.h"
@@ -441,13 +439,12 @@ void RenderFrameSet::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
- bool doFullRepaint = !RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && selfNeedsLayout() && checkForRepaintDuringLayout();
+ bool doFullRepaint = selfNeedsLayout() && checkForPaintInvalidationDuringLayout();
LayoutRect oldBounds;
- RenderLayerModelObject* repaintContainer = 0;
+ const RenderLayerModelObject* repaintContainer = 0;
if (doFullRepaint) {
- repaintContainer = containerForRepaint();
- oldBounds = clippedOverflowRectForRepaint(repaintContainer);
+ repaintContainer = containerForPaintInvalidation();
+ oldBounds = boundsRectForPaintInvalidation(repaintContainer);
}
if (!parent()->isFrameSet() && !document().printing()) {
@@ -473,13 +470,13 @@ void RenderFrameSet::layout()
computeEdgeInfo();
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
if (doFullRepaint) {
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds));
- LayoutRect newBounds = clippedOverflowRectForRepaint(repaintContainer);
+ invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds), InvalidationSelfLayout);
+ LayoutRect newBounds = boundsRectForPaintInvalidation(repaintContainer);
if (newBounds != oldBounds)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds));
+ invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds), InvalidationSelfLayout);
}
clearNeedsLayout();
@@ -517,7 +514,7 @@ void RenderFrameSet::positionFrames()
if (width != child->width() || height != child->height()) {
child->setWidth(width);
child->setHeight(height);
- child->setNeedsLayout();
+ child->setNeedsLayoutAndFullPaintInvalidation();
child->layout();
}
@@ -557,7 +554,7 @@ void RenderFrameSet::continueResizing(GridAxis& axis, int position)
return;
axis.m_deltas[axis.m_splitBeingResized - 1] += delta;
axis.m_deltas[axis.m_splitBeingResized] -= delta;
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
}
bool RenderFrameSet::userResize(MouseEvent* evt)
@@ -596,20 +593,10 @@ void RenderFrameSet::setIsResizing(bool isResizing)
if (ancestor->isFrameSet())
toRenderFrameSet(ancestor)->m_isChildResizing = isResizing;
}
- if (Frame* frame = this->frame())
+ if (LocalFrame* frame = this->frame())
frame->eventHandler().setResizingFrameSet(isResizing ? frameSet() : 0);
}
-bool RenderFrameSet::isResizingRow() const
-{
- return m_isResizing && m_rows.m_splitBeingResized != noSplit;
-}
-
-bool RenderFrameSet::isResizingColumn() const
-{
- return m_isResizing && m_cols.m_splitBeingResized != noSplit;
-}
-
bool RenderFrameSet::canResizeRow(const IntPoint& p) const
{
int r = hitTestSplit(m_rows, p.y());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.h
index 21f90eac87a..90bf5933792 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFrameSet.h
@@ -30,7 +30,6 @@ namespace WebCore {
class HTMLDimension;
class HTMLFrameSetElement;
class MouseEvent;
-class RenderFrame;
enum FrameEdge { LeftFrameEdge, RightFrameEdge, TopFrameEdge, BottomFrameEdge };
@@ -62,6 +61,10 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderFrameSet, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
@@ -69,9 +72,6 @@ public:
bool userResize(MouseEvent*);
- bool isResizingRow() const;
- bool isResizingColumn() const;
-
bool canResizeRow(const IntPoint&) const;
bool canResizeColumn(const IntPoint&) const;
@@ -94,16 +94,16 @@ private:
int m_splitResizeOffset;
};
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ virtual RenderObjectChildList* virtualChildren() OVERRIDE { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const OVERRIDE { return children(); }
- virtual const char* renderName() const { return "RenderFrameSet"; }
- virtual bool isFrameSet() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderFrameSet"; }
+ virtual bool isFrameSet() const OVERRIDE { return true; }
- virtual void layout();
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
- virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
+ virtual void layout() OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+ virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const OVERRIDE;
inline HTMLFrameSetElement* frameSet() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.cpp
index 23fa9925c0f..9ce9810a3ac 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.cpp
@@ -39,9 +39,8 @@ public:
setDocumentForAnonymous(&owner->document());
}
private:
- virtual bool isRenderFullScreenPlaceholder() const { return true; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual void willBeDestroyed();
+ virtual bool isRenderFullScreenPlaceholder() const OVERRIDE { return true; }
+ virtual void willBeDestroyed() OVERRIDE;
RenderFullScreen* m_owner;
};
@@ -76,9 +75,9 @@ void RenderFullScreen::willBeDestroyed()
// RenderObjects are unretained, so notify the document (which holds a pointer to a RenderFullScreen)
// if it's RenderFullScreen is destroyed.
- FullscreenElementStack* controller = FullscreenElementStack::from(&document());
- if (controller->fullScreenRenderer() == this)
- controller->fullScreenRendererDestroyed();
+ FullscreenElementStack& controller = FullscreenElementStack::from(document());
+ if (controller.fullScreenRenderer() == this)
+ controller.fullScreenRendererDestroyed();
RenderFlexibleBox::willBeDestroyed();
}
@@ -91,11 +90,11 @@ static PassRefPtr<RenderStyle> createFullScreenStyle()
fullscreenStyle->setZIndex(INT_MAX);
fullscreenStyle->setFontDescription(FontDescription());
- fullscreenStyle->font().update(0);
+ fullscreenStyle->font().update(nullptr);
fullscreenStyle->setDisplay(FLEX);
fullscreenStyle->setJustifyContent(JustifyCenter);
- fullscreenStyle->setAlignItems(AlignCenter);
+ fullscreenStyle->setAlignItems(ItemPositionCenter);
fullscreenStyle->setFlexDirection(FlowColumn);
fullscreenStyle->setPosition(FixedPosition);
@@ -104,13 +103,17 @@ static PassRefPtr<RenderStyle> createFullScreenStyle()
fullscreenStyle->setLeft(Length(0, WebCore::Fixed));
fullscreenStyle->setTop(Length(0, WebCore::Fixed));
- fullscreenStyle->setBackgroundColor(Color::black);
+ fullscreenStyle->setBackgroundColor(StyleColor(Color::black));
return fullscreenStyle.release();
}
RenderObject* RenderFullScreen::wrapRenderer(RenderObject* object, RenderObject* parent, Document* document)
{
+ // FIXME: We should not modify the structure of the render tree during
+ // layout. crbug.com/370459
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
+
RenderFullScreen* fullscreenRenderer = RenderFullScreen::createAnonymous(document);
fullscreenRenderer->setStyle(createFullScreenStyle());
if (parent && !parent->isChildAllowed(fullscreenRenderer, fullscreenRenderer->style())) {
@@ -133,19 +136,24 @@ RenderObject* RenderFullScreen::wrapRenderer(RenderObject* object, RenderObject*
// Always just do a full layout to ensure that line boxes get deleted properly.
// Because objects moved from |parent| to |fullscreenRenderer|, we want to
// make new line boxes instead of leaving the old ones around.
- parent->setNeedsLayoutAndPrefWidthsRecalc();
- containingBlock->setNeedsLayoutAndPrefWidthsRecalc();
+ parent->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ containingBlock->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
fullscreenRenderer->addChild(object);
- fullscreenRenderer->setNeedsLayoutAndPrefWidthsRecalc();
+ fullscreenRenderer->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
- FullscreenElementStack::from(document)->setFullScreenRenderer(fullscreenRenderer);
+ ASSERT(document);
+ FullscreenElementStack::from(*document).setFullScreenRenderer(fullscreenRenderer);
return fullscreenRenderer;
}
void RenderFullScreen::unwrapRenderer()
{
+ // FIXME: We should not modify the structure of the render tree during
+ // layout. crbug.com/370459
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
+
if (parent()) {
RenderObject* child;
while ((child = firstChild())) {
@@ -156,13 +164,13 @@ void RenderFullScreen::unwrapRenderer()
toRenderBox(child)->clearOverrideSize();
child->remove();
parent()->addChild(child, this);
- parent()->setNeedsLayoutAndPrefWidthsRecalc();
+ parent()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
if (placeholder())
placeholder()->remove();
remove();
- FullscreenElementStack::from(&document())->setFullScreenRenderer(0);
+ FullscreenElementStack::from(document()).setFullScreenRenderer(0);
}
void RenderFullScreen::setPlaceholder(RenderBlock* placeholder)
@@ -182,7 +190,7 @@ void RenderFullScreen::createPlaceholder(PassRefPtr<RenderStyle> style, const La
m_placeholder->setStyle(style);
if (parent()) {
parent()->addChild(m_placeholder, this);
- parent()->setNeedsLayoutAndPrefWidthsRecalc();
+ parent()->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
} else
m_placeholder->setStyle(style);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.h b/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.h
index 48c40f4f7fe..285dbd21a70 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderFullScreen.h
@@ -34,8 +34,8 @@ class RenderFullScreen FINAL : public RenderFlexibleBox {
public:
static RenderFullScreen* createAnonymous(Document*);
- virtual bool isRenderFullScreen() const { return true; }
- virtual const char* renderName() const { return "RenderFullScreen"; }
+ virtual bool isRenderFullScreen() const OVERRIDE { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderFullScreen"; }
void setPlaceholder(RenderBlock*);
RenderBlock* placeholder() { return m_placeholder; }
@@ -47,8 +47,7 @@ public:
private:
RenderFullScreen();
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
protected:
RenderBlock* m_placeholder;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.cpp
index 07ab16f7014..13782a8af3d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "core/rendering/RenderGeometryMap.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "platform/geometry/TransformState.h"
@@ -57,7 +57,7 @@ void RenderGeometryMap::mapToContainer(TransformState& transformState, const Ren
}
bool inFixed = false;
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_renderer == container);
#endif
@@ -66,7 +66,7 @@ void RenderGeometryMap::mapToContainer(TransformState& transformState, const Ren
// If container is the root RenderView (step 0) we want to apply its fixed position offset.
if (i > 0 && currentStep.m_renderer == container) {
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
foundContainer = true;
#endif
break;
@@ -109,14 +109,14 @@ FloatPoint RenderGeometryMap::mapToContainer(const FloatPoint& p, const RenderLa
FloatPoint result;
if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() && (!container || (m_mapping.size() && container == m_mapping[0].m_renderer)))
- result = p + roundedIntSize(m_accumulatedOffset);
+ result = p + m_accumulatedOffset;
else {
TransformState transformState(TransformState::ApplyTransformDirection, p);
mapToContainer(transformState, container);
result = transformState.lastPlanarPoint();
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
if (m_mapping.size() > 0) {
const RenderObject* lastRenderer = m_mapping.last().m_renderer;
const RenderLayer* layer = lastRenderer->enclosingLayer();
@@ -125,7 +125,7 @@ FloatPoint RenderGeometryMap::mapToContainer(const FloatPoint& p, const RenderLa
// therefore not necessarily expected to be correct here. This is ok,
// because they will be recomputed if the layer becomes visible.
if (!layer || !layer->subtreeIsInvisible()) {
- FloatPoint rendererMappedResult = lastRenderer->localToAbsolute(p, m_mapCoordinatesFlags);
+ FloatPoint rendererMappedResult = lastRenderer->localToContainerPoint(p, container, m_mapCoordinatesFlags);
ASSERT(roundedIntPoint(rendererMappedResult) == roundedIntPoint(result));
}
@@ -137,7 +137,7 @@ FloatPoint RenderGeometryMap::mapToContainer(const FloatPoint& p, const RenderLa
#ifndef NDEBUG
// Handy function to call from gdb while debugging mismatched point/rect errors.
-void RenderGeometryMap::dumpSteps()
+void RenderGeometryMap::dumpSteps() const
{
fprintf(stderr, "RenderGeometryMap::dumpSteps accumulatedOffset=%d,%d\n", m_accumulatedOffset.width().toInt(), m_accumulatedOffset.height().toInt());
for (int i = m_mapping.size() - 1; i >= 0; --i) {
@@ -162,7 +162,7 @@ FloatQuad RenderGeometryMap::mapToContainer(const FloatRect& rect, const RenderL
result = transformState.lastPlanarQuad().boundingBox();
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
if (m_mapping.size() > 0) {
const RenderObject* lastRenderer = m_mapping.last().m_renderer;
const RenderLayer* layer = lastRenderer->enclosingLayer();
@@ -170,7 +170,7 @@ FloatQuad RenderGeometryMap::mapToContainer(const FloatRect& rect, const RenderL
// Bounds for invisible layers are intentionally not calculated, and are
// therefore not necessarily expected to be correct here. This is ok,
// because they will be recomputed if the layer becomes visible.
- if (!layer || !layer->subtreeIsInvisible()) {
+ if (!layer->subtreeIsInvisible() && lastRenderer->style()->visibility() == VISIBLE) {
FloatRect rendererMappedResult = lastRenderer->localToContainerQuad(rect, container, m_mapCoordinatesFlags).boundingBox();
// Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>.
@@ -235,7 +235,8 @@ void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const R
}
TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
- push(renderer, toLayoutSize(layerOffset), /*accumulatingTransform*/ true, /*isNonUniform*/ false, /*isFixedPosition*/ false, /*hasTransform*/ false);
+ bool accumulatingTransform = layer->renderer()->style()->preserves3D() || ancestorLayer->renderer()->style()->preserves3D();
+ push(renderer, toLayoutSize(layerOffset), accumulatingTransform, /*isNonUniform*/ false, /*isFixedPosition*/ false, /*hasTransform*/ false);
return;
}
const RenderLayerModelObject* ancestorRenderer = ancestorLayer ? ancestorLayer->renderer() : 0;
@@ -328,7 +329,7 @@ void RenderGeometryMap::stepRemoved(const RenderGeometryMapStep& step)
}
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool RenderGeometryMap::isTopmostRenderView(const RenderObject* renderer) const
{
if (!renderer->isRenderView())
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.h b/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.h
index 8049bbbc066..807c458be7e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderGeometryMap.h
@@ -38,7 +38,6 @@ namespace WebCore {
class RenderLayer;
class RenderLayerModelObject;
-class RenderView;
class TransformState;
// Stores data about how to map from one renderer to its container.
@@ -121,10 +120,10 @@ private:
bool hasFixedPositionStep() const { return m_fixedStepsCount; }
#ifndef NDEBUG
- void dumpSteps();
+ void dumpSteps() const;
#endif
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool isTopmostRenderView(const RenderObject* renderer) const;
#endif
@@ -141,10 +140,6 @@ private:
} // namespace WebCore
-namespace WTF {
-// This is required for a struct with OwnPtr. We know RenderGeometryMapStep is simple enough that
-// initializing to 0 and moving with memcpy (and then not destructing the original) will work.
-template<> struct VectorTraits<WebCore::RenderGeometryMapStep> : SimpleClassVectorTraits { };
-}
+WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::RenderGeometryMapStep);
#endif // RenderGeometryMap_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.cpp
index 38c296ac866..0d167415707 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.cpp
@@ -26,10 +26,12 @@
#include "config.h"
#include "core/rendering/RenderGrid.h"
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/style/GridCoordinate.h"
+#include "platform/LengthFunctions.h"
namespace WebCore {
@@ -75,7 +77,7 @@ struct GridTrackForNormalization {
}
// Required by std::sort.
- GridTrackForNormalization operator=(const GridTrackForNormalization& o)
+ GridTrackForNormalization& operator=(const GridTrackForNormalization& o)
{
m_track = o.m_track;
m_flex = o.m_flex;
@@ -120,16 +122,37 @@ public:
return 0;
}
- PassOwnPtr<GridCoordinate> nextEmptyGridArea()
+ bool checkEmptyCells(size_t rowSpan, size_t columnSpan) const
+ {
+ // Ignore cells outside current grid as we will grow it later if needed.
+ size_t maxRows = std::min(m_rowIndex + rowSpan, m_grid.size());
+ size_t maxColumns = std::min(m_columnIndex + columnSpan, m_grid[0].size());
+
+ // This adds a O(N^2) behavior that shouldn't be a big deal as we expect spanning areas to be small.
+ for (size_t row = m_rowIndex; row < maxRows; ++row) {
+ for (size_t column = m_columnIndex; column < maxColumns; ++column) {
+ const GridCell& children = m_grid[row][column];
+ if (!children.isEmpty())
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ PassOwnPtr<GridCoordinate> nextEmptyGridArea(size_t fixedTrackSpan, size_t varyingTrackSpan)
{
ASSERT(!m_grid.isEmpty());
+ ASSERT(fixedTrackSpan >= 1 && varyingTrackSpan >= 1);
+
+ size_t rowSpan = (m_direction == ForColumns) ? varyingTrackSpan : fixedTrackSpan;
+ size_t columnSpan = (m_direction == ForColumns) ? fixedTrackSpan : varyingTrackSpan;
size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
- const GridCell& children = m_grid[m_rowIndex][m_columnIndex];
- if (children.isEmpty()) {
- OwnPtr<GridCoordinate> result = adoptPtr(new GridCoordinate(GridSpan(m_rowIndex, m_rowIndex), GridSpan(m_columnIndex, m_columnIndex)));
+ if (checkEmptyCells(rowSpan, columnSpan)) {
+ OwnPtr<GridCoordinate> result = adoptPtr(new GridCoordinate(GridSpan(m_rowIndex, m_rowIndex + rowSpan - 1), GridSpan(m_columnIndex, m_columnIndex + columnSpan - 1)));
// Advance the iterator to avoid an infinite loop where we would return the same grid area over and over.
++varyingTrackIndex;
return result.release();
@@ -168,7 +191,6 @@ RenderGrid::RenderGrid(Element* element)
: RenderBlock(element)
, m_gridIsDirty(true)
, m_orderIterator(this)
- , m_gridItemOverflowGridArea(false)
{
// All of our children must be block level.
setChildrenInline(false);
@@ -190,20 +212,44 @@ void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
return;
}
+ if (style()->gridAutoFlow() != AutoFlowNone) {
+ // The grid needs to be recomputed as it might contain auto-placed items that will change their position.
+ dirtyGrid();
+ return;
+ }
+
RenderBox* newChildBox = toRenderBox(newChild);
- OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(newChildBox, ForRows);
- OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(newChildBox, ForColumns);
+ OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *newChildBox, ForRows);
+ OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *newChildBox, ForColumns);
if (!rowPositions || !columnPositions) {
// The new child requires the auto-placement algorithm to run so we need to recompute the grid fully.
dirtyGrid();
+ return;
} else {
- if (gridRowCount() <= rowPositions->finalPositionIndex || gridColumnCount() <= columnPositions->finalPositionIndex) {
- // FIXME: We could just insert the new child provided we had a primitive to arbitrarily grow the grid.
- dirtyGrid();
- } else {
- insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPositions));
- }
+ insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPositions));
+ addChildToIndexesMap(newChildBox);
+ }
+}
+
+void RenderGrid::addChildToIndexesMap(RenderBox* child)
+{
+ ASSERT(!m_gridItemsIndexesMap.contains(child));
+ RenderBox* sibling = child->nextSiblingBox();
+ bool lastSibling = !sibling;
+
+ if (lastSibling)
+ sibling = child->previousSiblingBox();
+
+ size_t index = 0;
+ if (sibling)
+ index = lastSibling ? m_gridItemsIndexesMap.get(sibling) + 1 : m_gridItemsIndexesMap.get(sibling);
+
+ if (sibling && !lastSibling) {
+ for (; sibling; sibling = sibling->nextSiblingBox())
+ m_gridItemsIndexesMap.set(sibling, m_gridItemsIndexesMap.get(sibling) + 1);
}
+
+ m_gridItemsIndexesMap.set(child, index);
}
void RenderGrid::removeChild(RenderObject* child)
@@ -214,8 +260,24 @@ void RenderGrid::removeChild(RenderObject* child)
return;
ASSERT(child->isBox());
- // FIXME: We could avoid dirtying the grid in some cases (e.g. if it's an explicitly positioned element).
- dirtyGrid();
+
+ if (style()->gridAutoFlow() != AutoFlowNone) {
+ // The grid needs to be recomputed as it might contain auto-placed items that will change their position.
+ dirtyGrid();
+ return;
+ }
+
+ const RenderBox* childBox = toRenderBox(child);
+ GridCoordinate coordinate = m_gridItemCoordinate.take(childBox);
+
+ for (GridSpan::iterator row = coordinate.rows.begin(); row != coordinate.rows.end(); ++row) {
+ for (GridSpan::iterator column = coordinate.columns.begin(); column != coordinate.columns.end(); ++column) {
+ GridCell& cell = m_grid[row.toInt()][column.toInt()];
+ cell.remove(cell.find(childBox));
+ }
+ }
+
+ m_gridItemsIndexesMap.remove(childBox);
}
void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
@@ -237,8 +299,8 @@ void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
bool RenderGrid::explicitGridDidResize(const RenderStyle* oldStyle) const
{
- return oldStyle->gridDefinitionColumns().size() != style()->gridDefinitionColumns().size()
- || oldStyle->gridDefinitionRows().size() != style()->gridDefinitionRows().size();
+ return oldStyle->gridTemplateColumns().size() != style()->gridTemplateColumns().size()
+ || oldStyle->gridTemplateRows().size() != style()->gridTemplateRows().size();
}
bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle* oldStyle) const
@@ -247,7 +309,7 @@ bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle* oldStyle)
|| oldStyle->namedGridColumnLines() != style()->namedGridColumnLines();
}
-void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
+void RenderGrid::layoutBlock(bool relayoutChildren)
{
ASSERT(needsLayout());
@@ -256,21 +318,16 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
// FIXME: Much of this method is boiler plate that matches RenderBox::layoutBlock and Render*FlexibleBox::layoutBlock.
// It would be nice to refactor some of the duplicate code.
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
-
- // Regions changing widths can force us to relayout our children.
- RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (logicalWidthChangedInRegions(flowThread))
- relayoutChildren = true;
- if (updateRegionsAndShapesLogicalSize(flowThread))
- relayoutChildren = true;
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout());
+ LayoutState state(*this, locationOffset());
LayoutSize previousSize = size();
setLogicalHeight(0);
updateLogicalWidth();
+ FastTextAutosizer::LayoutScope fastTextAutosizerLayoutScope(this);
+
layoutGridItems();
LayoutUnit oldClientAfterEdge = clientLogicalBottom();
@@ -279,14 +336,13 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
if (size() != previousSize)
relayoutChildren = true;
- layoutPositionedObjects(relayoutChildren || isRoot());
+ layoutPositionedObjects(relayoutChildren || isDocumentElement());
- computeRegionRangeForBlock(flowThread);
+ computeRegionRangeForBlock(flowThreadContainingBlock());
computeOverflow(oldClientAfterEdge);
- statePusher.pop();
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
@@ -304,7 +360,7 @@ void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Layo
GridSizingData sizingData(gridColumnCount(), gridRowCount());
LayoutUnit availableLogicalSpace = 0;
- const_cast<RenderGrid*>(this)->computedUsedBreadthOfGridTracks(ForColumns, sizingData, availableLogicalSpace);
+ const_cast<RenderGrid*>(this)->computeUsedBreadthOfGridTracks(ForColumns, sizingData, availableLogicalSpace);
for (size_t i = 0; i < sizingData.columnTracks.size(); ++i) {
LayoutUnit minTrackBreadth = sizingData.columnTracks[i].m_usedBreadth;
@@ -337,16 +393,24 @@ void RenderGrid::computePreferredLogicalWidths()
clearPreferredLogicalWidthsDirty();
}
-void RenderGrid::computedUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData)
+void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData)
{
LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding);
- computedUsedBreadthOfGridTracks(direction, sizingData, availableLogicalSpace);
+ computeUsedBreadthOfGridTracks(direction, sizingData, availableLogicalSpace);
}
-void RenderGrid::computedUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
+bool RenderGrid::gridElementIsShrinkToFit()
+{
+ return isFloatingOrOutOfFlowPositioned();
+}
+
+void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
{
Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
+ Vector<size_t> flexibleSizedTracksIndex;
sizingData.contentSizedTracksIndex.shrink(0);
+
+ // 1. Initialize per Grid track variables.
for (size_t i = 0; i < tracks.size(); ++i) {
GridTrack& track = tracks[i];
const GridTrackSize& trackSize = gridTrackSize(direction, i);
@@ -360,8 +424,11 @@ void RenderGrid::computedUsedBreadthOfGridTracks(GridTrackSizingDirection direct
if (trackSize.isContentSized())
sizingData.contentSizedTracksIndex.append(i);
+ if (trackSize.maxTrackBreadth().isFlex())
+ flexibleSizedTracksIndex.append(i);
}
+ // 2. Resolve content-based TrackSizingFunctions.
if (!sizingData.contentSizedTracksIndex.isEmpty())
resolveContentBasedTrackSizingFunctions(direction, sizingData, availableLogicalSpace);
@@ -370,26 +437,60 @@ void RenderGrid::computedUsedBreadthOfGridTracks(GridTrackSizingDirection direct
availableLogicalSpace -= tracks[i].m_usedBreadth;
}
- if (availableLogicalSpace <= 0)
+ const bool hasUndefinedRemainingSpace = (direction == ForRows) ? style()->logicalHeight().isAuto() : gridElementIsShrinkToFit();
+
+ if (!hasUndefinedRemainingSpace && availableLogicalSpace <= 0)
return;
+ // 3. Grow all Grid tracks in GridTracks from their UsedBreadth up to their MaxBreadth value until
+ // availableLogicalSpace (RemainingSpace in the specs) is exhausted.
const size_t tracksSize = tracks.size();
- Vector<GridTrack*> tracksForDistribution(tracksSize);
- for (size_t i = 0; i < tracksSize; ++i)
- tracksForDistribution[i] = tracks.data() + i;
+ if (!hasUndefinedRemainingSpace) {
+ Vector<GridTrack*> tracksForDistribution(tracksSize);
+ for (size_t i = 0; i < tracksSize; ++i)
+ tracksForDistribution[i] = tracks.data() + i;
- distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, sizingData, availableLogicalSpace);
+ distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, sizingData, availableLogicalSpace);
+ } else {
+ for (size_t i = 0; i < tracksSize; ++i)
+ tracks[i].m_usedBreadth = tracks[i].m_maxBreadth;
+ }
+
+ if (flexibleSizedTracksIndex.isEmpty())
+ return;
// 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
+ double normalizedFractionBreadth = 0;
+ if (!hasUndefinedRemainingSpace) {
+ normalizedFractionBreadth = computeNormalizedFractionBreadth(tracks, GridSpan(0, tracks.size() - 1), direction, availableLogicalSpace);
+ } else {
+ for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
+ const size_t trackIndex = flexibleSizedTracksIndex[i];
+ const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
+ normalizedFractionBreadth = std::max(normalizedFractionBreadth, tracks[trackIndex].m_usedBreadth / trackSize.maxTrackBreadth().flex());
+ }
- // FIXME: Handle the case where RemainingSpace is not defined.
- double normalizedFractionBreadth = computeNormalizedFractionBreadth(tracks, direction, availableLogicalSpace);
- for (size_t i = 0; i < tracksSize; ++i) {
- const GridTrackSize& trackSize = gridTrackSize(direction, i);
- if (!trackSize.maxTrackBreadth().isFlex())
- continue;
+ for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
+ GridIterator iterator(m_grid, direction, flexibleSizedTracksIndex[i]);
+ while (RenderBox* gridItem = iterator.nextGridItem()) {
+ const GridCoordinate coordinate = cachedGridCoordinate(gridItem);
+ const GridSpan span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
+
+ // Do not include already processed items.
+ if (i > 0 && span.resolvedInitialPosition.toInt() <= flexibleSizedTracksIndex[i - 1])
+ continue;
+
+ double itemNormalizedFlexBreadth = computeNormalizedFractionBreadth(tracks, span, direction, maxContentForChild(gridItem, direction, sizingData.columnTracks));
+ normalizedFractionBreadth = std::max(normalizedFractionBreadth, itemNormalizedFlexBreadth);
+ }
+ }
+ }
- tracks[i].m_usedBreadth = std::max<LayoutUnit>(tracks[i].m_usedBreadth, normalizedFractionBreadth * trackSize.maxTrackBreadth().flex());
+ for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
+ const size_t trackIndex = flexibleSizedTracksIndex[i];
+ const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
+
+ tracks[trackIndex].m_usedBreadth = std::max<LayoutUnit>(tracks[trackIndex].m_usedBreadth, normalizedFractionBreadth * trackSize.maxTrackBreadth().flex());
}
}
@@ -428,7 +529,7 @@ LayoutUnit RenderGrid::computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirect
{
ASSERT(trackLength.isSpecified());
// FIXME: The -1 here should be replaced by whatever the intrinsic height of the grid is.
- return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : computeContentLogicalHeight(style()->logicalHeight(), -1), view());
+ return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : computeContentLogicalHeight(style()->logicalHeight(), -1));
}
static bool sortByGridNormalizedFlexValue(const GridTrackForNormalization& track1, const GridTrackForNormalization& track2)
@@ -436,22 +537,21 @@ static bool sortByGridNormalizedFlexValue(const GridTrackForNormalization& track
return track1.m_normalizedFlexValue < track2.m_normalizedFlexValue;
}
-double RenderGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, GridTrackSizingDirection direction, LayoutUnit availableLogicalSpace) const
+double RenderGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, const GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit availableLogicalSpace) const
{
// |availableLogicalSpace| already accounts for the used breadths so no need to remove it here.
Vector<GridTrackForNormalization> tracksForNormalization;
- for (size_t i = 0; i < tracks.size(); ++i) {
- const GridTrackSize& trackSize = gridTrackSize(direction, i);
+ for (GridSpan::iterator resolvedPosition = tracksSpan.begin(); resolvedPosition != tracksSpan.end(); ++resolvedPosition) {
+ const GridTrackSize& trackSize = gridTrackSize(direction, resolvedPosition.toInt());
if (!trackSize.maxTrackBreadth().isFlex())
continue;
- tracksForNormalization.append(GridTrackForNormalization(tracks[i], trackSize.maxTrackBreadth().flex()));
+ tracksForNormalization.append(GridTrackForNormalization(tracks[resolvedPosition.toInt()], trackSize.maxTrackBreadth().flex()));
}
- // FIXME: Ideally we shouldn't come here without any <flex> grid track.
- if (tracksForNormalization.isEmpty())
- return LayoutUnit();
+ // The function is not called if we don't have <flex> grid tracks
+ ASSERT(!tracksForNormalization.isEmpty());
std::sort(tracksForNormalization.begin(), tracksForNormalization.end(), sortByGridNormalizedFlexValue);
@@ -483,40 +583,37 @@ double RenderGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, G
const GridTrackSize& RenderGrid::gridTrackSize(GridTrackSizingDirection direction, size_t i) const
{
- const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridDefinitionColumns() : style()->gridDefinitionRows();
+ const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridTemplateColumns() : style()->gridTemplateRows();
if (i >= trackStyles.size())
return (direction == ForColumns) ? style()->gridAutoColumns() : style()->gridAutoRows();
- return trackStyles[i];
-}
-
-size_t RenderGrid::explicitGridColumnCount() const
-{
- return style()->gridDefinitionColumns().size();
-}
-
-size_t RenderGrid::explicitGridRowCount() const
-{
- return style()->gridDefinitionRows().size();
-}
+ const GridTrackSize& trackSize = trackStyles[i];
+ // If the logical width/height of the grid container is indefinite, percentage values are treated as <auto>.
+ if (trackSize.isPercentage()) {
+ Length logicalSize = direction == ForColumns ? style()->logicalWidth() : style()->logicalHeight();
+ if (logicalSize.isIntrinsicOrAuto()) {
+ DEFINE_STATIC_LOCAL(GridTrackSize, autoTrackSize, (Length(Auto)));
+ return autoTrackSize;
+ }
+ }
-size_t RenderGrid::explicitGridSizeForSide(GridPositionSide side) const
-{
- return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount() : explicitGridRowCount();
+ return trackSize;
}
-LayoutUnit RenderGrid::logicalContentHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
+LayoutUnit RenderGrid::logicalHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
{
- SubtreeLayoutScope layoutScope(child);
- if (child->style()->logicalHeight().isPercent())
+ SubtreeLayoutScope layoutScope(*child);
+ LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
+ LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, columnTracks);
+ if (child->style()->logicalHeight().isPercent() || oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth)
layoutScope.setNeedsLayout(child);
- child->setOverrideContainingBlockContentLogicalWidth(gridAreaBreadthForChild(child, ForColumns, columnTracks));
+ child->setOverrideContainingBlockContentLogicalWidth(overrideContainingBlockContentLogicalWidth);
// If |child| has a percentage logical height, we shouldn't let it override its intrinsic height, which is
// what we are interested in here. Thus we need to set the override logical height to -1 (no possible resolution).
child->setOverrideContainingBlockContentLogicalHeight(-1);
child->layoutIfNeeded();
- return child->logicalHeight();
+ return child->logicalHeight() + child->marginLogicalHeight();
}
LayoutUnit RenderGrid::minContentForChild(RenderBox* child, GridTrackSizingDirection direction, Vector<GridTrack>& columnTracks)
@@ -532,7 +629,7 @@ LayoutUnit RenderGrid::minContentForChild(RenderBox* child, GridTrackSizingDirec
return child->minPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
}
- return logicalContentHeightForChild(child, columnTracks);
+ return logicalHeightForChild(child, columnTracks);
}
LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, GridTrackSizingDirection direction, Vector<GridTrack>& columnTracks)
@@ -548,7 +645,7 @@ LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, GridTrackSizingDirec
return child->maxPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
}
- return logicalContentHeightForChild(child, columnTracks);
+ return logicalHeightForChild(child, columnTracks);
}
void RenderGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
@@ -575,16 +672,16 @@ void RenderGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirectio
void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
{
const GridCoordinate coordinate = cachedGridCoordinate(gridItem);
- const size_t initialTrackIndex = (direction == ForColumns) ? coordinate.columns.initialPositionIndex : coordinate.rows.initialPositionIndex;
- const size_t finalTrackIndex = (direction == ForColumns) ? coordinate.columns.finalPositionIndex : coordinate.rows.finalPositionIndex;
+ const GridResolvedPosition initialTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedInitialPosition : coordinate.rows.resolvedInitialPosition;
+ const GridResolvedPosition finalTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedFinalPosition : coordinate.rows.resolvedFinalPosition;
sizingData.filteredTracks.shrink(0);
- for (size_t trackIndex = initialTrackIndex; trackIndex <= finalTrackIndex; ++trackIndex) {
- const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
+ for (GridResolvedPosition trackPosition = initialTrackPosition; trackPosition <= finalTrackPosition; ++trackPosition) {
+ const GridTrackSize& trackSize = gridTrackSize(direction, trackPosition.toInt());
if (!(trackSize.*filterFunction)())
continue;
- GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex];
+ GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackPosition.toInt()] : sizingData.rowTracks[trackPosition.toInt()];
sizingData.filteredTracks.append(&track);
}
@@ -592,8 +689,8 @@ void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing
return;
LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, sizingData.columnTracks);
- for (size_t trackIndexForSpace = initialTrackIndex; trackIndexForSpace <= finalTrackIndex; ++trackIndexForSpace) {
- GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndexForSpace] : sizingData.rowTracks[trackIndexForSpace];
+ for (GridResolvedPosition trackIndexForSpace = initialTrackPosition; trackIndexForSpace <= finalTrackPosition; ++trackIndexForSpace) {
+ GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndexForSpace.toInt()] : sizingData.rowTracks[trackIndexForSpace.toInt()];
additionalBreadthSpace -= (track.*trackGetter)();
}
@@ -655,36 +752,33 @@ bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire
}
#endif
-void RenderGrid::growGrid(GridTrackSizingDirection direction)
+void RenderGrid::ensureGridSize(size_t maximumRowIndex, size_t maximumColumnIndex)
{
- if (direction == ForColumns) {
- const size_t oldColumnSize = m_grid[0].size();
- for (size_t row = 0; row < m_grid.size(); ++row)
- m_grid[row].grow(oldColumnSize + 1);
- } else {
- const size_t oldRowSize = m_grid.size();
- m_grid.grow(oldRowSize + 1);
- m_grid[oldRowSize].grow(m_grid[0].size());
+ const size_t oldRowSize = gridRowCount();
+ if (maximumRowIndex >= oldRowSize) {
+ m_grid.grow(maximumRowIndex + 1);
+ for (size_t row = oldRowSize; row < gridRowCount(); ++row)
+ m_grid[row].grow(gridColumnCount());
+ }
+
+ if (maximumColumnIndex >= gridColumnCount()) {
+ for (size_t row = 0; row < gridRowCount(); ++row)
+ m_grid[row].grow(maximumColumnIndex + 1);
}
}
void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
{
- for (size_t row = coordinate.rows.initialPositionIndex; row <= coordinate.rows.finalPositionIndex; ++row) {
- for (size_t column = coordinate.columns.initialPositionIndex; column <= coordinate.columns.finalPositionIndex; ++column)
- m_grid[row][column].append(child);
+ ensureGridSize(coordinate.rows.resolvedFinalPosition.toInt(), coordinate.columns.resolvedFinalPosition.toInt());
+
+ for (GridSpan::iterator row = coordinate.rows.begin(); row != coordinate.rows.end(); ++row) {
+ for (GridSpan::iterator column = coordinate.columns.begin(); column != coordinate.columns.end(); ++column)
+ m_grid[row.toInt()][column.toInt()].append(child);
}
m_gridItemCoordinate.set(child, coordinate);
}
-void RenderGrid::insertItemIntoGrid(RenderBox* child, size_t rowTrack, size_t columnTrack)
-{
- const GridSpan& rowSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForRows, rowTrack);
- const GridSpan& columnSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForColumns, columnTrack);
- insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
-}
-
void RenderGrid::placeItemsOnGrid()
{
if (!gridIsDirty())
@@ -704,8 +798,8 @@ void RenderGrid::placeItemsOnGrid()
for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
// FIXME: We never re-resolve positions if the grid is grown during auto-placement which may lead auto / <integer>
// positions to not match the author's intent. The specification is unclear on what should be done in this case.
- OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
- OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
+ OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForRows);
+ OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForColumns);
if (!rowPositions || !columnPositions) {
GridSpan* majorAxisPositions = (autoPlacementMajorAxisDirection() == ForColumns) ? columnPositions.get() : rowPositions.get();
if (!majorAxisPositions)
@@ -717,8 +811,8 @@ void RenderGrid::placeItemsOnGrid()
insertItemIntoGrid(child, GridCoordinate(*rowPositions, *columnPositions));
}
- ASSERT(gridRowCount() >= style()->gridDefinitionRows().size());
- ASSERT(gridColumnCount() >= style()->gridDefinitionColumns().size());
+ ASSERT(gridRowCount() >= style()->gridTemplateRows().size());
+ ASSERT(gridColumnCount() >= style()->gridTemplateColumns().size());
if (autoFlow == AutoFlowNone) {
// If we did collect some grid items, they won't be placed thus never laid out.
@@ -737,22 +831,35 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
{
OrderIteratorPopulator populator(m_orderIterator);
- size_t maximumRowIndex = std::max<size_t>(1, explicitGridRowCount());
- size_t maximumColumnIndex = std::max<size_t>(1, explicitGridColumnCount());
+ size_t maximumRowIndex = std::max<size_t>(1, GridResolvedPosition::explicitGridRowCount(*style()));
+ size_t maximumColumnIndex = std::max<size_t>(1, GridResolvedPosition::explicitGridColumnCount(*style()));
+ ASSERT(m_gridItemsIndexesMap.isEmpty());
+ size_t childIndex = 0;
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
populator.collectChild(child);
+ m_gridItemsIndexesMap.set(child, childIndex++);
// This function bypasses the cache (cachedGridCoordinate()) as it is used to build it.
- OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
- OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
-
- // |positions| is 0 if we need to run the auto-placement algorithm. Our estimation ignores
- // this case as the auto-placement algorithm will grow the grid as needed.
- if (rowPositions)
- maximumRowIndex = std::max(maximumRowIndex, rowPositions->finalPositionIndex + 1);
- if (columnPositions)
- maximumColumnIndex = std::max(maximumColumnIndex, columnPositions->finalPositionIndex + 1);
+ OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForRows);
+ OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForColumns);
+
+ // |positions| is 0 if we need to run the auto-placement algorithm.
+ if (rowPositions) {
+ maximumRowIndex = std::max<size_t>(maximumRowIndex, rowPositions->resolvedFinalPosition.next().toInt());
+ } else {
+ // Grow the grid for items with a definite row span, getting the largest such span.
+ GridSpan positions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *child, ForRows, GridResolvedPosition(0));
+ maximumRowIndex = std::max<size_t>(maximumRowIndex, positions.resolvedFinalPosition.next().toInt());
+ }
+
+ if (columnPositions) {
+ maximumColumnIndex = std::max<size_t>(maximumColumnIndex, columnPositions->resolvedFinalPosition.next().toInt());
+ } else {
+ // Grow the grid for items with a definite column span, getting the largest such span.
+ GridSpan positions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *child, ForColumns, GridResolvedPosition(0));
+ maximumColumnIndex = std::max<size_t>(maximumColumnIndex, positions.resolvedFinalPosition.next().toInt());
+ }
}
m_grid.grow(maximumRowIndex);
@@ -760,20 +867,25 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
m_grid[i].grow(maximumColumnIndex);
}
+PassOwnPtr<GridCoordinate> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(const RenderBox* gridItem, GridTrackSizingDirection specifiedDirection, const GridSpan& specifiedPositions) const
+{
+ GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
+ const size_t endOfCrossDirection = crossDirection == ForColumns ? gridColumnCount() : gridRowCount();
+ GridSpan crossDirectionPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, crossDirection, GridResolvedPosition(endOfCrossDirection));
+ return adoptPtr(new GridCoordinate(specifiedDirection == ForColumns ? crossDirectionPositions : specifiedPositions, specifiedDirection == ForColumns ? specifiedPositions : crossDirectionPositions));
+}
+
void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGridItems)
{
for (size_t i = 0; i < autoGridItems.size(); ++i) {
- OwnPtr<GridSpan> majorAxisPositions = resolveGridPositionsFromStyle(autoGridItems[i], autoPlacementMajorAxisDirection());
- GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->initialPositionIndex);
- if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
- insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
- continue;
- }
-
- growGrid(autoPlacementMinorAxisDirection());
- OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
- ASSERT(emptyGridArea);
- insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+ OwnPtr<GridSpan> majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *autoGridItems[i], autoPlacementMajorAxisDirection());
+ GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *autoGridItems[i], autoPlacementMinorAxisDirection(), GridResolvedPosition(0));
+
+ GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->resolvedInitialPosition.toInt());
+ OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions->integerSpan(), minorAxisPositions.integerSpan());
+ if (!emptyGridArea)
+ emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(autoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPositions);
+ insertItemIntoGrid(autoGridItems[i], *emptyGridArea);
}
}
@@ -785,32 +897,41 @@ void RenderGrid::placeAutoMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGri
void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
{
- OwnPtr<GridSpan> minorAxisPositions = resolveGridPositionsFromStyle(gridItem, autoPlacementMinorAxisDirection());
- ASSERT(!resolveGridPositionsFromStyle(gridItem, autoPlacementMajorAxisDirection()));
- size_t minorAxisIndex = 0;
+ OwnPtr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMinorAxisDirection());
+ ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMajorAxisDirection()));
+ GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMajorAxisDirection(), GridResolvedPosition(0));
+ OwnPtr<GridCoordinate> emptyGridArea;
if (minorAxisPositions) {
- minorAxisIndex = minorAxisPositions->initialPositionIndex;
- GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisIndex);
- if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
- insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
- return;
- }
+ GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisPositions->resolvedInitialPosition.toInt());
+ emptyGridArea = iterator.nextEmptyGridArea(minorAxisPositions->integerSpan(), majorAxisPositions.integerSpan());
+ if (!emptyGridArea)
+ emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions);
} else {
+ GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMinorAxisDirection(), GridResolvedPosition(0));
+
const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : gridRowCount();
for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) {
GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisIndex);
- if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
- insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
- return;
+ emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions.integerSpan(), minorAxisPositions.integerSpan());
+
+ if (emptyGridArea) {
+ // Check that it fits in the minor axis direction, as we shouldn't grow in that direction here (it was already managed in populateExplicitGridAndOrderIterator()).
+ GridResolvedPosition minorAxisFinalPositionIndex = autoPlacementMinorAxisDirection() == ForColumns ? emptyGridArea->columns.resolvedFinalPosition : emptyGridArea->rows.resolvedFinalPosition;
+ const size_t endOfMinorAxis = autoPlacementMinorAxisDirection() == ForColumns ? gridColumnCount() : gridRowCount();
+ if (minorAxisFinalPositionIndex.toInt() < endOfMinorAxis)
+ break;
+
+ // Discard empty grid area as it does not fit in the minor axis direction.
+ // We don't need to create a new empty grid area yet as we might find a valid one in the next iteration.
+ emptyGridArea = nullptr;
}
}
+
+ if (!emptyGridArea)
+ emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions);
}
- // We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it.
- const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? m_grid[0].size() : minorAxisIndex;
- const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : m_grid.size();
- growGrid(autoPlacementMajorAxisDirection());
- insertItemIntoGrid(gridItem, rowIndex, columnIndex);
+ insertItemIntoGrid(gridItem, *emptyGridArea);
}
GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
@@ -832,6 +953,8 @@ void RenderGrid::dirtyGrid()
m_grid.resize(0);
m_gridItemCoordinate.clear();
m_gridIsDirty = true;
+ m_gridItemsOverflowingGridArea.resize(0);
+ m_gridItemsIndexesMap.clear();
}
void RenderGrid::layoutGridItems()
@@ -839,12 +962,13 @@ void RenderGrid::layoutGridItems()
placeItemsOnGrid();
GridSizingData sizingData(gridColumnCount(), gridRowCount());
- computedUsedBreadthOfGridTracks(ForColumns, sizingData);
+ computeUsedBreadthOfGridTracks(ForColumns, sizingData);
ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData.columnTracks));
- computedUsedBreadthOfGridTracks(ForRows, sizingData);
+ computeUsedBreadthOfGridTracks(ForRows, sizingData);
ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData.rowTracks));
populateGridPositions(sizingData);
+ m_gridItemsOverflowingGridArea.resize(0);
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
// Because the grid area cannot be styled, we don't need to adjust
@@ -855,7 +979,7 @@ void RenderGrid::layoutGridItems()
LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, sizingData.columnTracks);
LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, sizingData.rowTracks);
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || (oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight && child->hasRelativeLogicalHeight()))
layoutScope.setNeedsLayout(child);
@@ -869,16 +993,23 @@ void RenderGrid::layoutGridItems()
// now, just size as if we were a regular child.
child->layoutIfNeeded();
- child->setLogicalLocation(findChildLogicalPosition(child, sizingData));
+#ifndef NDEBUG
+ const GridCoordinate& coordinate = cachedGridCoordinate(child);
+ ASSERT(coordinate.columns.resolvedInitialPosition.toInt() < sizingData.columnTracks.size());
+ ASSERT(coordinate.rows.resolvedInitialPosition.toInt() < sizingData.rowTracks.size());
+#endif
+ child->setLogicalLocation(findChildLogicalPosition(child));
- // For correctness, we disable some painting optimizations if we have a child overflowing its grid area.
- m_gridItemOverflowGridArea = child->logicalHeight() > overrideContainingBlockContentLogicalHeight
- || child->logicalWidth() > overrideContainingBlockContentLogicalWidth;
+ // Keep track of children overflowing their grid area as we might need to paint them even if the grid-area is
+ // not visible
+ if (child->logicalHeight() > overrideContainingBlockContentLogicalHeight
+ || child->logicalWidth() > overrideContainingBlockContentLogicalWidth)
+ m_gridItemsOverflowingGridArea.append(child);
// If the child moved, we have to repaint it as well as any floating/positioned
// descendants. An exception is if we need a layout. In this case, we know we're going to
// repaint ourselves (and the child) anyway.
- if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ if (!selfNeedsLayout() && child->checkForPaintInvalidationDuringLayout())
child->repaintDuringLayoutIfMoved(oldChildRect);
}
@@ -896,243 +1027,219 @@ GridCoordinate RenderGrid::cachedGridCoordinate(const RenderBox* gridItem) const
return m_gridItemCoordinate.get(gridItem);
}
-GridSpan RenderGrid::resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, GridTrackSizingDirection, size_t initialPosition) const
+LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox* child, GridTrackSizingDirection direction, const Vector<GridTrack>& tracks) const
{
- // FIXME: We don't support spanning with auto positions yet. Once we do, this is wrong. Also we should make
- // sure the grid can accomodate the new item as we only grow 1 position in a given direction.
- return GridSpan(initialPosition, initialPosition);
+ const GridCoordinate& coordinate = cachedGridCoordinate(child);
+ const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
+ LayoutUnit gridAreaBreadth = 0;
+ for (GridSpan::iterator trackPosition = span.begin(); trackPosition != span.end(); ++trackPosition)
+ gridAreaBreadth += tracks[trackPosition.toInt()].m_usedBreadth;
+ return gridAreaBreadth;
}
-PassOwnPtr<GridSpan> RenderGrid::resolveGridPositionsFromStyle(const RenderBox* gridItem, GridTrackSizingDirection direction) const
+void RenderGrid::populateGridPositions(const GridSizingData& sizingData)
{
- const GridPosition& initialPosition = (direction == ForColumns) ? gridItem->style()->gridColumnStart() : gridItem->style()->gridRowStart();
- const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide;
- const GridPosition& finalPosition = (direction == ForColumns) ? gridItem->style()->gridColumnEnd() : gridItem->style()->gridRowEnd();
- const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide;
-
- // We should NEVER see both spans as they should have been handled during style resolve.
- ASSERT(!initialPosition.isSpan() || !finalPosition.isSpan());
-
- if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
- if (style()->gridAutoFlow() == AutoFlowNone)
- return adoptPtr(new GridSpan(0, 0));
-
- // We can't get our grid positions without running the auto placement algorithm.
- return nullptr;
- }
-
- if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
- // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
- const size_t finalResolvedPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
- return resolveGridPositionAgainstOppositePosition(finalResolvedPosition, initialPosition, initialPositionSide);
- }
-
- if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
- // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
- const size_t initialResolvedPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
- return resolveGridPositionAgainstOppositePosition(initialResolvedPosition, finalPosition, finalPositionSide);
- }
-
- size_t resolvedInitialPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
- size_t resolvedFinalPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
-
- // If 'grid-after' specifies a line at or before that specified by 'grid-before', it computes to 'span 1'.
- if (resolvedFinalPosition < resolvedInitialPosition)
- resolvedFinalPosition = resolvedInitialPosition;
+ m_columnPositions.resize(sizingData.columnTracks.size() + 1);
+ m_columnPositions[0] = borderAndPaddingStart();
+ for (size_t i = 0; i < m_columnPositions.size() - 1; ++i)
+ m_columnPositions[i + 1] = m_columnPositions[i] + sizingData.columnTracks[i].m_usedBreadth;
- return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
+ m_rowPositions.resize(sizingData.rowTracks.size() + 1);
+ m_rowPositions[0] = borderAndPaddingBefore();
+ for (size_t i = 0; i < m_rowPositions.size() - 1; ++i)
+ m_rowPositions[i + 1] = m_rowPositions[i] + sizingData.rowTracks[i].m_usedBreadth;
}
-size_t RenderGrid::resolveNamedGridLinePositionFromStyle(const GridPosition& position, GridPositionSide side) const
+LayoutUnit RenderGrid::startOfColumnForChild(const RenderBox* child) const
{
- ASSERT(!position.namedGridLine().isNull());
-
- const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
- NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
- if (it == gridLinesNames.end()) {
- if (position.isPositive())
- return 0;
- const size_t lastLine = explicitGridSizeForSide(side);
- return GridPosition::adjustGridPositionForSide(lastLine, side);
- }
-
- size_t namedGridLineIndex;
- if (position.isPositive())
- namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
- else
- namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
- return GridPosition::adjustGridPositionForSide(it->value[namedGridLineIndex], side);
+ const GridCoordinate& coordinate = cachedGridCoordinate(child);
+ LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInitialPosition.toInt()];
+ // The grid items should be inside the grid container's border box, that's why they need to be shifted.
+ // FIXME: This should account for the grid item's <overflow-position>.
+ return startOfColumn + marginStartForChild(child);
}
-size_t RenderGrid::resolveGridPositionFromStyle(const GridPosition& position, GridPositionSide side) const
+LayoutUnit RenderGrid::endOfColumnForChild(const RenderBox* child) const
{
- switch (position.type()) {
- case ExplicitPosition: {
- ASSERT(position.integerPosition());
-
- if (!position.namedGridLine().isNull())
- return resolveNamedGridLinePositionFromStyle(position, side);
-
- // Handle <integer> explicit position.
- if (position.isPositive())
- return GridPosition::adjustGridPositionForSide(position.integerPosition() - 1, side);
-
- size_t resolvedPosition = abs(position.integerPosition()) - 1;
- const size_t endOfTrack = explicitGridSizeForSide(side);
-
- // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
- if (endOfTrack < resolvedPosition)
- return 0;
+ const GridCoordinate& coordinate = cachedGridCoordinate(child);
+ LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInitialPosition.toInt()];
+ // The grid items should be inside the grid container's border box, that's why they need to be shifted.
+ LayoutUnit columnPosition = startOfColumn + marginStartForChild(child);
- return GridPosition::adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
- }
- case NamedGridAreaPosition:
- {
- NamedGridAreaMap::const_iterator it = style()->namedGridArea().find(position.namedGridLine());
- // Unknown grid area should have been computed to 'auto' by now.
- ASSERT_WITH_SECURITY_IMPLICATION(it != style()->namedGridArea().end());
- const GridCoordinate& gridAreaCoordinate = it->value;
- switch (side) {
- case ColumnStartSide:
- return gridAreaCoordinate.columns.initialPositionIndex;
- case ColumnEndSide:
- return gridAreaCoordinate.columns.finalPositionIndex;
- case RowStartSide:
- return gridAreaCoordinate.rows.initialPositionIndex;
- case RowEndSide:
- return gridAreaCoordinate.rows.finalPositionIndex;
- }
- ASSERT_NOT_REACHED();
- return 0;
- }
- case AutoPosition:
- case SpanPosition:
- // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
- ASSERT_NOT_REACHED();
- return 0;
- }
- ASSERT_NOT_REACHED();
- return 0;
+ LayoutUnit endOfColumn = m_columnPositions[coordinate.columns.resolvedFinalPosition.next().toInt()];
+ // FIXME: This should account for the grid item's <overflow-position>.
+ return columnPosition + std::max<LayoutUnit>(0, endOfColumn - m_columnPositions[coordinate.columns.resolvedInitialPosition.toInt()] - child->logicalWidth());
}
-PassOwnPtr<GridSpan> RenderGrid::resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
+LayoutUnit RenderGrid::columnPositionAlignedWithGridContainerStart(const RenderBox* child) const
{
- if (position.isAuto())
- return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
+ if (style()->isLeftToRightDirection())
+ return startOfColumnForChild(child);
- ASSERT(position.isSpan());
- ASSERT(position.spanPosition() > 0);
-
- if (!position.namedGridLine().isNull()) {
- // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
- return resolveNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, side);
- }
-
- return GridSpan::createWithSpanAgainstOpposite(resolvedOppositePosition, position, side);
+ return endOfColumnForChild(child);
}
-PassOwnPtr<GridSpan> RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
+LayoutUnit RenderGrid::columnPositionAlignedWithGridContainerEnd(const RenderBox* child) const
{
- ASSERT(position.isSpan());
- ASSERT(!position.namedGridLine().isNull());
- // Negative positions are not allowed per the specification and should have been handled during parsing.
- ASSERT(position.spanPosition() > 0);
+ if (!style()->isLeftToRightDirection())
+ return startOfColumnForChild(child);
- const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
- NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
-
- // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
- // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
- if (it == gridLinesNames.end())
- return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
-
- return GridSpan::createWithNamedSpanAgainstOpposite(resolvedOppositePosition, position, side, it->value);
+ return endOfColumnForChild(child);
}
-LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox* child, GridTrackSizingDirection direction, const Vector<GridTrack>& tracks) const
+LayoutUnit RenderGrid::centeredColumnPositionForChild(const RenderBox* child) const
{
const GridCoordinate& coordinate = cachedGridCoordinate(child);
- const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
- LayoutUnit gridAreaBreadth = 0;
- for (size_t trackIndex = span.initialPositionIndex; trackIndex <= span.finalPositionIndex; ++trackIndex)
- gridAreaBreadth += tracks[trackIndex].m_usedBreadth;
- return gridAreaBreadth;
+ LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInitialPosition.toInt()];
+ LayoutUnit endOfColumn = m_columnPositions[coordinate.columns.resolvedFinalPosition.next().toInt()];
+ LayoutUnit columnPosition = startOfColumn + marginStartForChild(child);
+ return columnPosition + std::max<LayoutUnit>(0, endOfColumn - startOfColumn - child->logicalWidth()) / 2;
}
-void RenderGrid::populateGridPositions(const GridSizingData& sizingData)
+LayoutUnit RenderGrid::columnPositionForChild(const RenderBox* child) const
{
- m_columnPositions.resize(sizingData.columnTracks.size() + 1);
- m_columnPositions[0] = borderAndPaddingStart();
- for (size_t i = 0; i < m_columnPositions.size() - 1; ++i)
- m_columnPositions[i + 1] = m_columnPositions[i] + sizingData.columnTracks[i].m_usedBreadth;
+ ItemPosition childJustifySelf = child->style()->justifySelf();
+ switch (childJustifySelf) {
+ case ItemPositionSelfStart:
+ // self-start is based on the child's direction. That's why we need to check against the grid container's direction.
+ if (child->style()->direction() != style()->direction())
+ return columnPositionAlignedWithGridContainerEnd(child);
+
+ return columnPositionAlignedWithGridContainerStart(child);
+ case ItemPositionSelfEnd:
+ // self-end is based on the child's direction. That's why we need to check against the grid container's direction.
+ if (child->style()->direction() != style()->direction())
+ return columnPositionAlignedWithGridContainerStart(child);
+
+ return columnPositionAlignedWithGridContainerEnd(child);
+
+ case ItemPositionFlexStart:
+ case ItemPositionFlexEnd:
+ // Only used in flex layout, for other layout, it's equivalent to 'start'.
+ return columnPositionAlignedWithGridContainerStart(child);
+
+ case ItemPositionLeft:
+ // If the property's axis is not parallel with the inline axis, this is equivalent to ‘start’.
+ if (!isHorizontalWritingMode())
+ return columnPositionAlignedWithGridContainerStart(child);
+
+ if (style()->isLeftToRightDirection())
+ return columnPositionAlignedWithGridContainerStart(child);
+
+ return columnPositionAlignedWithGridContainerEnd(child);
+ case ItemPositionRight:
+ // If the property's axis is not parallel with the inline axis, this is equivalent to ‘start’.
+ if (!isHorizontalWritingMode())
+ return columnPositionAlignedWithGridContainerStart(child);
+
+ if (style()->isLeftToRightDirection())
+ return columnPositionAlignedWithGridContainerEnd(child);
+
+ return columnPositionAlignedWithGridContainerStart(child);
+
+ case ItemPositionCenter:
+ return centeredColumnPositionForChild(child);
+ case ItemPositionStart:
+ return columnPositionAlignedWithGridContainerStart(child);
+ case ItemPositionEnd:
+ return columnPositionAlignedWithGridContainerEnd(child);
+
+ case ItemPositionAuto:
+ case ItemPositionStretch:
+ case ItemPositionBaseline:
+ // FIXME: Implement the previous values. For now, we always start align the child.
+ return startOfColumnForChild(child);
+ }
- m_rowPositions.resize(sizingData.rowTracks.size() + 1);
- m_rowPositions[0] = borderAndPaddingBefore();
- for (size_t i = 0; i < m_rowPositions.size() - 1; ++i)
- m_rowPositions[i + 1] = m_rowPositions[i] + sizingData.rowTracks[i].m_usedBreadth;
+ ASSERT_NOT_REACHED();
+ return 0;
}
-LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const GridSizingData& sizingData)
+LayoutUnit RenderGrid::rowPositionForChild(const RenderBox* child) const
{
const GridCoordinate& coordinate = cachedGridCoordinate(child);
- ASSERT(coordinate.columns.initialPositionIndex < sizingData.columnTracks.size());
- ASSERT(coordinate.rows.initialPositionIndex < sizingData.rowTracks.size());
// The grid items should be inside the grid container's border box, that's why they need to be shifted.
- return LayoutPoint(m_columnPositions[coordinate.columns.initialPositionIndex] + marginStartForChild(child), m_rowPositions[coordinate.rows.initialPositionIndex] + marginBeforeForChild(child));
+ LayoutUnit startOfRow = m_rowPositions[coordinate.rows.resolvedInitialPosition.toInt()];
+ LayoutUnit rowPosition = startOfRow + marginBeforeForChild(child);
+
+ // FIXME: This function should account for 'align-self'.
+
+ return rowPosition;
+}
+
+LayoutPoint RenderGrid::findChildLogicalPosition(const RenderBox* child) const
+{
+ return LayoutPoint(columnPositionForChild(child), rowPositionForChild(child));
}
static GridSpan dirtiedGridAreas(const Vector<LayoutUnit>& coordinates, LayoutUnit start, LayoutUnit end)
{
// This function does a binary search over the coordinates.
- // FIXME: This doesn't work with grid items overflowing their grid areas and should be tested & fixed.
+ // This doesn't work with grid items overflowing their grid areas, but that is managed with m_gridItemsOverflowingGridArea.
size_t startGridAreaIndex = std::upper_bound(coordinates.begin(), coordinates.end() - 1, start) - coordinates.begin();
if (startGridAreaIndex > 0)
--startGridAreaIndex;
size_t endGridAreaIndex = std::upper_bound(coordinates.begin() + startGridAreaIndex, coordinates.end() - 1, end) - coordinates.begin();
+ if (endGridAreaIndex > 0)
+ --endGridAreaIndex;
+
return GridSpan(startGridAreaIndex, endGridAreaIndex);
}
-void RenderGrid::paintChildrenSlowCase(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
- for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next())
- paintChild(child, paintInfo, paintOffset);
-}
+class GridItemsSorter {
+public:
+ bool operator()(const std::pair<RenderBox*, size_t> firstChild, const std::pair<RenderBox*, size_t> secondChild) const
+ {
+ if (firstChild.first->style()->order() != secondChild.first->style()->order())
+ return firstChild.first->style()->order() < secondChild.first->style()->order();
+
+ return firstChild.second < secondChild.second;
+ }
+};
void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
ASSERT_WITH_SECURITY_IMPLICATION(!gridIsDirty());
- if (m_gridItemOverflowGridArea) {
- paintChildrenSlowCase(paintInfo, paintOffset);
- return;
- }
-
LayoutRect localRepaintRect = paintInfo.rect;
localRepaintRect.moveBy(-paintOffset);
GridSpan dirtiedColumns = dirtiedGridAreas(m_columnPositions, localRepaintRect.x(), localRepaintRect.maxX());
GridSpan dirtiedRows = dirtiedGridAreas(m_rowPositions, localRepaintRect.y(), localRepaintRect.maxY());
- OrderIterator paintIterator(this);
- {
- OrderIteratorPopulator populator(paintIterator);
-
- for (size_t row = dirtiedRows.initialPositionIndex; row < dirtiedRows.finalPositionIndex; ++row) {
- for (size_t column = dirtiedColumns.initialPositionIndex; column < dirtiedColumns.finalPositionIndex; ++column) {
- const Vector<RenderBox*, 1>& children = m_grid[row][column];
- // FIXME: If we start adding spanning children in all grid areas they span, this
- // would make us paint them several times, which is wrong!
- for (size_t j = 0; j < children.size(); ++j)
- populator.storeChild(children[j]);
- }
+ Vector<std::pair<RenderBox*, size_t> > gridItemsToBePainted;
+
+ for (GridSpan::iterator row = dirtiedRows.begin(); row != dirtiedRows.end(); ++row) {
+ for (GridSpan::iterator column = dirtiedColumns.begin(); column != dirtiedColumns.end(); ++column) {
+ const Vector<RenderBox*, 1>& children = m_grid[row.toInt()][column.toInt()];
+ for (size_t j = 0; j < children.size(); ++j)
+ gridItemsToBePainted.append(std::make_pair(children[j], m_gridItemsIndexesMap.get(children[j])));
}
}
- for (RenderBox* child = paintIterator.first(); child; child = paintIterator.next())
- paintChild(child, paintInfo, paintOffset);
+ for (Vector<RenderBox*>::const_iterator it = m_gridItemsOverflowingGridArea.begin(); it != m_gridItemsOverflowingGridArea.end(); ++it) {
+ if ((*it)->frameRect().intersects(localRepaintRect))
+ gridItemsToBePainted.append(std::make_pair(*it, m_gridItemsIndexesMap.get(*it)));
+ }
+
+ // Sort grid items following order-modified document order.
+ // See http://www.w3.org/TR/css-flexbox/#order-modified-document-order
+ std::stable_sort(gridItemsToBePainted.begin(), gridItemsToBePainted.end(), GridItemsSorter());
+
+ RenderBox* previous = 0;
+ for (Vector<std::pair<RenderBox*, size_t> >::const_iterator it = gridItemsToBePainted.begin(); it != gridItemsToBePainted.end(); ++it) {
+ // We might have duplicates because of spanning children are included in all cells they span.
+ // Skip them here to avoid painting items several times.
+ RenderBox* current = (*it).first;
+ if (current == previous)
+ continue;
+
+ paintChild(current, paintInfo, paintOffset);
+ previous = current;
+ }
}
const char* RenderGrid::renderName() const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.h b/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.h
index f8a4de326f5..d06e2632141 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderGrid.h
@@ -28,6 +28,7 @@
#include "core/rendering/OrderIterator.h"
#include "core/rendering/RenderBlock.h"
+#include "core/rendering/style/GridResolvedPosition.h"
namespace WebCore {
@@ -35,11 +36,6 @@ struct GridCoordinate;
struct GridSpan;
class GridTrack;
-enum GridTrackSizingDirection {
- ForColumns,
- ForRows
-};
-
class RenderGrid FINAL : public RenderBlock {
public:
RenderGrid(Element*);
@@ -47,7 +43,7 @@ public:
virtual const char* renderName() const OVERRIDE;
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
+ virtual void layoutBlock(bool relayoutChildren) OVERRIDE;
virtual bool avoidsFloats() const OVERRIDE { return true; }
virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return false; }
@@ -63,6 +59,7 @@ private:
virtual void computePreferredLogicalWidths() OVERRIDE;
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+ void addChildToIndexesMap(RenderBox*);
virtual void removeChild(RenderObject*) OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
@@ -72,18 +69,19 @@ private:
class GridIterator;
struct GridSizingData;
- void computedUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&);
- void computedUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace);
+ bool gridElementIsShrinkToFit();
+ void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&);
+ void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace);
LayoutUnit computeUsedBreadthOfMinLength(GridTrackSizingDirection, const GridLength&) const;
LayoutUnit computeUsedBreadthOfMaxLength(GridTrackSizingDirection, const GridLength&, LayoutUnit usedBreadth) const;
LayoutUnit computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirection, const Length&) const;
void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace);
- void growGrid(GridTrackSizingDirection);
- void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack);
+ void ensureGridSize(size_t maximumRowIndex, size_t maximumColumnIndex);
void insertItemIntoGrid(RenderBox*, const GridCoordinate&);
void placeItemsOnGrid();
void populateExplicitGridAndOrderIterator();
+ PassOwnPtr<GridCoordinate> createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(const RenderBox*, GridTrackSizingDirection, const GridSpan& specifiedPositions) const;
void placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>&);
void placeAutoMajorAxisItemsOnGrid(const Vector<RenderBox*>&);
void placeAutoMajorAxisItemOnGrid(RenderBox*);
@@ -93,8 +91,6 @@ private:
void layoutGridItems();
void populateGridPositions(const GridSizingData&);
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
typedef LayoutUnit (RenderGrid::* SizingFunction)(RenderBox*, GridTrackSizingDirection, Vector<GridTrack>&);
typedef LayoutUnit (GridTrack::* AccumulatorGetter)() const;
typedef void (GridTrack::* AccumulatorGrowFunction)(LayoutUnit);
@@ -102,32 +98,26 @@ private:
void resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection, GridSizingData&, RenderBox*, FilterFunction, SizingFunction, AccumulatorGetter, AccumulatorGrowFunction);
void distributeSpaceToTracks(Vector<GridTrack*>&, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter, AccumulatorGrowFunction, GridSizingData&, LayoutUnit& availableLogicalSpace);
- double computeNormalizedFractionBreadth(Vector<GridTrack>&, GridTrackSizingDirection, LayoutUnit availableLogicalSpace) const;
+ double computeNormalizedFractionBreadth(Vector<GridTrack>&, const GridSpan& tracksSpan, GridTrackSizingDirection, LayoutUnit availableLogicalSpace) const;
const GridTrackSize& gridTrackSize(GridTrackSizingDirection, size_t) const;
- size_t explicitGridColumnCount() const;
- size_t explicitGridRowCount() const;
- size_t explicitGridSizeForSide(GridPositionSide) const;
- LayoutUnit logicalContentHeightForChild(RenderBox*, Vector<GridTrack>&);
+ LayoutUnit logicalHeightForChild(RenderBox*, Vector<GridTrack>&);
LayoutUnit minContentForChild(RenderBox*, GridTrackSizingDirection, Vector<GridTrack>& columnTracks);
LayoutUnit maxContentForChild(RenderBox*, GridTrackSizingDirection, Vector<GridTrack>& columnTracks);
- LayoutPoint findChildLogicalPosition(RenderBox*, const GridSizingData&);
+ LayoutUnit startOfColumnForChild(const RenderBox* child) const;
+ LayoutUnit endOfColumnForChild(const RenderBox* child) const;
+ LayoutUnit columnPositionAlignedWithGridContainerStart(const RenderBox*) const;
+ LayoutUnit columnPositionAlignedWithGridContainerEnd(const RenderBox*) const;
+ LayoutUnit centeredColumnPositionForChild(const RenderBox*) const;
+ LayoutUnit columnPositionForChild(const RenderBox*) const;
+ LayoutUnit rowPositionForChild(const RenderBox*) const;
+ LayoutPoint findChildLogicalPosition(const RenderBox*) const;
GridCoordinate cachedGridCoordinate(const RenderBox*) const;
- GridSpan resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, GridTrackSizingDirection, size_t) const;
- PassOwnPtr<GridSpan> resolveGridPositionsFromStyle(const RenderBox*, GridTrackSizingDirection) const;
- size_t resolveNamedGridLinePositionFromStyle(const GridPosition&, GridPositionSide) const;
- size_t resolveGridPositionFromStyle(const GridPosition&, GridPositionSide) const;
- PassOwnPtr<GridSpan> resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, GridPositionSide) const;
- PassOwnPtr<GridSpan> resolveNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, GridPositionSide) const;
- PassOwnPtr<GridSpan> resolveBeforeStartNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, const Vector<size_t>&) const;
- PassOwnPtr<GridSpan> resolveAfterEndNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, const Vector<size_t>&) const;
-
LayoutUnit gridAreaBreadthForChild(const RenderBox* child, GridTrackSizingDirection, const Vector<GridTrack>&) const;
- virtual void paintChildren(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
- void paintChildrenSlowCase(PaintInfo&, const LayoutPoint&);
+ virtual void paintChildren(PaintInfo&, const LayoutPoint&) OVERRIDE;
bool gridIsDirty() const { return m_gridIsDirty; }
@@ -154,7 +144,8 @@ private:
Vector<LayoutUnit> m_columnPositions;
HashMap<const RenderBox*, GridCoordinate> m_gridItemCoordinate;
OrderIterator m_orderIterator;
- bool m_gridItemOverflowGridArea;
+ Vector<RenderBox*> m_gridItemsOverflowingGridArea;
+ HashMap<const RenderBox*, size_t> m_gridItemsIndexesMap;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderGrid, isRenderGrid());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.cpp
index 96a06bbb5fd..41a29420906 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.cpp
@@ -28,8 +28,8 @@
#include "core/html/HTMLCanvasElement.h"
#include "core/html/canvas/CanvasRenderingContext.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/page/Page.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderView.h"
@@ -44,13 +44,9 @@ RenderHTMLCanvas::RenderHTMLCanvas(HTMLCanvasElement* element)
view()->frameView()->setIsVisuallyNonEmpty();
}
-bool RenderHTMLCanvas::requiresLayer() const
+LayerType RenderHTMLCanvas::layerTypeRequired() const
{
- if (RenderReplaced::requiresLayer())
- return true;
-
- HTMLCanvasElement* canvas = toHTMLCanvasElement(node());
- return canvas && canvas->renderingContext() && canvas->renderingContext()->isAccelerated();
+ return NormalLayer;
}
void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -69,8 +65,13 @@ void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& pa
paintInfo.context->clip(pixelSnappedIntRect(contentRect));
}
- bool useLowQualityScale = style()->imageRendering() == ImageRenderingOptimizeContrast;
- toHTMLCanvasElement(node())->paint(context, paintRect, useLowQualityScale);
+ // FIXME: InterpolationNone should be used if ImageRenderingOptimizeContrast is set.
+ // See bug for more details: crbug.com/353716.
+ InterpolationQuality interpolationQuality = style()->imageRendering() == ImageRenderingOptimizeContrast ? InterpolationLow : CanvasDefaultInterpolationQuality;
+ InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality();
+ context->setImageInterpolationQuality(interpolationQuality);
+ toHTMLCanvasElement(node())->paint(context, paintRect);
+ context->setImageInterpolationQuality(previousInterpolationQuality);
if (clip)
context->restore();
@@ -99,7 +100,19 @@ void RenderHTMLCanvas::canvasSizeChanged()
return;
if (!selfNeedsLayout())
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
+}
+
+CompositingReasons RenderHTMLCanvas::additionalCompositingReasons(CompositingTriggerFlags triggers) const
+{
+ if (!(triggers & CanvasTrigger))
+ return CompositingReasonNone;
+
+ HTMLCanvasElement* canvas = toHTMLCanvasElement(node());
+ if (canvas->renderingContext() && canvas->renderingContext()->isAccelerated())
+ return CompositingReasonCanvas;
+
+ return CompositingReasonNone;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.h b/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.h
index 6cdaf64a1da..c06ee44cefc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderHTMLCanvas.h
@@ -36,15 +36,17 @@ class RenderHTMLCanvas FINAL : public RenderReplaced {
public:
explicit RenderHTMLCanvas(HTMLCanvasElement*);
- virtual bool isCanvas() const { return true; }
- virtual bool requiresLayer() const;
+ virtual bool isCanvas() const OVERRIDE { return true; }
+ virtual LayerType layerTypeRequired() const OVERRIDE;
void canvasSizeChanged();
private:
- virtual const char* renderName() const { return "RenderHTMLCanvas"; }
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
- virtual void intrinsicSizeChanged() { canvasSizeChanged(); }
+ virtual const char* renderName() const OVERRIDE { return "RenderHTMLCanvas"; }
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void intrinsicSizeChanged() OVERRIDE { canvasSizeChanged(); }
+
+ virtual CompositingReasons additionalCompositingReasons(CompositingTriggerFlags) const OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderHTMLCanvas, isCanvas());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.cpp
index 85016ccc523..e783f196778 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.cpp
@@ -26,11 +26,10 @@
#include "config.h"
#include "core/rendering/RenderIFrame.h"
-#include "HTMLNames.h"
-#include "core/html/HTMLIFrameElement.h"
-#include "core/frame/Frame.h"
+#include "core/HTMLNames.h"
#include "core/frame/FrameView.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLIFrameElement.h"
#include "core/rendering/RenderView.h"
namespace WebCore {
@@ -44,99 +43,32 @@ RenderIFrame::RenderIFrame(Element* element)
bool RenderIFrame::shouldComputeSizeAsReplaced() const
{
- // When we're seamless, we use normal block/box sizing code except when inline.
- return !isSeamless();
+ return true;
}
bool RenderIFrame::isInlineBlockOrInlineTable() const
{
- return isSeamless() && isInline();
-}
-
-LayoutUnit RenderIFrame::minPreferredLogicalWidth() const
-{
- if (!isSeamless())
- return RenderPart::minPreferredLogicalWidth();
-
- RenderView* childRoot = contentRootRenderer();
- if (!childRoot)
- return 0;
-
- return childRoot->minPreferredLogicalWidth() + borderAndPaddingLogicalWidth();
-}
-
-LayoutUnit RenderIFrame::maxPreferredLogicalWidth() const
-{
- if (!isSeamless())
- return RenderPart::maxPreferredLogicalWidth();
-
- RenderView* childRoot = contentRootRenderer();
- if (!childRoot)
- return 0;
-
- return childRoot->maxPreferredLogicalWidth() + borderAndPaddingLogicalWidth();
-}
-
-bool RenderIFrame::isSeamless() const
-{
- return node() && node()->hasTagName(iframeTag) && toHTMLIFrameElement(node())->shouldDisplaySeamlessly();
-}
-
-bool RenderIFrame::requiresLayer() const
-{
- return RenderPart::requiresLayer() || style()->resize() != RESIZE_NONE;
-}
-
-RenderView* RenderIFrame::contentRootRenderer() const
-{
- // FIXME: Is this always a valid cast? What about plugins?
- ASSERT(!widget() || widget()->isFrameView());
- FrameView* childFrameView = toFrameView(widget());
- return childFrameView ? childFrameView->frame().contentRenderer() : 0;
+ return isInline();
}
-void RenderIFrame::layoutSeamlessly()
+LayerType RenderIFrame::layerTypeRequired() const
{
- updateLogicalWidth();
- // FIXME: Containers set their height to 0 before laying out their kids (as we're doing here)
- // however, this causes FrameView::layout() to add vertical scrollbars, incorrectly inflating
- // the resulting contentHeight(). We'll need to make FrameView::layout() smarter.
- setLogicalHeight(0);
- updateWidgetPosition(); // Tell the Widget about our new width/height (it will also layout the child document).
-
- // Laying out our kids is normally responsible for adjusting our height, so we set it here.
- // Replaced elements normally do not respect padding, but seamless elements should: we'll add
- // both padding and border to the child's logical height here.
- FrameView* childFrameView = toFrameView(widget());
- if (childFrameView) // Widget should never be null during layout(), but just in case.
- setLogicalHeight(childFrameView->contentsHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom());
- updateLogicalHeight();
-
- updateWidgetPosition(); // Notify the Widget of our final height.
-
- // Assert that the child document did a complete layout.
- RenderView* childRoot = childFrameView ? childFrameView->frame().contentRenderer() : 0;
- ASSERT(!childFrameView || !childFrameView->layoutPending());
- ASSERT_UNUSED(childRoot, !childRoot || !childRoot->needsLayout());
+ if (style()->resize() != RESIZE_NONE)
+ return NormalLayer;
+ return RenderPart::layerTypeRequired();
}
void RenderIFrame::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
- if (isSeamless()) {
- layoutSeamlessly();
- // Do not return so as to share the layer and overflow updates below.
- } else {
- updateLogicalWidth();
- // No kids to layout as a replaced element.
- updateLogicalHeight();
- }
+ updateLogicalWidth();
+ // No kids to layout as a replaced element.
+ updateLogicalHeight();
m_overflow.clear();
addVisualEffectOverflow();
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
clearNeedsLayout();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.h b/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.h
index e8a6197c91d..7ec616547c0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderIFrame.h
@@ -30,18 +30,11 @@
namespace WebCore {
-class RenderView;
-
class RenderIFrame FINAL : public RenderPart {
public:
explicit RenderIFrame(Element*);
- bool isSeamless() const;
-
private:
- virtual LayoutUnit minPreferredLogicalWidth() const OVERRIDE;
- virtual LayoutUnit maxPreferredLogicalWidth() const OVERRIDE;
-
virtual bool shouldComputeSizeAsReplaced() const OVERRIDE;
virtual bool isInlineBlockOrInlineTable() const OVERRIDE;
@@ -51,11 +44,7 @@ private:
virtual const char* renderName() const OVERRIDE { return "RenderPartObject"; } // Lying for now to avoid breaking tests
- virtual bool requiresLayer() const OVERRIDE;
-
- void layoutSeamlessly();
-
- RenderView* contentRootRenderer() const;
+ virtual LayerType layerTypeRequired() const OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderIFrame, isRenderIFrame());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
index f2db1e3a3a6..610c7906446 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
@@ -28,19 +28,19 @@
#include "config.h"
#include "core/rendering/RenderImage.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/editing/FrameSelection.h"
#include "core/fetch/ImageResource.h"
#include "core/fetch/ResourceLoadPriorityOptimizer.h"
#include "core/fetch/ResourceLoader.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAreaElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMapElement.h"
#include "core/inspector/InspectorInstrumentation.h"
-#include "core/frame/Frame.h"
+#include "core/inspector/InspectorTraceEvents.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderView.h"
#include "core/svg/graphics/SVGImage.h"
@@ -57,12 +57,12 @@ using namespace HTMLNames;
RenderImage::RenderImage(Element* element)
: RenderReplaced(element, IntSize())
- , m_needsToSetSizeForAltText(false)
, m_didIncrementVisuallyNonEmptyPixelCount(false)
, m_isGeneratedContent(false)
, m_imageDevicePixelRatio(1.0f)
{
updateAltText();
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addRenderObject(this);
}
RenderImage* RenderImage::createAnonymous(Document* document)
@@ -141,22 +141,12 @@ bool RenderImage::setImageSizeForAltText(ImageResource* newImage /* = 0 */)
return true;
}
-void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderReplaced::styleDidChange(diff, oldStyle);
- if (m_needsToSetSizeForAltText) {
- if (!m_altText.isEmpty() && setImageSizeForAltText(m_imageResource->cachedImage()))
- imageDimensionsChanged(true /* imageSizeChanged */);
- m_needsToSetSizeForAltText = false;
- }
-}
-
void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
{
if (documentBeingDestroyed())
return;
- if (hasBoxDecorations() || hasMask())
+ if (hasBoxDecorations() || hasMask() || hasShapeOutside())
RenderReplaced::imageChanged(newImage, rect);
if (!m_imageResource)
@@ -179,29 +169,17 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
bool imageSizeChanged = false;
// Set image dimensions, taking into account the size of the alt text.
- if (m_imageResource->errorOccurred() || !newImage) {
- if (!m_altText.isEmpty() && document().hasPendingStyleRecalc()) {
- ASSERT(node());
- if (node()) {
- m_needsToSetSizeForAltText = true;
- node()->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer);
- }
- return;
- }
+ if (m_imageResource->errorOccurred() || !newImage)
imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage());
- }
- imageDimensionsChanged(imageSizeChanged, rect);
+ repaintOrMarkForLayout(imageSizeChanged, rect);
}
-bool RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize, bool imageSizeChanged)
+void RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize)
{
- if (newSize == intrinsicSize() && !imageSizeChanged)
- return false;
if (m_imageResource->errorOccurred() || !m_imageResource->hasImage())
- return imageSizeChanged;
+ return;
setIntrinsicSize(newSize);
- return true;
}
void RenderImage::updateInnerContentRect()
@@ -213,9 +191,11 @@ void RenderImage::updateInnerContentRect()
m_imageResource->setContainerSizeForRenderer(containerSize);
}
-void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect)
+void RenderImage::repaintOrMarkForLayout(bool imageSizeChangedToAccomodateAltText, const IntRect* rect)
{
- bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->intrinsicSize(style()->effectiveZoom()), imageSizeChanged);
+ LayoutSize oldIntrinsicSize = intrinsicSize();
+ LayoutSize newIntrinsicSize = m_imageResource->intrinsicSize(style()->effectiveZoom());
+ updateIntrinsicSizeIfNeeded(newIntrinsicSize);
// In the case of generated image content using :before/:after/content, we might not be
// in the render tree yet. In that case, we just need to update our intrinsic size.
@@ -224,37 +204,25 @@ void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
if (!containingBlock())
return;
- bool shouldRepaint = true;
- if (intrinsicSizeChanged) {
- if (!preferredLogicalWidthsDirty())
- setPreferredLogicalWidthsDirty();
+ bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize || imageSizeChangedToAccomodateAltText;
+ if (imageSourceHasChangedSize)
+ setPreferredLogicalWidthsDirty();
- bool hasOverrideSize = hasOverrideHeight() || hasOverrideWidth();
- if (!hasOverrideSize && !imageSizeChanged) {
- LogicalExtentComputedValues computedValues;
- computeLogicalWidthInRegion(computedValues);
- LayoutUnit newWidth = computedValues.m_extent;
- computeLogicalHeight(height(), 0, computedValues);
- LayoutUnit newHeight = computedValues.m_extent;
+ // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required.
+ bool imageSizeIsConstrained = style()->logicalWidth().isSpecified() && style()->logicalHeight().isSpecified();
+ bool needsLayout = !imageSizeIsConstrained && imageSourceHasChangedSize;
- imageSizeChanged = width() != newWidth || height() != newHeight;
- }
+ // FIXME: We only need to recompute the containing block's preferred size if the containing block's size
+ // depends on the image's size (i.e., the container uses shrink-to-fit sizing).
+ // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
+ bool containingBlockNeedsToRecomputePreferredSize = style()->logicalWidth().isPercent() || style()->logicalMaxWidth().isPercent() || style()->logicalMinWidth().isPercent();
- // FIXME: We only need to recompute the containing block's preferred size
- // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
- // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
- bool containingBlockNeedsToRecomputePreferredSize =
- style()->logicalWidth().isPercent()
- || style()->logicalMaxWidth().isPercent()
- || style()->logicalMinWidth().isPercent();
-
- if (imageSizeChanged || hasOverrideSize || containingBlockNeedsToRecomputePreferredSize) {
- shouldRepaint = false;
- if (!selfNeedsLayout())
- setNeedsLayout();
- }
+ if (needsLayout || containingBlockNeedsToRecomputePreferredSize) {
+ setNeedsLayoutAndFullPaintInvalidation();
+ return;
}
+ // The image hasn't changed in size or its style constrains its size, so a repaint will suffice.
if (everHadLayout() && !selfNeedsLayout()) {
// The inner content rectangle is calculated during layout, but may need an update now
// (unless the box has already been scheduled for layout). In order to calculate it, we
@@ -263,22 +231,26 @@ void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
updateInnerContentRect();
}
- if (shouldRepaint) {
- LayoutRect repaintRect;
- if (rect) {
- // The image changed rect is in source image coordinates (pre-zooming),
- // so map from the bounds of the image to the contentsBox.
- repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), m_imageResource->imageSize(1.0f)), contentBoxRect()));
- // Guard against too-large changed rects.
- repaintRect.intersect(contentBoxRect());
- } else
- repaintRect = contentBoxRect();
-
- repaintRectangle(repaintRect);
+ LayoutRect repaintRect;
+ if (rect) {
+ // The image changed rect is in source image coordinates (without zoom),
+ // so map from the bounds of the image to the contentsBox.
+ const LayoutSize imageSizeWithoutZoom = m_imageResource->imageSize(1 / style()->effectiveZoom());
+ repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), imageSizeWithoutZoom), contentBoxRect()));
+ // Guard against too-large changed rects.
+ repaintRect.intersect(contentBoxRect());
+ } else {
+ repaintRect = contentBoxRect();
+ }
- // Tell any potential compositing layers that the image needs updating.
- contentChanged(ImageChanged);
+ {
+ // FIXME: We should not be allowing repaint during layout. crbug.com/339584
+ AllowPaintInvalidationScope scoper(frameView());
+ invalidatePaintRectangle(repaintRect);
}
+
+ // Tell any potential compositing layers that the image needs updating.
+ contentChanged(ImageChanged);
}
void RenderImage::notifyFinished(Resource* newImage)
@@ -361,15 +333,20 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
// Only draw the alt text if it'll fit within the content box,
// and only if it fits above the error image.
TextRun textRun = RenderBlockFlow::constructTextRun(this, font, m_altText, style(), TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, DefaultTextRunFlags | RespectDirection);
- LayoutUnit textWidth = font.width(textRun);
+ float textWidth = font.width(textRun);
TextRunPaintInfo textRunPaintInfo(textRun);
textRunPaintInfo.bounds = FloatRect(textRectOrigin, FloatSize(textWidth, fontMetrics.height()));
context->setFillColor(resolveColor(CSSPropertyColor));
+ if (textRun.direction() == RTL) {
+ int availableWidth = cWidth - static_cast<int>(paddingWidth);
+ textOrigin.move(availableWidth - ceilf(textWidth), 0);
+ }
if (errorPictureDrawn) {
if (usableWidth >= textWidth && fontMetrics.height() <= imageOffset.height())
- context->drawText(font, textRunPaintInfo, textOrigin);
- } else if (usableWidth >= textWidth && usableHeight >= fontMetrics.height())
- context->drawText(font, textRunPaintInfo, textOrigin);
+ context->drawBidiText(font, textRunPaintInfo, textOrigin);
+ } else if (usableWidth >= textWidth && usableHeight >= fontMetrics.height()) {
+ context->drawBidiText(font, textRunPaintInfo, textOrigin);
+ }
}
}
} else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) {
@@ -413,21 +390,21 @@ void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
return;
Element* focusedElement = document.focusedElement();
- if (!focusedElement || !isHTMLAreaElement(focusedElement))
+ if (!isHTMLAreaElement(focusedElement))
return;
- HTMLAreaElement* areaElement = toHTMLAreaElement(focusedElement);
- if (areaElement->imageElement() != node())
+ HTMLAreaElement& areaElement = toHTMLAreaElement(*focusedElement);
+ if (areaElement.imageElement() != node())
return;
// Even if the theme handles focus ring drawing for entire elements, it won't do it for
// an area within an image, so we don't call RenderTheme::supportsFocusRing here.
- Path path = areaElement->computePath(this);
+ Path path = areaElement.computePath(this);
if (path.isEmpty())
return;
- RenderStyle* areaElementStyle = areaElement->computedStyle();
+ RenderStyle* areaElementStyle = areaElement.computedStyle();
unsigned short outlineWidth = areaElementStyle->outlineWidth();
if (!outlineWidth)
return;
@@ -456,7 +433,7 @@ void RenderImage::areaElementFocusChanged(HTMLAreaElement* areaElement)
repaintRect.moveBy(-absoluteContentBox().location());
repaintRect.inflate(outlineWidth);
- repaintRectangle(repaintRect);
+ invalidatePaintRectangle(repaintRect);
}
void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect)
@@ -469,13 +446,18 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect
if (!img || img->isNull())
return;
- HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? toHTMLImageElement(node()) : 0;
+ HTMLImageElement* imageElt = isHTMLImageElement(node()) ? toHTMLImageElement(node()) : 0;
CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
Image* image = m_imageResource->image().get();
- bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
+ InterpolationQuality interpolationQuality = chooseInterpolationQuality(context, image, image, alignedRect.size());
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(*this));
+ // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
InspectorInstrumentation::willPaintImage(this);
- context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
+ InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality();
+ context->setImageInterpolationQuality(interpolationQuality);
+ context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), alignedRect, compositeOperator, shouldRespectImageOrientation());
+ context->setImageInterpolationQuality(previousInterpolationQuality);
InspectorInstrumentation::didPaintImage(this);
}
@@ -517,7 +499,11 @@ bool RenderImage::computeBackgroundIsKnownToBeObscured()
{
if (!hasBackground())
return false;
- return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0);
+
+ LayoutRect paintedExtent;
+ if (!getBackgroundPaintedExtent(paintedExtent))
+ return false;
+ return foregroundIsKnownToBeOpaqueInRect(paintedExtent, 0);
}
LayoutUnit RenderImage::minimumReplacedHeight() const
@@ -527,7 +513,7 @@ LayoutUnit RenderImage::minimumReplacedHeight() const
HTMLMapElement* RenderImage::imageMap() const
{
- HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? toHTMLImageElement(node()) : 0;
+ HTMLImageElement* i = isHTMLImageElement(node()) ? toHTMLImageElement(node()) : 0;
return i ? i->treeScope().getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
}
@@ -560,35 +546,22 @@ void RenderImage::updateAltText()
if (!node())
return;
- if (node()->hasTagName(inputTag))
+ if (isHTMLInputElement(*node()))
m_altText = toHTMLInputElement(node())->altText();
- else if (node()->hasTagName(imgTag))
+ else if (isHTMLImageElement(*node()))
m_altText = toHTMLImageElement(node())->altText();
}
void RenderImage::layout()
{
- LayoutRectRecorder recorder(*this);
RenderReplaced::layout();
updateInnerContentRect();
}
-void RenderImage::didLayout(ResourceLoadPriorityOptimizer& optimizer)
-{
- RenderReplaced::didLayout(optimizer);
- updateImageLoadingPriority(optimizer);
-}
-
-void RenderImage::didScroll(ResourceLoadPriorityOptimizer& optimizer)
-{
- RenderReplaced::didScroll(optimizer);
- updateImageLoadingPriority(optimizer);
-}
-
-void RenderImage::updateImageLoadingPriority(ResourceLoadPriorityOptimizer& optimizer)
+bool RenderImage::updateImageLoadingPriorities()
{
if (!m_imageResource || !m_imageResource->cachedImage() || m_imageResource->cachedImage()->isLoaded())
- return;
+ return false;
LayoutRect viewBounds = viewRect();
LayoutRect objectBounds = absoluteContentBox();
@@ -604,20 +577,28 @@ void RenderImage::updateImageLoadingPriority(ResourceLoadPriorityOptimizer& opti
ResourceLoadPriorityOptimizer::VisibilityStatus status = isVisible ?
ResourceLoadPriorityOptimizer::Visible : ResourceLoadPriorityOptimizer::NotVisible;
- optimizer.notifyImageResourceVisibility(m_imageResource->cachedImage(), status);
+ LayoutRect screenArea;
+ if (!objectBounds.isEmpty()) {
+ screenArea = viewBounds;
+ screenArea.intersect(objectBounds);
+ }
+
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->notifyImageResourceVisibility(m_imageResource->cachedImage(), status, screenArea);
+
+ return true;
}
-void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
{
- RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
// 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 = isOutOfFlowPositioned() ? container() : this->containingBlock();
if (containingBlock->isBox()) {
RenderBox* box = toRenderBox(containingBlock);
- intrinsicSize.setWidth(box->availableLogicalWidth());
- intrinsicSize.setHeight(box->availableLogicalHeight(IncludeMarginBorderPadding));
+ intrinsicSize.setWidth(box->availableLogicalWidth().toFloat());
+ intrinsicSize.setHeight(box->availableLogicalHeight(IncludeMarginBorderPadding).toFloat());
}
}
// Don't compute an intrinsic ratio to preserve historical WebKit behavior if we're painting alt text and/or a broken image.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImage.h b/chromium/third_party/WebKit/Source/core/rendering/RenderImage.h
index d7e67f0c7e3..0313703b8c7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImage.h
@@ -67,32 +67,28 @@ public:
protected:
virtual bool needsPreferredWidthsRecalculation() const OVERRIDE FINAL;
virtual RenderBox* embeddedContentBox() const OVERRIDE FINAL;
- virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const OVERRIDE FINAL;
+ virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const OVERRIDE FINAL;
- virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE FINAL;
-
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
void paintIntoRect(GraphicsContext*, const LayoutRect&);
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
- virtual void layout();
- virtual void didLayout(ResourceLoadPriorityOptimizer&);
- virtual void didScroll(ResourceLoadPriorityOptimizer&);
- void updateImageLoadingPriority(ResourceLoadPriorityOptimizer&);
+ virtual void layout() OVERRIDE;
+ virtual bool updateImageLoadingPriorities() OVERRIDE FINAL;
- virtual void intrinsicSizeChanged()
+ virtual void intrinsicSizeChanged() OVERRIDE
{
if (m_imageResource)
imageChanged(m_imageResource->imagePtr());
}
private:
- virtual const char* renderName() const { return "RenderImage"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderImage"; }
- virtual bool isImage() const { return true; }
+ virtual bool isImage() const OVERRIDE { return true; }
virtual bool isRenderImage() const OVERRIDE FINAL { return true; }
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const OVERRIDE FINAL;
virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE FINAL;
@@ -105,8 +101,8 @@ private:
virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE FINAL;
IntSize imageSizeForError(ImageResource*) const;
- void imageDimensionsChanged(bool imageSizeChanged, const IntRect* = 0);
- bool updateIntrinsicSizeIfNeeded(const LayoutSize&, bool imageSizeChanged);
+ void repaintOrMarkForLayout(bool imageSizeChanged, const IntRect* = 0);
+ void updateIntrinsicSizeIfNeeded(const LayoutSize&);
// Update the size of the image to be rendered. Object-fit may cause this to be different from the CSS box's content rect.
void updateInnerContentRect();
@@ -115,7 +111,6 @@ private:
// Text to display as long as the image isn't available.
String m_altText;
OwnPtr<RenderImageResource> m_imageResource;
- bool m_needsToSetSizeForAltText;
bool m_didIncrementVisuallyNonEmptyPixelCount;
bool m_isGeneratedContent;
float m_imageDevicePixelRatio;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.cpp
index 12ab7231776..79fd0804e73 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.cpp
@@ -87,7 +87,7 @@ void RenderImageResource::resetAnimation()
image()->resetAnimation();
if (!m_renderer->needsLayout())
- m_renderer->repaint();
+ m_renderer->paintInvalidationForWholeRenderer();
}
void RenderImageResource::setContainerSizeForRenderer(const IntSize& imageContainerSize)
@@ -97,11 +97,6 @@ void RenderImageResource::setContainerSizeForRenderer(const IntSize& imageContai
m_cachedImage->setContainerSizeForRenderer(m_renderer, imageContainerSize, m_renderer->style()->effectiveZoom());
}
-Image* RenderImageResource::nullImage()
-{
- return Image::nullImage();
-}
-
LayoutSize RenderImageResource::getImageSize(float multiplier, ImageResource::SizeType type) const
{
if (!m_cachedImage)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.h b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.h
index cae42e2eb03..2850d72ba5b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResource.h
@@ -29,8 +29,6 @@
#include "core/fetch/ImageResource.h"
#include "core/fetch/ResourcePtr.h"
#include "core/rendering/style/StyleImage.h"
-#include "platform/geometry/LayoutSize.h"
-#include "platform/graphics/Image.h"
namespace WebCore {
@@ -55,7 +53,10 @@ public:
void resetAnimation();
- virtual PassRefPtr<Image> image(int /* width */ = 0, int /* height */ = 0) const { return m_cachedImage ? m_cachedImage->imageForRenderer(m_renderer) : nullImage(); }
+ virtual PassRefPtr<Image> image(int /* width */ = 0, int /* height */ = 0) const
+ {
+ return m_cachedImage ? m_cachedImage->imageForRenderer(m_renderer) : Image::nullImage();
+ }
virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); }
virtual void setContainerSizeForRenderer(const IntSize&);
@@ -74,7 +75,6 @@ protected:
ResourcePtr<ImageResource> m_cachedImage;
private:
- static Image* nullImage();
LayoutSize getImageSize(float multiplier, ImageResource::SizeType) const;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.cpp
index 5e0fff78319..eded16a0240 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.cpp
@@ -65,7 +65,7 @@ PassRefPtr<Image> RenderImageResourceStyleImage::image(int width, int height) co
{
// Generated content may trigger calls to image() while we're still pending, don't assert but gracefully exit.
if (m_styleImage->isPendingImage())
- return 0;
+ return nullptr;
return m_styleImage->image(m_renderer, IntSize(width, height));
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.h b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.h
index 6844e2a5811..098cc634acb 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImageResourceStyleImage.h
@@ -34,7 +34,7 @@ namespace WebCore {
class RenderObject;
-class RenderImageResourceStyleImage : public RenderImageResource {
+class RenderImageResourceStyleImage FINAL : public RenderImageResource {
public:
virtual ~RenderImageResourceStyleImage();
@@ -42,22 +42,22 @@ public:
{
return adoptPtr(new RenderImageResourceStyleImage(styleImage));
}
- virtual void initialize(RenderObject*);
- virtual void shutdown();
+ virtual void initialize(RenderObject*) OVERRIDE;
+ virtual void shutdown() OVERRIDE;
- virtual bool hasImage() const { return true; }
- virtual PassRefPtr<Image> image(int width = 0, int height = 0) const;
- virtual bool errorOccurred() const { return m_styleImage->errorOccurred(); }
+ virtual bool hasImage() const OVERRIDE { return true; }
+ virtual PassRefPtr<Image> image(int width = 0, int height = 0) const OVERRIDE;
+ virtual bool errorOccurred() const OVERRIDE { return m_styleImage->errorOccurred(); }
- virtual void setContainerSizeForRenderer(const IntSize&);
- virtual bool usesImageContainerSize() const { return m_styleImage->usesImageContainerSize(); }
- virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); }
- virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); }
+ virtual void setContainerSizeForRenderer(const IntSize&) OVERRIDE;
+ virtual bool usesImageContainerSize() const OVERRIDE { return m_styleImage->usesImageContainerSize(); }
+ virtual bool imageHasRelativeWidth() const OVERRIDE { return m_styleImage->imageHasRelativeWidth(); }
+ virtual bool imageHasRelativeHeight() const OVERRIDE { return m_styleImage->imageHasRelativeHeight(); }
virtual LayoutSize imageSize(float multiplier) const OVERRIDE { return m_styleImage->imageSize(m_renderer, multiplier); }
virtual LayoutSize intrinsicSize(float multiplier) const OVERRIDE { return m_styleImage->imageSize(m_renderer, multiplier); }
- virtual WrappedImagePtr imagePtr() const { return m_styleImage->data(); }
+ virtual WrappedImagePtr imagePtr() const OVERRIDE { return m_styleImage->data(); }
private:
RenderImageResourceStyleImage(StyleImage*);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderInline.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderInline.cpp
index bd82486d441..80664b5e3b1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderInline.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderInline.cpp
@@ -29,7 +29,6 @@
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/InlineTextBox.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderBlock.h"
#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderFullScreen.h"
@@ -62,7 +61,7 @@ RenderInline* RenderInline::createAnonymous(Document* document)
void RenderInline::willBeDestroyed()
{
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
// Make sure we do not retain "this" in the continuation outline table map of our containing blocks.
if (parent() && style()->visibility() == VISIBLE && hasOutline()) {
bool containingBlockPaintsContinuationOutline = continuation() || isInlineElementContinuation();
@@ -194,7 +193,7 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || newStyle->hasPadding() || newStyle->hasMargin() || hasOutline();
if (oldStyle && alwaysCreateLineBoxes) {
dirtyLineBoxes(false);
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
}
m_alwaysCreateLineBoxes = alwaysCreateLineBoxes;
}
@@ -210,14 +209,12 @@ void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
RenderStyle* parentStyle = parent()->style();
RenderInline* parentRenderInline = parent()->isRenderInline() ? toRenderInline(parent()) : 0;
bool checkFonts = document().inNoQuirksMode();
- RenderFlowThread* flowThread = flowThreadContainingBlock();
bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes())
|| (parentRenderInline && parentStyle->verticalAlign() != BASELINE)
|| style()->verticalAlign() != BASELINE
|| style()->textEmphasisMark() != TextEmphasisMarkNone
|| (checkFonts && (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(style()->font().fontMetrics())
- || parentStyle->lineHeight() != style()->lineHeight()))
- || (flowThread && flowThread->hasRegionsWithStyling());
+ || parentStyle->lineHeight() != style()->lineHeight()));
if (!alwaysCreateLineBoxes && checkFonts && document().styleEngine()->usesFirstLineRules()) {
// Have to check the first line style as well.
@@ -283,7 +280,7 @@ RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild
RenderBoxModelObject* last = this;
while (curr) {
if (beforeChild && beforeChild->parent() == curr) {
- if (curr->firstChild() == beforeChild)
+ if (curr->slowFirstChild() == beforeChild)
return last;
return curr;
}
@@ -293,7 +290,7 @@ RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild
curr = nextContinuation(curr);
}
- if (!beforeChild && !last->firstChild())
+ if (!beforeChild && !last->slowFirstChild())
return nextToLast;
return last;
}
@@ -327,7 +324,7 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb
RenderBoxModelObject::addChild(newChild, beforeChild);
- newChild->setNeedsLayoutAndPrefWidthsRecalc();
+ newChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
RenderInline* RenderInline::clone() const
@@ -351,7 +348,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
// that renderer is wrapped in a RenderFullScreen, so |this| is not its
// parent. Since the splitting logic expects |this| to be the parent, set
// |beforeChild| to be the RenderFullScreen.
- if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(&document())) {
+ if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document())) {
const Element* fullScreenElement = fullscreen->webkitCurrentFullScreenElement();
if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
beforeChild = fullscreen->fullScreenRenderer();
@@ -364,7 +361,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
RenderObject* tmp = o;
o = tmp->nextSibling();
cloneInline->addChildIgnoringContinuation(children()->removeChildNode(this, tmp), 0);
- tmp->setNeedsLayoutAndPrefWidthsRecalc();
+ tmp->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
// Hook |clone| up as the continuation of the middle block.
@@ -405,7 +402,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
RenderObject* tmp = o;
o = tmp->nextSibling();
cloneInline->addChildIgnoringContinuation(inlineCurr->children()->removeChildNode(curr, tmp), 0);
- tmp->setNeedsLayoutAndPrefWidthsRecalc();
+ tmp->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
@@ -466,7 +463,7 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
RenderObject* no = o;
o = no->nextSibling();
pre->children()->appendChildNode(pre, block->children()->removeChildNode(block, no));
- no->setNeedsLayoutAndPrefWidthsRecalc();
+ no->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
@@ -481,9 +478,9 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
// Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
// get deleted properly. Because objects moves from the pre block into the post block, we want to
// make new line boxes instead of leaving the old line boxes around.
- pre->setNeedsLayoutAndPrefWidthsRecalc();
- block->setNeedsLayoutAndPrefWidthsRecalc();
- post->setNeedsLayoutAndPrefWidthsRecalc();
+ pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
@@ -560,13 +557,13 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
if (curr->isBox()) {
RenderBox* currBox = toRenderBox(curr);
if (currBox->inlineBoxWrapper()) {
- RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
- int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
- int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root();
+ int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
if (isHorizontal)
- yield(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginWidth(), logicalHeight));
+ yield(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, (currBox->width() + currBox->marginWidth()).toFloat(), logicalHeight));
else
- yield(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginHeight()));
+ yield(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, (currBox->height() + currBox->marginHeight()).toFloat()));
}
} else if (curr->isRenderInline()) {
// If the child doesn't need line boxes either, then we can recur.
@@ -575,9 +572,9 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
currInline->generateCulledLineBoxRects(yield, container);
else {
for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
- RootInlineBox* rootBox = childLine->root();
- int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
- int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ RootInlineBox& rootBox = childLine->root();
+ int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
if (isHorizontal)
yield(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
logicalTop,
@@ -593,9 +590,9 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
} else if (curr->isText()) {
RenderText* currText = toRenderText(curr);
for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
- RootInlineBox* rootBox = childText->root();
- int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
- int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ RootInlineBox& rootBox = childText->root();
+ int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
if (isHorizontal)
yield(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
else
@@ -696,8 +693,6 @@ static LayoutUnit computeMargin(const RenderInline* renderer, const Length& marg
return margin.value();
if (margin.isPercent())
return minimumValueForLength(margin, max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
- if (margin.isViewportPercentage())
- return valueForLength(margin, 0, renderer->view());
return 0;
}
@@ -817,7 +812,7 @@ PositionWithAffinity RenderInline::positionForPoint(const LayoutPoint& point)
RenderBoxModelObject* c = continuation();
while (c) {
RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
- if (c->isInline() || c->firstChild())
+ if (c->isInline() || c->slowFirstChild())
return c->positionForPoint(parentBlockPoint - contBlock->locationOffset());
c = toRenderBlock(c)->inlineElementContinuation();
}
@@ -984,12 +979,12 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
}
- RootInlineBox* firstRootBox = firstLineBox()->root();
- RootInlineBox* lastRootBox = lastLineBox()->root();
+ RootInlineBox& firstRootBox = firstLineBox()->root();
+ RootInlineBox& lastRootBox = lastLineBox()->root();
- LayoutUnit logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
+ LayoutUnit logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox.lineTop());
LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
- LayoutUnit logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom()) - logicalTop;
+ LayoutUnit logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom()) - logicalTop;
LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
if (!style()->isHorizontalWritingMode())
@@ -997,9 +992,9 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
return rect;
}
-LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- ASSERT(!view() || !view()->layoutStateEnabled() || LayoutRectRecorder::shouldRecordLayoutRects());
+ ASSERT(!view() || !view()->layoutStateCachedOffsetsEnabled());
if (!firstLineBoxIncludingCulling() && !continuation())
return LayoutRect();
@@ -1012,7 +1007,7 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObj
RenderBlock* cb = containingBlock();
for (const RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb;
inlineFlow = inlineFlow->parent()) {
- if (inlineFlow == repaintContainer) {
+ if (inlineFlow == paintInvalidationContainer) {
hitRepaintContainer = true;
break;
}
@@ -1032,51 +1027,51 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObj
if (cb->hasOverflowClip())
cb->applyCachedClipAndScrollOffsetForRepaint(repaintRect);
- cb->computeRectForRepaint(repaintContainer, repaintRect);
+ cb->mapRectToPaintInvalidationBacking(paintInvalidationContainer, repaintRect);
if (outlineSize) {
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
if (!curr->isText())
- repaintRect.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineSize));
+ repaintRect.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize));
}
if (continuation() && !continuation()->isInline() && continuation()->parent())
- repaintRect.unite(continuation()->rectWithOutlineForRepaint(repaintContainer, outlineSize));
+ repaintRect.unite(continuation()->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize));
}
return repaintRect;
}
-LayoutRect RenderInline::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
+LayoutRect RenderInline::rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth) const
{
- LayoutRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+ LayoutRect r(RenderBoxModelObject::rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineWidth));
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
if (!curr->isText())
- r.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+ r.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineWidth));
}
return r;
}
-void RenderInline::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+void RenderInline::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, bool fixed) const
{
if (RenderView* v = view()) {
// LayoutState is only valid for root-relative repainting
- if (v->layoutStateEnabled() && !repaintContainer) {
+ if (v->canMapUsingLayoutStateForContainer(paintInvalidationContainer)) {
LayoutState* layoutState = v->layoutState();
if (style()->hasInFlowPosition() && layer())
rect.move(layer()->offsetForInFlowPosition());
- rect.move(layoutState->m_paintOffset);
- if (layoutState->m_clipped)
- rect.intersect(layoutState->m_clipRect);
+ rect.move(layoutState->paintOffset());
+ if (layoutState->isClipped())
+ rect.intersect(layoutState->clipRect());
return;
}
}
- if (repaintContainer == this)
+ if (paintInvalidationContainer == this)
return;
bool containerSkipped;
- RenderObject* o = container(repaintContainer, &containerSkipped);
+ RenderObject* o = container(paintInvalidationContainer, &containerSkipped);
if (!o)
return;
@@ -1111,16 +1106,16 @@ void RenderInline::computeRectForRepaint(const RenderLayerModelObject* repaintCo
}
if (containerSkipped) {
- // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
- LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+ // If the paintInvalidationContainer is below o, then we need to map the rect into paintInvalidationContainer's coordinates.
+ LayoutSize containerOffset = paintInvalidationContainer->offsetFromAncestorContainer(o);
rect.move(-containerOffset);
return;
}
- o->computeRectForRepaint(repaintContainer, rect, fixed);
+ o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, fixed);
}
-LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+LayoutSize RenderInline::offsetFromContainer(const RenderObject* container, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(container == this->container());
@@ -1128,7 +1123,7 @@ LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const Layo
if (isInFlowPositioned())
offset += offsetForInFlowPosition();
- container->adjustForColumns(offset, point);
+ offset += container->columnOffset(point);
if (container->hasOverflowClip())
offset -= toRenderBox(container)->scrolledContentOffset();
@@ -1148,9 +1143,9 @@ void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintCont
return;
if (RenderView *v = view()) {
- if (v->layoutStateEnabled() && !repaintContainer) {
+ if (v->canMapUsingLayoutStateForContainer(repaintContainer)) {
LayoutState* layoutState = v->layoutState();
- LayoutSize offset = layoutState->m_paintOffset;
+ LayoutSize offset = layoutState->paintOffset();
if (style()->hasInFlowPosition() && layer())
offset += layer()->offsetForInFlowPosition();
transformState.move(offset);
@@ -1250,16 +1245,16 @@ void RenderInline::dirtyLineBoxes(bool fullLayout)
if (curr->isBox() && !curr->needsLayout()) {
RenderBox* currBox = toRenderBox(curr);
if (currBox->inlineBoxWrapper())
- currBox->inlineBoxWrapper()->root()->markDirty();
+ currBox->inlineBoxWrapper()->root().markDirty();
} else if (!curr->selfNeedsLayout()) {
if (curr->isRenderInline()) {
RenderInline* currInline = toRenderInline(curr);
for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox())
- childLine->root()->markDirty();
+ childLine->root().markDirty();
} else if (curr->isText()) {
RenderText* currText = toRenderText(curr);
for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox())
- childText->root()->markDirty();
+ childText->root().markDirty();
}
}
}
@@ -1274,7 +1269,7 @@ void RenderInline::deleteLineBoxTree()
InlineFlowBox* RenderInline::createInlineFlowBox()
{
- return new InlineFlowBox(this);
+ return new InlineFlowBox(*this);
}
InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
@@ -1290,10 +1285,10 @@ LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*directio
if (firstLine && document().styleEngine()->usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
if (s != style())
- return s->computedLineHeight(view());
+ return s->computedLineHeight();
}
- return style()->computedLineHeight(view());
+ return style()->computedLineHeight();
}
int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
@@ -1303,7 +1298,7 @@ int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, Li
return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
}
-LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox* child) const
+LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox& child) const
{
// FIXME: This function isn't right with mixed writing modes.
@@ -1326,18 +1321,18 @@ LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox* child)
blockPosition = layer()->staticBlockPosition();
}
- if (!child->style()->hasStaticInlinePosition(style()->isHorizontalWritingMode()))
+ if (!child.style()->hasStaticInlinePosition(style()->isHorizontalWritingMode()))
logicalOffset.setWidth(inlinePosition);
// This is not terribly intuitive, but we have to match other browsers. Despite being a block display type inside
// an inline, we still keep our x locked to the left of the relative positioned inline. Arguably the correct
// behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
// do.
- else if (!child->style()->isOriginalDisplayInlineType())
+ else if (!child.style()->isOriginalDisplayInlineType())
// Avoid adding in the left border/padding of the containing block twice. Subtract it out.
- logicalOffset.setWidth(inlinePosition - child->containingBlock()->borderAndPaddingLogicalLeft());
+ logicalOffset.setWidth(inlinePosition - child.containingBlock()->borderAndPaddingLogicalLeft());
- if (!child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
+ if (!child.style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
logicalOffset.setHeight(blockPosition);
return style()->isHorizontalWritingMode() ? logicalOffset : logicalOffset.transposedSize();
@@ -1349,7 +1344,7 @@ void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
return;
// FIXME: We can do better.
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderInline::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
@@ -1357,19 +1352,12 @@ void RenderInline::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&
AbsoluteRectsGeneratorContext context(rects, additionalOffset);
generateLineBoxRects(context);
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText() && !curr->isListMarker()) {
- FloatPoint pos(additionalOffset);
- // FIXME: This doesn't work correctly with transforms.
- if (curr->hasLayer())
- pos = curr->localToContainerPoint(FloatPoint(), paintContainer);
- else if (curr->isBox())
- pos.move(toRenderBox(curr)->locationOffset());
- curr->addFocusRingRects(rects, flooredIntPoint(pos), paintContainer);
- }
- }
+ addChildFocusRingRects(rects, additionalOffset, paintContainer);
if (continuation()) {
+ // If the continuation doesn't paint into the same container, let its repaint container handle it.
+ if (paintContainer != continuation()->containerForPaintInvalidation())
+ return;
if (continuation()->isInline())
continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + continuation()->containingBlock()->location() - containingBlock()->location()), paintContainer);
else
@@ -1428,9 +1416,9 @@ void RenderInline::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOf
rects.append(LayoutRect());
for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- RootInlineBox* root = curr->root();
- LayoutUnit top = max<LayoutUnit>(root->lineTop(), curr->logicalTop());
- LayoutUnit bottom = min<LayoutUnit>(root->lineBottom(), curr->logicalBottom());
+ RootInlineBox& root = curr->root();
+ LayoutUnit top = max<LayoutUnit>(root.lineTop(), curr->logicalTop());
+ LayoutUnit bottom = min<LayoutUnit>(root.lineBottom(), curr->logicalBottom());
rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
}
rects.append(LayoutRect());
@@ -1465,6 +1453,8 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L
LayoutSize(thisline.width() + offset, thisline.height() + offset));
IntRect pixelSnappedBox = pixelSnappedIntRect(box);
+ if (pixelSnappedBox.width() < 0 || pixelSnappedBox.height() < 0)
+ return;
IntRect pixelSnappedLastLine = pixelSnappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0);
IntRect pixelSnappedNextLine = pixelSnappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderInline.h b/chromium/third_party/WebKit/Source/core/rendering/RenderInline.h
index c69f0258daa..c2710ab5143 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderInline.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderInline.h
@@ -23,14 +23,13 @@
#ifndef RenderInline_h
#define RenderInline_h
+#include "core/animation/ActiveAnimations.h"
#include "core/rendering/InlineFlowBox.h"
#include "core/rendering/RenderBoxModelObject.h"
#include "core/rendering/RenderLineBoxList.h"
namespace WebCore {
-class Position;
-
class RenderInline : public RenderBoxModelObject {
public:
explicit RenderInline(Element*);
@@ -40,7 +39,11 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+ // If you have a RenderInline, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
Element* node() const { return toElement(RenderBoxModelObject::node()); }
@@ -54,9 +57,9 @@ public:
virtual LayoutUnit marginEnd(const RenderStyle* otherStyle = 0) const OVERRIDE FINAL;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const OVERRIDE FINAL;
+ virtual LayoutSize offsetFromContainer(const RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const OVERRIDE FINAL;
IntRect linesBoundingBox() const;
LayoutRect linesVisualOverflowBoundingBox() const;
@@ -79,7 +82,7 @@ public:
virtual void updateDragState(bool dragOn) OVERRIDE FINAL;
- LayoutSize offsetForInFlowPositionedInline(const RenderBox* child) const;
+ LayoutSize offsetForInFlowPositionedInline(const RenderBox& child) const;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE FINAL;
void paintOutline(PaintInfo&, const LayoutPoint&);
@@ -96,7 +99,7 @@ public:
bool hitTestCulledInline(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
protected:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
@@ -108,7 +111,7 @@ private:
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual const char* renderName() const;
+ virtual const char* renderName() const OVERRIDE;
virtual bool isRenderInline() const OVERRIDE FINAL { return true; }
@@ -135,16 +138,16 @@ private:
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
- virtual bool requiresLayer() const { return isInFlowPositioned() || createsGroup() || hasClipPath(); }
+ virtual LayerType layerTypeRequired() const OVERRIDE { return isInFlowPositioned() || createsGroup() || hasClipPath() || style()->shouldCompositeForCurrentAnimations() ? NormalLayer : NoLayer; }
virtual LayoutUnit offsetLeft() const OVERRIDE FINAL;
virtual LayoutUnit offsetTop() const OVERRIDE FINAL;
virtual LayoutUnit offsetWidth() const OVERRIDE FINAL { return linesBoundingBox().width(); }
virtual LayoutUnit offsetHeight() const OVERRIDE FINAL { return linesBoundingBox().height(); }
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL;
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed) const OVERRIDE FINAL;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL;
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed) const OVERRIDE FINAL;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.cpp
deleted file mode 100644
index 85134417040..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2010 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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(INPUT_SPEECH)
-#include "core/rendering/RenderInputSpeech.h"
-
-#include "core/html/shadow/TextControlInnerElements.h"
-#include "core/rendering/PaintInfo.h"
-#include "core/rendering/RenderBox.h"
-#include "platform/graphics/GraphicsContext.h"
-
-namespace WebCore {
-
-static const float defaultControlFontPixelSize = 13;
-static const float defaultSpeechButtonSize = 16;
-static const float minSpeechButtonSize = 8;
-static const float maxSpeechButtonSize = 40;
-
-void RenderInputSpeech::adjustInputFieldSpeechButtonStyle(RenderStyle* style, Element*)
-{
- // Scale the button size based on the font size.
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int speechButtonSize = lroundf(std::min(std::max(minSpeechButtonSize, defaultSpeechButtonSize * fontScale), maxSpeechButtonSize));
- style->setWidth(Length(speechButtonSize, Fixed));
- style->setHeight(Length(speechButtonSize, Fixed));
-}
-
-bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
-{
- Element* element = object->node()->isElementNode() ? toElement(object->node()) : 0;
- if (!element || !element->isInputFieldSpeechButtonElement())
- return false;
-
- // Get the renderer of <input> element.
- Node* input = object->node()->shadowHost();
- if (!input->renderer()->isBox())
- return false;
- RenderBox* inputRenderBox = toRenderBox(input->renderer());
- LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
-
- // Make sure the scaled button stays square and will fit in its parent's box.
- 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.
- 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.
- LayoutSize offsetFromInputRenderer = -(object->offsetFromAncestorContainer(inputRenderBox));
- // Move the rect into partRenderer's coords.
- buttonRect.move(offsetFromInputRenderer);
- // Account for the local drawing offset.
- buttonRect.moveBy(rect.location());
-
- DEFINE_STATIC_REF(Image, imageStateNormal, (Image::loadPlatformResource("inputSpeech")));
- DEFINE_STATIC_REF(Image, imageStateRecording, (Image::loadPlatformResource("inputSpeechRecording")));
- DEFINE_STATIC_REF(Image, imageStateWaiting, (Image::loadPlatformResource("inputSpeechWaiting")));
-
- InputFieldSpeechButtonElement* speechButton = toInputFieldSpeechButtonElement(element);
- Image* image = imageStateNormal;
- if (speechButton->state() == InputFieldSpeechButtonElement::Recording)
- image = imageStateRecording;
- else if (speechButton->state() == InputFieldSpeechButtonElement::Recognizing)
- image = imageStateWaiting;
- paintInfo.context->drawImage(image, pixelSnappedIntRect(buttonRect));
-
- return false;
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(INPUT_SPEECH)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.h b/chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.h
deleted file mode 100644
index e1d8c6e1ee8..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderInputSpeech.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 RenderInputSpeech_h
-#define RenderInputSpeech_h
-
-#if ENABLE(INPUT_SPEECH)
-
-namespace WebCore {
-
-struct PaintInfo;
-
-class Element;
-class IntRect;
-class RenderObject;
-class RenderStyle;
-class StyleResolver;
-
-class RenderInputSpeech {
-public:
- static void adjustInputFieldSpeechButtonStyle(RenderStyle*, Element*);
- static bool paintInputFieldSpeechButton(RenderObject*, const PaintInfo&, const IntRect&);
-};
-
-} // namespace WebCore
-
-#endif
-#endif // RenderInputSpeech_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.cpp
index c3b8403215f..6b7ba1c904f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.cpp
@@ -44,23 +44,20 @@
#include "config.h"
#include "core/rendering/RenderLayer.h"
-#include "CSSPropertyNames.h"
-#include "HTMLNames.h"
-#include "RuntimeEnabledFeatures.h"
-#include "SVGNames.h"
+#include "core/CSSPropertyNames.h"
+#include "core/HTMLNames.h"
#include "core/animation/ActiveAnimations.h"
#include "core/css/PseudoStyleRequest.h"
#include "core/dom/Document.h"
#include "core/dom/shadow/ShadowRoot.h"
-#include "core/html/HTMLFrameElement.h"
-#include "core/frame/Frame.h"
+#include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h"
#include "core/frame/FrameView.h"
-#include "core/page/Page.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
-#include "core/frame/animation/AnimationController.h"
+#include "core/html/HTMLFrameElement.h"
+#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/rendering/ColumnInfo.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/FilterEffectRenderer.h"
#include "core/rendering/HitTestRequest.h"
#include "core/rendering/HitTestResult.h"
@@ -68,26 +65,25 @@
#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderInline.h"
-#include "core/rendering/RenderLayerCompositor.h"
#include "core/rendering/RenderReplica.h"
#include "core/rendering/RenderScrollbar.h"
#include "core/rendering/RenderScrollbarPart.h"
#include "core/rendering/RenderTreeAsText.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "core/rendering/svg/ReferenceFilterBuilder.h"
#include "core/rendering/svg/RenderSVGResourceClipper.h"
#include "platform/LengthFunctions.h"
#include "platform/Partitions.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/TraceEvent.h"
#include "platform/geometry/FloatPoint3D.h"
#include "platform/geometry/FloatRect.h"
+#include "platform/geometry/TransformState.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/graphics/filters/ReferenceFilter.h"
#include "platform/graphics/filters/SourceGraphic.h"
-#include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
-#include "platform/graphics/filters/custom/CustomFilterOperation.h"
-#include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
-#include "platform/graphics/filters/custom/ValidatedCustomFilterOperation.h"
#include "platform/transforms/ScaleTransformOperation.h"
#include "platform/transforms/TransformationMatrix.h"
#include "platform/transforms/TranslateTransformOperation.h"
@@ -99,19 +95,21 @@ using namespace std;
namespace WebCore {
+namespace {
+
+static CompositingQueryMode gCompositingQueryMode =
+ CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;
+
+} // namespace
+
using namespace HTMLNames;
-RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
- : m_hasSelfPaintingLayerDescendant(false)
+RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type)
+ : m_layerType(type)
+ , m_hasSelfPaintingLayerDescendant(false)
, m_hasSelfPaintingLayerDescendantDirty(false)
- , m_hasOutOfFlowPositionedDescendant(false)
- , m_hasOutOfFlowPositionedDescendantDirty(true)
- , m_hasUnclippedDescendant(false)
- , m_isUnclippedDescendant(false)
, m_isRootLayer(renderer->isRenderView())
, m_usedTransparency(false)
- , m_childLayerHasBlendMode(false)
- , m_childLayerHasBlendModeStatusDirty(false)
, m_visibleContentStatusDirty(true)
, m_hasVisibleContent(false)
, m_visibleDescendantStatusDirty(false)
@@ -123,7 +121,13 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
, m_containsDirtyOverlayScrollbars(false)
, m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
, m_hasFilterInfo(false)
- , m_blendMode(blink::WebBlendModeNormal)
+ , m_needsCompositingInputsUpdate(true)
+ , m_childNeedsCompositingInputsUpdate(true)
+ , m_hasCompositingDescendant(false)
+ , m_hasNonCompositedChild(false)
+ , m_shouldIsolateCompositedDescendants(false)
+ , m_lostGroupedMapping(false)
+ , m_viewportConstrainedNotCompositedReason(NoNotCompositedReason)
, m_renderer(renderer)
, m_parent(0)
, m_previous(0)
@@ -133,15 +137,18 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
, m_staticInlinePosition(0)
, m_staticBlockPosition(0)
, m_enclosingPaginationLayer(0)
+ , m_styleDeterminedCompositingReasons(CompositingReasonNone)
+ , m_compositingReasons(CompositingReasonNone)
, m_groupedMapping(0)
- , m_repainter(renderer)
- , m_clipper(renderer)
+ , m_repainter(*renderer)
+ , m_clipper(*renderer)
+ , m_blendInfo(*renderer)
{
updateStackingNode();
m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
- if (!renderer->firstChild() && renderer->style()) {
+ if (!renderer->slowFirstChild() && renderer->style()) {
m_visibleContentStatusDirty = false;
m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
}
@@ -151,9 +158,6 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
RenderLayer::~RenderLayer()
{
- if (!m_renderer->documentBeingDestroyed())
- compositor()->removeOutOfFlowPositionedLayer(this);
-
if (renderer()->frame() && renderer()->frame()->page()) {
if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->page()->scrollingCoordinator())
scrollingCoordinator->willDestroyRenderLayer(this);
@@ -161,6 +165,12 @@ RenderLayer::~RenderLayer()
removeFilterInfoIfNeeded();
+ if (groupedMapping()) {
+ DisableCompositingQueryAsserts disabler;
+ groupedMapping()->removeRenderLayerFromSquashingGraphicsLayer(this);
+ setGroupedMapping(0);
+ }
+
// Child layers will be deleted by their corresponding render objects, so
// we don't need to delete them ourselves.
@@ -169,8 +179,10 @@ RenderLayer::~RenderLayer()
String RenderLayer::debugName() const
{
- if (isReflection())
+ if (isReflection()) {
+ ASSERT(m_reflectionInfo);
return m_reflectionInfo->debugName();
+ }
return renderer()->debugName();
}
@@ -183,28 +195,38 @@ RenderLayerCompositor* RenderLayer::compositor() const
void RenderLayer::contentChanged(ContentChangeType changeType)
{
- // This can get called when video becomes accelerated, so the layers may change.
- if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this))
- compositor()->setCompositingLayersNeedRebuild();
+ // updateLayerCompositingState will query compositingReasons for accelerated overflow scrolling.
+ // This is tripped by LayoutTests/compositing/content-changed-chicken-egg.html
+ DisableCompositingQueryAsserts disabler;
+
+ if (changeType == CanvasChanged)
+ compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
+
+ if (changeType == CanvasContextChanged) {
+ compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
+
+ // Although we're missing test coverage, we need to call
+ // GraphicsLayer::setContentsToPlatformLayer with the new platform
+ // layer for this canvas.
+ // See http://crbug.com/349195
+ if (hasCompositedLayerMapping())
+ compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+ }
if (m_compositedLayerMapping)
m_compositedLayerMapping->contentChanged(changeType);
}
-bool RenderLayer::canRender3DTransforms() const
-{
- return compositor()->canRender3DTransforms();
-}
-
bool RenderLayer::paintsWithFilters() const
{
if (!renderer()->hasFilter())
return false;
- if (compositingState() != PaintsIntoOwnBacking)
- return true;
-
- if (!m_compositedLayerMapping || !m_compositedLayerMapping->canCompositeFilters())
+ // https://code.google.com/p/chromium/issues/detail?id=343759
+ DisableCompositingQueryAsserts disabler;
+ if (!m_compositedLayerMapping
+ || compositingState() != PaintsIntoOwnBacking
+ || !m_compositedLayerMapping->canCompositeFilters())
return true;
return false;
@@ -218,57 +240,43 @@ bool RenderLayer::requiresFullLayerImageForFilters() const
return filter ? filter->hasFilterThatMovesPixels() : false;
}
-LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
+LayoutSize RenderLayer::subpixelAccumulation() const
{
- hasLayerOffset = true;
-
- if (!parent())
- return LayoutPoint();
-
- // This is similar to root() but we check if an ancestor layer would
- // prevent the optimization from working.
- const RenderLayer* rootLayer = 0;
- for (const RenderLayer* parentLayer = parent(); parentLayer; rootLayer = parentLayer, parentLayer = parentLayer->parent()) {
- hasLayerOffset = parentLayer->canUseConvertToLayerCoords();
- if (!hasLayerOffset)
- return LayoutPoint();
- }
- ASSERT(rootLayer == root());
+ return m_subpixelAccumulation;
+}
- LayoutPoint offset;
- parent()->convertToLayerCoords(rootLayer, offset);
- return offset;
+void RenderLayer::setSubpixelAccumulation(const LayoutSize& size)
+{
+ m_subpixelAccumulation = size;
}
void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags)
{
- RenderGeometryMap geometryMap(UseTransforms);
- if (this != rootLayer)
- geometryMap.pushMappingsToAncestor(parent(), 0);
- updateLayerPositions(&geometryMap, flags);
+ TRACE_EVENT0("blink_rendering", "RenderLayer::updateLayerPositionsAfterLayout");
+
+ // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues
+ // https://code.google.com/p/chromium/issues/detail?id=343756
+ DisableCompositingQueryAsserts disabler;
+ updateLayerPositionRecursive(flags);
}
-void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLayerPositionsFlags flags)
+void RenderLayer::updateLayerPositionRecursive(UpdateLayerPositionsFlags flags)
{
- updateLayerPosition(); // For relpositioned layers or non-positioned layers,
- // we need to keep in sync, since we may have shifted relative
- // to our parent layer.
- if (geometryMap)
- geometryMap->pushMappingsToAncestor(this, parent());
+ if (updateLayerPosition())
+ flags |= ForceMayNeedPaintInvalidation;
+
+ if (flags & ForceMayNeedPaintInvalidation)
+ m_renderer->setMayNeedPaintInvalidation(true);
// Clear our cached clip rect information.
m_clipper.clearClipRects();
if (hasOverflowControls()) {
- LayoutPoint offsetFromRoot;
- if (geometryMap)
- offsetFromRoot = LayoutPoint(geometryMap->absolutePoint(FloatPoint()));
- else {
- // FIXME: It looks suspicious to call convertToLayerCoords here
- // as canUseConvertToLayerCoords may be true for an ancestor layer.
- convertToLayerCoords(root(), offsetFromRoot);
- }
- scrollableArea()->positionOverflowControls(toIntSize(roundedIntPoint(offsetFromRoot)));
+ // FIXME: We should figure out the right time to position the overflow controls.
+ // This call appears to be necessary to pass some layout test that use EventSender,
+ // presumably because the normal time to position the controls is during paint. We
+ // probably shouldn't position the overflow controls during paint either...
+ scrollableArea()->positionOverflowControls(IntSize());
}
updateDescendantDependentFlags();
@@ -280,18 +288,13 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLay
m_enclosingPaginationLayer = 0;
}
- repainter().repaintAfterLayout(geometryMap, flags & CheckForRepaint);
+ repainter().repaintAfterLayout(flags & CheckForRepaint);
// Go ahead and update the reflection's position and size.
if (m_reflectionInfo)
m_reflectionInfo->reflection()->layout();
- // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
- bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
- if (hasCompositedLayerMapping())
- flags &= ~IsCompositingUpdateRoot;
-
- if (useRegionBasedColumns() && renderer()->isInFlowRenderFlowThread()) {
+ if (useRegionBasedColumns() && renderer()->isRenderFlowThread()) {
updatePagination();
flags |= UpdatePagination;
}
@@ -300,19 +303,15 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLay
flags |= UpdatePagination;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositions(geometryMap, flags);
+ child->updateLayerPositionRecursive(flags);
- if ((flags & UpdateCompositingLayers) && hasCompositedLayerMapping()) {
- CompositedLayerMapping::UpdateAfterLayoutFlags updateFlags = CompositedLayerMapping::CompositingChildrenOnly;
- if (flags & NeedsFullRepaintInBacking)
- updateFlags |= CompositedLayerMapping::NeedsFullRepaint;
- if (isUpdateRoot)
- updateFlags |= CompositedLayerMapping::IsUpdateRoot;
- compositedLayerMapping()->updateAfterLayout(updateFlags);
+ // FIXME: why isn't FrameView just calling RenderLayerCompositor::repaintCompositedLayers? Does it really impact
+ // performance?
+ if ((flags & NeedsFullRepaintInBacking) && hasCompositedLayerMapping() && !compositedLayerMapping()->paintsIntoCompositedAncestor()) {
+ compositedLayerMapping()->setContentsNeedDisplay();
+ // This code is called when the FrameView wants to repaint the entire frame. This includes squashing content.
+ compositedLayerMapping()->setSquashingContentsNeedDisplay();
}
-
- if (geometryMap)
- geometryMap->popMappingsToAncestor(parent());
}
void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
@@ -339,52 +338,6 @@ void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
}
}
-void RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant()
-{
- for (RenderLayer* layer = this; layer; layer = layer->parent()) {
- if (!layer->m_hasOutOfFlowPositionedDescendantDirty && layer->hasOutOfFlowPositionedDescendant())
- break;
-
- layer->setHasOutOfFlowPositionedDescendantDirty(false);
- layer->setHasOutOfFlowPositionedDescendant(true);
- }
-}
-
-void RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus()
-{
- for (RenderLayer* layer = this; layer; layer = layer->parent()) {
- layer->setHasOutOfFlowPositionedDescendantDirty(true);
-
- // We may or may not have an unclipped descendant. If we do, we'll reset
- // this to true the next time composited scrolling state is updated.
- layer->setHasUnclippedDescendant(false);
-
- // If we have reached an out of flow positioned layer, we know our parent should have an out-of-flow positioned descendant.
- // In this case, there is no need to dirty our ancestors further.
- if (layer->renderer()->isOutOfFlowPositioned()) {
- ASSERT(!parent() || parent()->m_hasOutOfFlowPositionedDescendantDirty || parent()->hasOutOfFlowPositionedDescendant());
- break;
- }
- }
-}
-
-bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const
-{
- const Settings* settings = renderer()->document().settings();
- return settings && settings->acceleratedCompositingForOverflowScrollEnabled();
-}
-
-// FIXME: This is a temporary flag and should be removed once accelerated
-// overflow scroll is ready (crbug.com/254111).
-bool RenderLayer::compositorDrivenAcceleratedScrollingEnabled() const
-{
- if (!acceleratedCompositingForOverflowScrollEnabled())
- return false;
-
- const Settings* settings = renderer()->document().settings();
- return settings && settings->compositorDrivenAcceleratedScrollingEnabled();
-}
-
bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
{
const EPosition position = renderer()->style()->position();
@@ -413,21 +366,28 @@ bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
const bool isRootFixedPos = position == FixedPosition && containingBlock->enclosingLayer() == rootLayer;
const bool otherIsRootFixedPos = otherPosition == FixedPosition && otherContainingBlock->enclosingLayer() == rootLayer;
+ // FIXME: some of these cases don't look quite right.
if (isRootFixedPos && otherIsRootFixedPos)
return false;
if (isRootFixedPos || otherIsRootFixedPos)
return true;
- if (containingBlock == otherContainingBlock)
+ if (containingBlock->enclosingLayer() == otherContainingBlock->enclosingLayer())
return false;
// Maintain a set of containing blocks between the first layer and its
// closest scrollable ancestor.
- HashSet<const RenderObject*> containingBlocks;
+ HashSet<const RenderLayer*> containingBlocks;
while (containingBlock) {
+ containingBlocks.add(containingBlock->enclosingLayer());
if (containingBlock->enclosingLayer()->scrollsOverflow())
break;
- containingBlocks.add(containingBlock);
+
+ if (containingBlock->enclosingLayer() == other) {
+ // This layer does not scroll with respect to the other layer if the other one does not scroll and this one is a child.
+ return false;
+ }
+
containingBlock = containingBlock->containingBlock();
}
@@ -435,7 +395,7 @@ bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
// it means both layers are contained within a single non-scrolling subtree.
// Hence, they will not scroll with respect to each other.
while (otherContainingBlock) {
- if (containingBlocks.contains(otherContainingBlock))
+ if (containingBlocks.contains(otherContainingBlock->enclosingLayer()))
return false;
if (otherContainingBlock->enclosingLayer()->scrollsOverflow())
break;
@@ -448,24 +408,17 @@ bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
void RenderLayer::updateLayerPositionsAfterDocumentScroll()
{
ASSERT(this == renderer()->view()->layer());
-
- RenderGeometryMap geometryMap(UseTransforms);
- updateLayerPositionsAfterScroll(&geometryMap);
+ updateLayerPositionsAfterScroll();
}
void RenderLayer::updateLayerPositionsAfterOverflowScroll()
{
- RenderGeometryMap geometryMap(UseTransforms);
- RenderView* view = renderer()->view();
- if (this != view->layer())
- geometryMap.pushMappingsToAncestor(parent(), 0);
-
// FIXME: why is it OK to not check the ancestors of this layer in order to
// initialize the HasSeenViewportConstrainedAncestor and HasSeenAncestorWithOverflowClip flags?
- updateLayerPositionsAfterScroll(&geometryMap, IsOverflowScroll);
+ updateLayerPositionsAfterScroll(IsOverflowScroll);
}
-void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap, UpdateLayerPositionsAfterScrollFlags flags)
+void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags flags)
{
// FIXME: This shouldn't be needed, but there are some corner cases where
// these flags are still dirty. Update so that the check below is valid.
@@ -477,14 +430,10 @@ void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap
if (subtreeIsInvisible())
return;
- bool positionChanged = updateLayerPosition();
- if (positionChanged)
+ if (updateLayerPosition())
flags |= HasChangedAncestor;
- if (geometryMap)
- geometryMap->pushMappingsToAncestor(this, parent());
-
- if (flags & HasChangedAncestor || flags & HasSeenViewportConstrainedAncestor || flags & IsOverflowScroll)
+ if ((flags & HasChangedAncestor) || (flags & HasSeenViewportConstrainedAncestor) || (flags & IsOverflowScroll))
m_clipper.clearClipRects();
if (renderer()->style()->hasViewportConstrainedPosition())
@@ -493,57 +442,42 @@ void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap
if (renderer()->hasOverflowClip())
flags |= HasSeenAncestorWithOverflowClip;
- if (flags & HasSeenViewportConstrainedAncestor
- || (flags & IsOverflowScroll && flags & HasSeenAncestorWithOverflowClip && !m_canSkipRepaintRectsUpdateOnScroll)) {
+ if ((flags & IsOverflowScroll) && (flags & HasSeenAncestorWithOverflowClip) && !m_canSkipRepaintRectsUpdateOnScroll) {
// FIXME: We could track the repaint container as we walk down the tree.
- repainter().computeRepaintRects(renderer()->containerForRepaint(), geometryMap);
+ repainter().computeRepaintRects();
} else {
// Check that RenderLayerRepainter's cached rects are correct.
// FIXME: re-enable these assertions when the issue with table cells is resolved: https://bugs.webkit.org/show_bug.cgi?id=103432
- // ASSERT(repainter().m_repaintRect == renderer()->clippedOverflowRectForRepaint(renderer()->containerForRepaint()));
- // ASSERT(repainter().m_outlineBox == renderer()->outlineBoundsForRepaint(renderer()->containerForRepaint(), geometryMap));
+ // ASSERT(repainter().m_repaintRect == renderer()->clippedOverflowRectForPaintInvalidation(renderer()->containerForPaintInvalidation()));
}
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositionsAfterScroll(geometryMap, flags);
+ child->updateLayerPositionsAfterScroll(flags);
// We don't update our reflection as scrolling is a translation which does not change the size()
// of an object, thus RenderReplica will still repaint itself properly as the layer position was
// updated above.
-
- if (geometryMap)
- geometryMap->popMappingsToAncestor(parent());
}
-bool RenderLayer::hasBlendMode() const
+void RenderLayer::updateTransformationMatrix()
{
- return RuntimeEnabledFeatures::cssCompositingEnabled() && renderer()->hasBlendMode();
+ if (m_transform) {
+ RenderBox* box = renderBox();
+ ASSERT(box);
+ m_transform->makeIdentity();
+ box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
+ makeMatrixRenderable(*m_transform, compositor()->hasAcceleratedCompositing());
+ }
}
-void RenderLayer::updateBlendMode()
+void RenderLayer::updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle)
{
- if (!RuntimeEnabledFeatures::cssCompositingEnabled())
+ if (oldStyle && newStyle->transformDataEquivalent(*oldStyle))
return;
- bool hadBlendMode = m_blendMode != blink::WebBlendModeNormal;
- blink::WebBlendMode newBlendMode = renderer()->style()->blendMode();
- if (newBlendMode != m_blendMode) {
- m_blendMode = newBlendMode;
-
- // Only update the flag if a blend mode is set or unset.
- if (parent() && (!hadBlendMode || !hasBlendMode()))
- parent()->dirtyAncestorChainBlendedDescendantStatus();
-
- if (hasCompositedLayerMapping())
- compositedLayerMapping()->setBlendMode(newBlendMode);
- }
-}
-
-void RenderLayer::updateTransform()
-{
// hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
// so check style too.
- bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
+ bool hasTransform = renderer()->hasTransform() && newStyle->hasTransform();
bool had3DTransform = has3DTransform();
bool hadTransform = m_transform;
@@ -555,40 +489,47 @@ void RenderLayer::updateTransform()
// Layers with transforms act as clip rects roots, so clear the cached clip rects here.
m_clipper.clearClipRectsIncludingDescendants();
+ } else if (hasTransform) {
+ m_clipper.clearClipRectsIncludingDescendants(AbsoluteClipRects);
}
- if (hasTransform) {
- RenderBox* box = renderBox();
- ASSERT(box);
- m_transform->makeIdentity();
- box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
- makeMatrixRenderable(*m_transform, canRender3DTransforms());
- }
+ updateTransformationMatrix();
if (had3DTransform != has3DTransform())
dirty3DTransformedDescendantStatus();
}
+static RenderLayer* enclosingLayerForContainingBlock(RenderLayer* layer)
+{
+ if (RenderObject* containingBlock = layer->renderer()->containingBlock())
+ return containingBlock->enclosingLayer();
+ return 0;
+}
+
+RenderLayer* RenderLayer::renderingContextRoot()
+{
+ RenderLayer* renderingContext = 0;
+
+ if (shouldPreserve3D())
+ renderingContext = this;
+
+ for (RenderLayer* current = enclosingLayerForContainingBlock(this); current && current->shouldPreserve3D(); current = enclosingLayerForContainingBlock(current))
+ renderingContext = current;
+
+ return renderingContext;
+}
+
TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
{
if (!m_transform)
return TransformationMatrix();
- // FIXME: handle this under web-animations
- if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled() && renderer()->style()->isRunningAcceleratedAnimation()) {
- TransformationMatrix currTransform;
- RefPtr<RenderStyle> style = renderer()->animation().getAnimatedStyleForRenderer(renderer());
- style->applyTransform(currTransform, renderBox()->pixelSnappedBorderBoxRect().size(), applyOrigin);
- makeMatrixRenderable(currTransform, canRender3DTransforms());
- return currTransform;
- }
-
// m_transform includes transform-origin, so we need to recompute the transform here.
if (applyOrigin == RenderStyle::ExcludeTransformOrigin) {
RenderBox* box = renderBox();
TransformationMatrix currTransform;
box->style()->applyTransform(currTransform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
- makeMatrixRenderable(currTransform, canRender3DTransforms());
+ makeMatrixRenderable(currTransform, compositor()->hasAcceleratedCompositing());
return currTransform;
}
@@ -609,6 +550,18 @@ TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavio
return *m_transform;
}
+RenderLayer* RenderLayer::enclosingOverflowClipLayer(IncludeSelfOrNot includeSelf) const
+{
+ const RenderLayer* layer = (includeSelf == IncludeSelf) ? this : parent();
+ while (layer) {
+ if (layer->renderer()->hasOverflowClip())
+ return const_cast<RenderLayer*>(layer);
+
+ layer = layer->parent();
+ }
+ return 0;
+}
+
static bool checkContainingBlockChainForPagination(RenderLayerModelObject* renderer, RenderBox* ancestorColumnsRenderer)
{
RenderView* view = renderer->view();
@@ -633,8 +586,7 @@ static bool checkContainingBlockChainForPagination(RenderLayerModelObject* rende
bool RenderLayer::useRegionBasedColumns() const
{
- const Settings* settings = renderer()->document().settings();
- return settings && settings->regionBasedColumnsEnabled();
+ return renderer()->document().regionBasedColumnsEnabled();
}
void RenderLayer::updatePagination()
@@ -654,7 +606,7 @@ void RenderLayer::updatePagination()
// layers). We track an enclosingPaginationLayer instead of using a simple bit, since we want to be able to get back
// to that layer easily.
bool regionBasedColumnsUsed = useRegionBasedColumns();
- if (regionBasedColumnsUsed && renderer()->isInFlowRenderFlowThread()) {
+ if (regionBasedColumnsUsed && renderer()->isRenderFlowThread()) {
m_enclosingPaginationLayer = this;
return;
}
@@ -694,17 +646,88 @@ void RenderLayer::updatePagination()
}
// If we're not normal flow, then we need to look for a multi-column object between us and our stacking container.
- RenderLayerStackingNode* ancestorStackingContainerNode = m_stackingNode->ancestorStackingContainerNode();
+ RenderLayerStackingNode* ancestorStackingContextNode = m_stackingNode->ancestorStackingContextNode();
for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
if (curr->renderer()->hasColumns()) {
m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
return;
}
- if (curr->stackingNode() == ancestorStackingContainerNode)
+ if (curr->stackingNode() == ancestorStackingContextNode)
return;
}
}
+static RenderLayerModelObject* getTransformedAncestor(const RenderLayerModelObject* repaintContainer)
+{
+ ASSERT(repaintContainer->layer()->enclosingTransformedAncestor());
+ ASSERT(repaintContainer->layer()->enclosingTransformedAncestor()->renderer());
+
+ // FIXME: this defensive code should not have to exist. None of these pointers should ever be 0. See crbug.com/370410.
+ RenderLayerModelObject* transformedAncestor = 0;
+ if (RenderLayer* ancestor = repaintContainer->layer()->enclosingTransformedAncestor())
+ transformedAncestor = ancestor->renderer();
+ return transformedAncestor;
+}
+
+LayoutPoint RenderLayer::positionFromPaintInvalidationContainer(const RenderObject* renderObject, const RenderLayerModelObject* repaintContainer)
+{
+ if (!repaintContainer || !repaintContainer->groupedMapping())
+ return renderObject->positionFromPaintInvalidationContainer(repaintContainer);
+
+ RenderLayerModelObject* transformedAncestor = getTransformedAncestor(repaintContainer);
+ if (!transformedAncestor)
+ return renderObject->positionFromPaintInvalidationContainer(repaintContainer);
+
+ // If the transformedAncestor is actually the RenderView, we might get
+ // confused and think that we can use LayoutState. Ideally, we'd made
+ // LayoutState work for all composited layers as well, but until then
+ // we need to disable LayoutState for squashed layers.
+ ForceHorriblySlowRectMapping slowRectMapping(*transformedAncestor);
+
+ LayoutPoint point = renderObject->positionFromPaintInvalidationContainer(transformedAncestor);
+ point.moveBy(-repaintContainer->groupedMapping()->squashingOffsetFromTransformedAncestor());
+ return point;
+}
+
+void RenderLayer::mapRectToRepaintBacking(const RenderObject* renderObject, const RenderLayerModelObject* repaintContainer, LayoutRect& rect)
+{
+ if (!repaintContainer->groupedMapping()) {
+ renderObject->mapRectToPaintInvalidationBacking(repaintContainer, rect);
+ return;
+ }
+
+ RenderLayerModelObject* transformedAncestor = getTransformedAncestor(repaintContainer);
+ if (!transformedAncestor)
+ return;
+
+ // If the transformedAncestor is actually the RenderView, we might get
+ // confused and think that we can use LayoutState. Ideally, we'd made
+ // LayoutState work for all composited layers as well, but until then
+ // we need to disable LayoutState for squashed layers.
+ ForceHorriblySlowRectMapping slowRectMapping(*transformedAncestor);
+
+ // This code adjusts the repaint rectangle to be in the space of the transformed ancestor of the grouped (i.e. squashed)
+ // layer. This is because all layers that squash together need to repaint w.r.t. a single container that is
+ // an ancestor of all of them, in order to properly take into account any local transforms etc.
+ // FIXME: remove this special-case code that works around the repainting code structure.
+ renderObject->mapRectToPaintInvalidationBacking(repaintContainer, rect);
+
+ // |repaintContainer| may have a local 2D transform on it, so take that into account when mapping into the space of the
+ // transformed ancestor.
+ rect = LayoutRect(repaintContainer->localToContainerQuad(FloatRect(rect), transformedAncestor).boundingBox());
+
+ rect.moveBy(-repaintContainer->groupedMapping()->squashingOffsetFromTransformedAncestor());
+}
+
+LayoutRect RenderLayer::computeRepaintRect(const RenderObject* renderObject, const RenderLayer* repaintContainer)
+{
+ if (!repaintContainer->groupedMapping())
+ return renderObject->computePaintInvalidationRect(repaintContainer->renderer());
+ LayoutRect rect = renderObject->clippedOverflowRectForPaintInvalidation(repaintContainer->renderer());
+ mapRectToRepaintBacking(repaintContainer->renderer(), repaintContainer->renderer(), rect);
+ return rect;
+}
+
void RenderLayer::setHasVisibleContent()
{
if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
@@ -712,19 +735,11 @@ void RenderLayer::setHasVisibleContent()
return;
}
- m_visibleContentStatusDirty = false;
m_hasVisibleContent = true;
- repainter().computeRepaintRects(renderer()->containerForRepaint());
- if (!m_stackingNode->isNormalFlowOnly()) {
- // We don't collect invisible layers in z-order lists if we are not in compositing mode.
- // As we became visible, we need to dirty our stacking containers ancestors to be properly
- // collected. FIXME: When compositing, we could skip this dirtying phase.
- for (RenderLayerStackingNode* sc = m_stackingNode->ancestorStackingContainerNode(); sc; sc = sc->ancestorStackingContainerNode()) {
- sc->dirtyZOrderLists();
- if (sc->layer()->hasVisibleContent())
- break;
- }
- }
+ m_visibleContentStatusDirty = false;
+
+ setNeedsCompositingInputsUpdate();
+ repainter().computeRepaintRects();
if (parent())
parent()->setAncestorChainHasVisibleDescendant();
@@ -758,135 +773,84 @@ void RenderLayer::setAncestorChainHasVisibleDescendant()
}
}
-void RenderLayer::dirtyAncestorChainBlendedDescendantStatus()
-{
- for (RenderLayer* layer = this; layer; layer = layer->parent()) {
- if (layer->m_childLayerHasBlendModeStatusDirty)
- break;
-
- layer->m_childLayerHasBlendModeStatusDirty = true;
-
- if (layer->stackingNode()->isStackingContext())
- break;
- }
-}
-
-void RenderLayer::setAncestorChainBlendedDescendant()
-{
- for (RenderLayer* layer = this; layer; layer = layer->parent()) {
- if (!layer->m_childLayerHasBlendModeStatusDirty && layer->childLayerHasBlendMode())
- break;
-
- layer->m_childLayerHasBlendMode = true;
- layer->m_childLayerHasBlendModeStatusDirty = false;
-
- if (layer->stackingNode()->isStackingContext())
- break;
- }
-}
-
-void RenderLayer::updateHasUnclippedDescendant()
-{
- TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasUnclippedDescendant");
- ASSERT(renderer()->isOutOfFlowPositioned());
- if (!m_hasVisibleContent && !m_hasVisibleDescendant)
- return;
-
- FrameView* frameView = renderer()->view()->frameView();
- if (!frameView)
- return;
-
- const RenderObject* containingBlock = renderer()->containingBlock();
- setIsUnclippedDescendant(false);
- for (RenderLayer* ancestor = parent(); ancestor && ancestor->renderer() != containingBlock; ancestor = ancestor->parent()) {
- // TODO(vollick): This isn't quite right. Whenever ancestor is composited and clips
- // overflow, we're technically unclipped. However, this will currently cause a huge
- // number of layers to report that they are unclipped. Eventually, when we've formally
- // separated the clipping, transform, opacity, and stacking trees here and in the
- // compositor, we will be able to relax this restriction without it being prohibitively
- // expensive (currently, we have to do a lot of work in the compositor to honor a
- // clip child/parent relationship).
- if (ancestor->scrollsOverflow())
- setIsUnclippedDescendant(true);
- ancestor->setHasUnclippedDescendant(true);
- }
-}
-
// FIXME: this is quite brute-force. We could be more efficient if we were to
-// track state and update it as appropriate as changes are made in the RenderObject tree.
-void RenderLayer::updateHasVisibleNonLayerContent()
+// track state and update it as appropriate as changes are made in the Render tree.
+void RenderLayer::updateScrollingStateAfterCompositingChange()
{
- TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasVisibleNonLayerContent");
+ TRACE_EVENT0("blink_rendering", "RenderLayer::updateScrollingStateAfterCompositingChange");
m_hasVisibleNonLayerContent = false;
- for (RenderObject* r = renderer()->firstChild(); r; r = r->nextSibling()) {
+ for (RenderObject* r = renderer()->slowFirstChild(); r; r = r->nextSibling()) {
if (!r->hasLayer()) {
m_hasVisibleNonLayerContent = true;
break;
}
}
-}
-static bool subtreeContainsOutOfFlowPositionedLayer(const RenderLayer* subtreeRoot)
-{
- return (subtreeRoot->renderer() && subtreeRoot->renderer()->isOutOfFlowPositioned()) || subtreeRoot->hasOutOfFlowPositionedDescendant();
+ m_hasNonCompositedChild = false;
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->compositingState() == NotComposited) {
+ m_hasNonCompositedChild = true;
+ return;
+ }
+ }
}
void RenderLayer::updateDescendantDependentFlags()
{
- if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
+ if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) {
m_hasVisibleDescendant = false;
m_hasSelfPaintingLayerDescendant = false;
- m_hasOutOfFlowPositionedDescendant = false;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
child->updateDescendantDependentFlags();
bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
- bool hasOutOfFlowPositionedDescendant = subtreeContainsOutOfFlowPositionedLayer(child);
m_hasVisibleDescendant |= hasVisibleDescendant;
m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
- m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
- if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && hasOutOfFlowPositionedDescendant)
+ if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant)
break;
}
m_visibleDescendantStatusDirty = false;
m_hasSelfPaintingLayerDescendantDirty = false;
- m_hasOutOfFlowPositionedDescendantDirty = false;
}
- if (m_childLayerHasBlendModeStatusDirty) {
- m_childLayerHasBlendMode = false;
+ if (m_blendInfo.childLayerHasBlendModeStatusDirty()) {
+ m_blendInfo.setChildLayerHasBlendMode(false);
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
if (!child->stackingNode()->isStackingContext())
child->updateDescendantDependentFlags();
- bool childLayerHasBlendMode = child->paintsWithBlendMode() || (child->m_childLayerHasBlendMode && !child->stackingNode()->isStackingContext());
- m_childLayerHasBlendMode |= childLayerHasBlendMode;
+ bool childLayerHadBlendMode = child->blendInfo().childLayerHasBlendModeWhileDirty();
+ bool childLayerHasBlendMode = childLayerHadBlendMode || child->blendInfo().hasBlendMode();
- if (m_childLayerHasBlendMode)
+ m_blendInfo.setChildLayerHasBlendMode(childLayerHasBlendMode);
+
+ if (childLayerHasBlendMode)
break;
}
- m_childLayerHasBlendModeStatusDirty = false;
+ m_blendInfo.setChildLayerHasBlendModeStatusDirty(false);
}
if (m_visibleContentStatusDirty) {
+ bool previouslyHasVisibleContent = m_hasVisibleContent;
if (renderer()->style()->visibility() == VISIBLE)
m_hasVisibleContent = true;
else {
// layer may be hidden but still have some visible content, check for this
m_hasVisibleContent = false;
- RenderObject* r = renderer()->firstChild();
+ RenderObject* r = renderer()->slowFirstChild();
while (r) {
if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
m_hasVisibleContent = true;
break;
}
- if (r->firstChild() && !r->hasLayer())
- r = r->firstChild();
+ RenderObject* rendererFirstChild = r->slowFirstChild();
+ if (rendererFirstChild && !r->hasLayer())
+ r = rendererFirstChild;
else if (r->nextSibling())
r = r->nextSibling();
else {
@@ -901,12 +865,17 @@ void RenderLayer::updateDescendantDependentFlags()
}
}
m_visibleContentStatusDirty = false;
+
+ // FIXME: We can remove this code once we remove the recursive tree
+ // walk inside updateGraphicsLayerGeometry.
+ if (hasVisibleContent() != previouslyHasVisibleContent)
+ setNeedsCompositingInputsUpdate();
}
}
void RenderLayer::dirty3DTransformedDescendantStatus()
{
- RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContainerNode();
+ RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContextNode();
if (!stackingNode)
return;
@@ -916,7 +885,7 @@ void RenderLayer::dirty3DTransformedDescendantStatus()
// Note that preserves3D() creates stacking context, so we can just run up the stacking containers.
while (stackingNode && stackingNode->layer()->preserves3D()) {
stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
- stackingNode = stackingNode->ancestorStackingContainerNode();
+ stackingNode = stackingNode->ancestorStackingContextNode();
}
}
@@ -949,6 +918,7 @@ bool RenderLayer::updateLayerPosition()
{
LayoutPoint localPoint;
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()->isInline() && renderer()->isRenderInline()) {
RenderInline* inlineFlow = toRenderInline(renderer());
IntRect lineBox = inlineFlow->linesBoundingBox();
@@ -990,20 +960,17 @@ bool RenderLayer::updateLayerPosition()
}
if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isInFlowPositioned() && positionedParent->renderer()->isRenderInline()) {
- LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(toRenderBox(renderer()));
+ LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(*toRenderBox(renderer()));
localPoint += offset;
}
} else if (parent()) {
if (hasCompositedLayerMapping()) {
// FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
// They won't split across columns properly.
- LayoutSize columnOffset;
- if (!parent()->renderer()->hasColumns() && parent()->renderer()->isRoot() && renderer()->view()->hasColumns())
- renderer()->view()->adjustForColumns(columnOffset, localPoint);
+ if (!parent()->renderer()->hasColumns() && parent()->renderer()->isDocumentElement() && renderer()->view()->hasColumns())
+ localPoint += renderer()->view()->columnOffset(localPoint);
else
- parent()->renderer()->adjustForColumns(columnOffset, localPoint);
-
- localPoint += columnOffset;
+ localPoint += parent()->renderer()->columnOffset(localPoint);
}
if (parent()->renderer()->hasOverflowClip()) {
@@ -1068,8 +1035,7 @@ FloatPoint RenderLayer::perspectiveOrigin() const
const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
RenderStyle* style = renderer()->style();
- return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width()),
- floatValueForLength(style->perspectiveOriginY(), borderBox.height()));
+ return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width().toFloat()), floatValueForLength(style->perspectiveOriginY(), borderBox.height().toFloat()));
}
static inline bool isFixedPositionedContainer(RenderLayer* layer)
@@ -1086,14 +1052,6 @@ RenderLayer* RenderLayer::enclosingPositionedAncestor() const
return curr;
}
-RenderLayer* RenderLayer::enclosingScrollableLayer() const
-{
- if (RenderBox* enclosingScrollableBox = renderer()->enclosingScrollableBox())
- return enclosingScrollableBox->layer();
-
- return 0;
-}
-
RenderLayer* RenderLayer::enclosingTransformedAncestor() const
{
RenderLayer* curr = parent();
@@ -1103,9 +1061,29 @@ RenderLayer* RenderLayer::enclosingTransformedAncestor() const
return curr;
}
-static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
+LayoutPoint RenderLayer::computeOffsetFromTransformedAncestor() const
+{
+ const CompositingInputs& properties = compositingInputs();
+
+ TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
+ // FIXME: add a test that checks flipped writing mode and ApplyContainerFlip are correct.
+ renderer()->mapLocalToContainer(properties.transformAncestor ? properties.transformAncestor->renderer() : 0, transformState, ApplyContainerFlip);
+ transformState.flatten();
+ return LayoutPoint(transformState.lastPlanarPoint());
+}
+
+const RenderLayer* RenderLayer::compositingContainer() const
+{
+ if (stackingNode()->isNormalFlowOnly())
+ return parent();
+ if (RenderLayerStackingNode* ancestorStackingNode = stackingNode()->ancestorStackingContextNode())
+ return ancestorStackingNode->layer();
+ return 0;
+}
+
+bool RenderLayer::isRepaintContainer() const
{
- return layer->stackingNode()->isNormalFlowOnly() ? layer->parent() : (layer->stackingNode()->ancestorStackingContainerNode() ? layer->stackingNode()->ancestorStackingContainerNode()->layer() : 0);
+ return compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking;
}
// FIXME: having two different functions named enclosingCompositingLayer and enclosingCompositingLayerForRepaint
@@ -1113,12 +1091,14 @@ static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
// the includeSelf option. It is very likely that we don't even want either of these functions; A layer
// should be told explicitly which GraphicsLayer is the repaintContainer for a RenderLayer, and
// any other use cases should probably have an API between the non-compositing and compositing sides of code.
-RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
+RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf) const
{
- if (includeSelf && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking)
+ ASSERT(isAllowedToQueryCompositingState());
+
+ if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking)
return const_cast<RenderLayer*>(this);
- for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
+ for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
if (curr->compositingState() != NotComposited && curr->compositingState() != PaintsIntoGroupedBacking)
return const_cast<RenderLayer*>(curr);
}
@@ -1126,59 +1106,92 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
return 0;
}
-RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(bool includeSelf) const
+RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const
{
- if (includeSelf && (compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking))
+ ASSERT(isAllowedToQueryCompositingState());
+
+ if ((includeSelf == IncludeSelf) && isRepaintContainer())
return const_cast<RenderLayer*>(this);
- for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
- if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == PaintsIntoGroupedBacking)
+ for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
+ if (curr->isRepaintContainer())
return const_cast<RenderLayer*>(curr);
}
return 0;
}
-RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const
+RenderLayer* RenderLayer::ancestorScrollingLayer() const
{
- if (!acceleratedCompositingForOverflowScrollEnabled())
- return 0;
+ for (RenderObject* container = renderer()->containingBlock(); container; container = container->containingBlock()) {
+ RenderLayer* currentLayer = container->enclosingLayer();
+ if (currentLayer->scrollsOverflow())
+ return currentLayer;
+ }
- RenderObject* containingBlock = renderer()->containingBlock();
- if (!containingBlock)
- return 0;
+ return 0;
+}
- for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
- if (ancestorLayer->needsCompositedScrolling())
- return ancestorLayer;
+RenderLayer* RenderLayer::enclosingFilterLayer(IncludeSelfOrNot includeSelf) const
+{
+ const RenderLayer* curr = (includeSelf == IncludeSelf) ? this : parent();
+ for (; curr; curr = curr->parent()) {
+ if (curr->requiresFullLayerImageForFilters())
+ return const_cast<RenderLayer*>(curr);
}
return 0;
}
-RenderLayer* RenderLayer::ancestorScrollingLayer() const
+void RenderLayer::setNeedsCompositingInputsUpdate()
{
- RenderObject* containingBlock = renderer()->containingBlock();
- if (!containingBlock)
- return 0;
+ m_needsCompositingInputsUpdate = true;
- for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
- if (ancestorLayer->scrollsOverflow())
- return ancestorLayer;
- }
+ for (RenderLayer* current = this; current && !current->m_childNeedsCompositingInputsUpdate; current = current->parent())
+ current->m_childNeedsCompositingInputsUpdate = true;
+}
- return 0;
+void RenderLayer::updateCompositingInputs(const CompositingInputs& compositingInputs)
+{
+ m_compositingInputs = compositingInputs;
+ m_needsCompositingInputsUpdate = false;
}
-RenderLayer* RenderLayer::enclosingFilterLayer(bool includeSelf) const
+void RenderLayer::clearChildNeedsCompositingInputsUpdate()
{
- const RenderLayer* curr = includeSelf ? this : parent();
- for (; curr; curr = curr->parent()) {
- if (curr->requiresFullLayerImageForFilters())
- return const_cast<RenderLayer*>(curr);
- }
+ ASSERT(!m_needsCompositingInputsUpdate);
+ m_childNeedsCompositingInputsUpdate = false;
+}
- return 0;
+void RenderLayer::setCompositingReasons(CompositingReasons reasons, CompositingReasons mask)
+{
+ ASSERT(reasons == (reasons & mask));
+ if ((compositingReasons() & mask) == (reasons & mask))
+ return;
+ m_compositingReasons = (reasons & mask) | (compositingReasons() & ~mask);
+ m_clipper.setCompositingClipRectsDirty();
+}
+
+void RenderLayer::setHasCompositingDescendant(bool hasCompositingDescendant)
+{
+ if (m_hasCompositingDescendant == static_cast<unsigned>(hasCompositingDescendant))
+ return;
+
+ m_hasCompositingDescendant = hasCompositingDescendant;
+
+ if (hasCompositedLayerMapping())
+ compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLocal);
+}
+
+void RenderLayer::setShouldIsolateCompositedDescendants(bool shouldIsolateCompositedDescendants)
+{
+ if (m_shouldIsolateCompositedDescendants == static_cast<unsigned>(shouldIsolateCompositedDescendants))
+ return;
+
+ m_shouldIsolateCompositedDescendants = shouldIsolateCompositedDescendants;
+
+ if (hasCompositedLayerMapping())
+ compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLocal);
}
bool RenderLayer::hasAncestorWithFilterOutsets() const
@@ -1191,28 +1204,6 @@ bool RenderLayer::hasAncestorWithFilterOutsets() const
return false;
}
-RenderLayer* RenderLayer::clippingRootForPainting() const
-{
- if (hasCompositedLayerMapping())
- return const_cast<RenderLayer*>(this);
-
- const RenderLayer* current = this;
- while (current) {
- if (current->isRootLayer())
- return const_cast<RenderLayer*>(current);
-
- current = compositingContainer(current);
- ASSERT(current);
- if (current->transform()
- || (current->compositingState() == PaintsIntoOwnBacking)
- )
- return const_cast<RenderLayer*>(current);
- }
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
bool RenderLayer::cannotBlitToWindow() const
{
if (isTransparent() || m_reflectionInfo || hasTransform())
@@ -1222,14 +1213,6 @@ bool RenderLayer::cannotBlitToWindow() const
return parent()->cannotBlitToWindow();
}
-bool RenderLayer::isTransparent() const
-{
- if (renderer()->node() && renderer()->node()->isSVGElement())
- return false;
-
- return renderer()->isTransparent() || renderer()->hasMask();
-}
-
RenderLayer* RenderLayer::transparentPaintingAncestor()
{
if (hasCompositedLayerMapping())
@@ -1254,10 +1237,10 @@ enum TransparencyClipBoxMode {
RootOfTransparencyClipBox
};
-static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, PaintBehavior = 0);
+static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, const LayoutSize& subPixelAccumulation, PaintBehavior = 0);
static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer,
- TransparencyClipBoxBehavior transparencyBehavior, PaintBehavior paintBehavior)
+ TransparencyClipBoxBehavior transparencyBehavior, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
{
// If we have a mask, then the clip is limited to the border box area (and there is
// no need to examine child layers).
@@ -1266,7 +1249,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons
// a stacking container. This means we can just walk the layer tree directly.
for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) {
if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionLayer() != curr)
- clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, paintBehavior));
+ clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, subPixelAccumulation, paintBehavior));
}
}
@@ -1284,7 +1267,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons
}
static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
- TransparencyClipBoxMode transparencyMode, PaintBehavior paintBehavior)
+ TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
{
// FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
// paintDirtyRect, and that should cut down on the amount we have to paint. Still it
@@ -1299,14 +1282,16 @@ static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLaye
LayoutPoint delta;
layer->convertToLayerCoords(rootLayerForTransform, delta);
+ delta.move(subPixelAccumulation);
+ IntPoint pixelSnappedDelta = roundedIntPoint(delta);
TransformationMatrix transform;
- transform.translate(delta.x(), delta.y());
+ transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y());
transform = transform * *layer->transform();
// We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
// paints unfragmented.
- LayoutRect clipRect = layer->boundingBox(layer);
- expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, paintBehavior);
+ LayoutRect clipRect = layer->physicalBoundingBox(layer);
+ expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, subPixelAccumulation, paintBehavior);
layer->renderer()->style()->filterOutsets().expandRect(clipRect);
LayoutRect result = transform.mapRect(clipRect);
if (!paginationLayer)
@@ -1324,36 +1309,41 @@ static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLaye
return result;
}
- LayoutRect clipRect = layer->boundingBox(rootLayer, RenderLayer::UseFragmentBoxes);
- expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, paintBehavior);
+ LayoutRect clipRect = layer->physicalBoundingBox(rootLayer);
+ expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, subPixelAccumulation, paintBehavior);
layer->renderer()->style()->filterOutsets().expandRect(clipRect);
+ clipRect.move(subPixelAccumulation);
return clipRect;
}
-LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
+LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
{
- return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintBehavior), paintDirtyRect);
+ return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, subPixelAccumulation, paintBehavior), paintDirtyRect);
}
-void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
+void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
{
- bool createTransparencyLayerForBlendMode = m_stackingNode->isStackingContext() && m_childLayerHasBlendMode;
+ bool createTransparencyLayerForBlendMode = m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency))
return;
RenderLayer* ancestor = transparentPaintingAncestor();
if (ancestor)
- ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
+ ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior);
if (paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) {
m_usedTransparency = true;
context->save();
- LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, paintBehavior);
+ LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior);
context->clip(clipRect);
+
if (paintsWithBlendMode())
- context->setCompositeOperation(context->compositeOperation(), m_blendMode);
+ context->setCompositeOperation(context->compositeOperation(), m_blendInfo.blendMode());
context->beginTransparencyLayer(renderer()->opacity());
+
+ if (paintsWithBlendMode())
+ context->setCompositeOperation(context->compositeOperation(), blink::WebBlendModeNormal);
#ifdef REVEAL_TRANSPARENCY_LAYERS
context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
context->fillRect(clipRect);
@@ -1388,16 +1378,19 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
} else
setLastChild(child);
- child->setParent(this);
+ child->m_parent = this;
+
+ setNeedsCompositingInputsUpdate();
+ compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree);
if (child->stackingNode()->isNormalFlowOnly())
m_stackingNode->dirtyNormalFlowList();
if (!child->stackingNode()->isNormalFlowOnly() || child->firstChild()) {
- // Dirty the z-order list in which we are contained. The ancestorStackingContainerNode() can be null in the
+ // Dirty the z-order list in which we are contained. The ancestorStackingContextNode() can be null in the
// case where we're building up generated content layers. This is ok, since the lists will start
// off dirty in that case anyway.
- child->stackingNode()->dirtyStackingContainerZOrderLists();
+ child->stackingNode()->dirtyStackingContextZOrderLists();
}
child->updateDescendantDependentFlags();
@@ -1407,32 +1400,12 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
setAncestorChainHasSelfPaintingLayerDescendant();
- if (child->paintsWithBlendMode() || child->childLayerHasBlendMode())
- setAncestorChainBlendedDescendant();
-
- if (subtreeContainsOutOfFlowPositionedLayer(child)) {
- // Now that the out of flow positioned descendant is in the tree, we
- // need to tell the compositor to reevaluate the compositing
- // requirements since we may be able to mark more layers as having
- // an 'unclipped' descendant.
- compositor()->setNeedsUpdateCompositingRequirementsState();
- setAncestorChainHasOutOfFlowPositionedDescendant();
- }
-
- // When we first dirty a layer, we will also dirty all the siblings in that
- // layer's stacking context. We need to manually do it here as well, in case
- // we're adding this layer after the stacking context has already been
- // updated.
- child->stackingNode()->setDescendantsAreContiguousInStackingOrderDirty(true);
- compositor()->layerWasAdded(this, child);
+ if (child->blendInfo().hasBlendMode() || child->blendInfo().childLayerHasBlendMode())
+ m_blendInfo.setAncestorChainBlendedDescendant();
}
RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
{
- if (!renderer()->documentBeingDestroyed())
- compositor()->layerWillBeRemoved(this, oldChild);
-
- // remove the child
if (oldChild->previousSibling())
oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
if (oldChild->nextSibling())
@@ -1448,28 +1421,25 @@ RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
if (!oldChild->stackingNode()->isNormalFlowOnly() || oldChild->firstChild()) {
// Dirty the z-order list in which we are contained. When called via the
// reattachment process in removeOnlyThisLayer, the layer may already be disconnected
- // from the main layer tree, so we need to null-check the |stackingContainer| value.
- oldChild->stackingNode()->dirtyStackingContainerZOrderLists();
+ // from the main layer tree, so we need to null-check the
+ // |stackingContext| value.
+ oldChild->stackingNode()->dirtyStackingContextZOrderLists();
}
+ if (renderer()->style()->visibility() != VISIBLE)
+ dirtyVisibleContentStatus();
+
oldChild->setPreviousSibling(0);
oldChild->setNextSibling(0);
- oldChild->setParent(0);
+ oldChild->m_parent = 0;
oldChild->updateDescendantDependentFlags();
- if (subtreeContainsOutOfFlowPositionedLayer(oldChild)) {
- // It may now be the case that a layer no longer has an unclipped
- // descendant. Let the compositor know that it needs to reevaluate
- // its compositing requirements to check this.
- compositor()->setNeedsUpdateCompositingRequirementsState();
- dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
- }
if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
dirtyAncestorChainVisibleDescendantStatus();
- if (oldChild->paintsWithBlendMode() || oldChild->childLayerHasBlendMode())
- dirtyAncestorChainBlendedDescendantStatus();
+ if (oldChild->m_blendInfo.hasBlendMode() || oldChild->blendInfo().childLayerHasBlendMode())
+ m_blendInfo.dirtyAncestorChainBlendedDescendantStatus();
if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
@@ -1482,9 +1452,6 @@ void RenderLayer::removeOnlyThisLayer()
if (!m_parent)
return;
- compositor()->layerWillBeRemoved(m_parent, this);
-
- // Dirty the clip rects.
m_clipper.clearClipRectsIncludingDescendants();
RenderLayer* nextSib = nextSibling();
@@ -1500,8 +1467,16 @@ void RenderLayer::removeOnlyThisLayer()
RenderLayer* next = current->nextSibling();
removeChild(current);
m_parent->addChild(current, nextSib);
- current->repainter().setRepaintStatus(NeedsFullRepaint);
- current->updateLayerPositions(0); // FIXME: use geometry map.
+
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ current->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
+ else
+ current->repainter().setRepaintStatus(NeedsFullRepaint);
+
+ // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-part-1.html
+ DisableCompositingQueryAsserts disabler;
+
+ current->updateLayerPositionRecursive();
current = next;
}
@@ -1522,27 +1497,13 @@ void RenderLayer::insertOnlyThisLayer()
}
// Remove all descendant layers from the hierarchy and add them to the new position.
- for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
+ for (RenderObject* curr = renderer()->slowFirstChild(); curr; curr = curr->nextSibling())
curr->moveLayers(m_parent, this);
// Clear out all the clip rects.
m_clipper.clearClipRectsIncludingDescendants();
}
-void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation) const
-{
- LayoutPoint location = roundedLocation;
- convertToLayerCoords(ancestorLayer, location);
- roundedLocation = roundedIntPoint(location);
-}
-
-void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect& roundedRect) const
-{
- LayoutRect rect = roundedRect;
- convertToLayerCoords(ancestorLayer, rect);
- roundedRect = pixelSnappedIntRect(rect);
-}
-
// Returns the layer reached on the walk up towards the ancestor.
static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, LayoutPoint& location)
{
@@ -1559,7 +1520,7 @@ static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLay
// FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
// may need to be revisited in a future patch.
// If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
- // since localToAbsolute maps the coordinates from named flow to regions coordinates and regions can be
+ // since localToAbsolute maps the coordinates from flow thread to regions coordinates and regions can be
// positioned in a completely different place in the viewport (RenderView).
if (position == FixedPosition && !fixedFlowThreadContainer && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) {
// If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
@@ -1627,8 +1588,7 @@ static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLay
// We should not reach RenderView layer past the RenderFlowThread layer for any
// children of the RenderFlowThread.
- if (renderer->flowThreadContainingBlock() && !layer->isOutOfFlowRenderFlowThread())
- ASSERT(parentLayer != renderer->view()->layer());
+ ASSERT(!renderer->flowThreadContainingBlock() || parentLayer != renderer->view()->layer());
if (foundAncestorFirst) {
// Found ancestorLayer before the abs. positioned container, so compute offset of both relative
@@ -1673,8 +1633,7 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutR
RenderLayer* RenderLayer::scrollParent() const
{
- if (!compositorDrivenAcceleratedScrollingEnabled())
- return 0;
+ ASSERT(compositor()->acceleratedCompositingForOverflowScrollEnabled());
// Normal flow elements will be parented under the main scrolling layer, so
// we don't need a scroll parent/child relationship to get them to scroll.
@@ -1693,16 +1652,18 @@ RenderLayer* RenderLayer::scrollParent() const
// our scrolling ancestor, and we will therefore not scroll with it. In this case, we must
// be a composited layer since the compositor will need to take special measures to ensure
// that we scroll with our scrolling ancestor and it cannot do this if we do not promote.
- RenderLayer* scrollParent = ancestorCompositedScrollingLayer();
- if (!scrollParent || scrollParent->stackingNode()->isStackingContainer())
+ RenderLayer* scrollParent = ancestorScrollingLayer();
+ if (!scrollParent || scrollParent->stackingNode()->isStackingContext())
return 0;
// If we hit a stacking context on our way up to the ancestor scrolling layer, it will already
// be composited due to an overflow scrolling parent, so we don't need to.
for (RenderLayer* ancestor = parent(); ancestor && ancestor != scrollParent; ancestor = ancestor->parent()) {
- if (ancestor->stackingNode()->isStackingContainer())
- return 0;
+ if (ancestor->stackingNode()->isStackingContext()) {
+ scrollParent = 0;
+ break;
+ }
}
return scrollParent;
@@ -1710,38 +1671,24 @@ RenderLayer* RenderLayer::scrollParent() const
RenderLayer* RenderLayer::clipParent() const
{
- const bool needsAncestorClip = compositor()->clippedByAncestor(this);
-
- RenderLayer* clipParent = 0;
- if ((compositingReasons() & CompositingReasonOutOfFlowClipping) && !needsAncestorClip) {
+ if (compositingReasons() & CompositingReasonOutOfFlowClipping && !compositor()->clippedByNonAncestorInStackingTree(this)) {
if (RenderObject* containingBlock = renderer()->containingBlock())
- clipParent = containingBlock->enclosingLayer()->enclosingCompositingLayer(true);
+ return containingBlock->enclosingLayer()->enclosingCompositingLayer();
}
-
- return clipParent;
+ return 0;
}
void RenderLayer::didUpdateNeedsCompositedScrolling()
{
- m_stackingNode->updateIsNormalFlowOnly();
updateSelfPaintingLayer();
-
- if (m_stackingNode->isStackingContainer())
- m_stackingNode->dirtyZOrderLists();
- else
- m_stackingNode->clearZOrderLists();
-
- m_stackingNode->dirtyStackingContainerZOrderLists();
-
- compositor()->setNeedsToRecomputeCompositingRequirements();
- compositor()->setCompositingLayersNeedRebuild();
}
void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle)
{
+ ASSERT(!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle));
if (renderer()->hasReflection()) {
if (!m_reflectionInfo)
- m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(toRenderBox(renderer())));
+ m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(*renderBox()));
m_reflectionInfo->updateAfterStyleChange(oldStyle);
} else if (m_reflectionInfo) {
m_reflectionInfo = nullptr;
@@ -1759,7 +1706,7 @@ void RenderLayer::updateStackingNode()
void RenderLayer::updateScrollableArea()
{
if (requiresScrollableArea())
- m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(renderBox()));
+ m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(*this));
else
m_scrollableArea = nullptr;
}
@@ -1776,12 +1723,13 @@ bool RenderLayer::hasOverflowControls() const
return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollableArea->hasScrollCorner() || renderer()->style()->resize() != RESIZE_NONE);
}
-void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags)
+void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, PaintLayerFlags paintFlags)
{
OverlapTestRequestMap overlapTestRequests;
- LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, region, &overlapTestRequests);
- paintLayer(context, paintingInfo, paintFlags);
+ LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, &overlapTestRequests);
+ if (shouldPaintLayerInSoftwareMode(context, paintingInfo, paintFlags))
+ paintLayer(context, paintingInfo, paintFlags);
OverlapTestRequestMap::iterator end = overlapTestRequests.end();
for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
@@ -1813,10 +1761,10 @@ static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
return false;
}
-void RenderLayer::clipToRect(RenderLayer* rootLayer, GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect,
- BorderRadiusClippingRule rule)
+void RenderLayer::clipToRect(const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const ClipRect& clipRect,
+ PaintLayerFlags paintFlags, BorderRadiusClippingRule rule)
{
- if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
+ if (clipRect.rect() == localPaintingInfo.paintDirtyRect && !clipRect.hasRadius())
return;
context->save();
context->clip(pixelSnappedIntRect(clipRect.rect()));
@@ -1828,13 +1776,20 @@ void RenderLayer::clipToRect(RenderLayer* rootLayer, GraphicsContext* context, c
// any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
// containing block chain so we check that also.
for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
+ // Composited scrolling layers handle border-radius clip in the compositor via a mask layer. We do not
+ // want to apply a border-radius clip to the layer contents itself, because that would require re-rastering
+ // every frame to update the clip. We only want to make sure that the mask layer is properly clipped so
+ // that it can in turn clip the scrolled contents in the compositor.
+ if (layer->needsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPhase))
+ break;
+
if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) {
LayoutPoint delta;
- layer->convertToLayerCoords(rootLayer, delta);
+ layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
}
- if (layer == rootLayer)
+ if (layer == localPaintingInfo.rootLayer)
break;
}
}
@@ -1850,7 +1805,7 @@ static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, cons
{
Vector<RenderWidget*> overlappedRequestClients;
OverlapTestRequestMap::iterator end = overlapTestRequests.end();
- LayoutRect boundingBox = layer->boundingBox(rootLayer);
+ LayoutRect boundingBox = layer->physicalBoundingBox(rootLayer);
for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
if (!boundingBox.intersects(it->value))
continue;
@@ -1858,13 +1813,7 @@ static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, cons
it->key->setIsOverlapped(true);
overlappedRequestClients.append(it->key);
}
- for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
- overlapTestRequests.remove(overlappedRequestClients[i]);
-}
-
-static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
-{
- return paintingReflection && !layer->has3DTransform();
+ overlapTestRequests.removeAll(overlappedRequestClients);
}
static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
@@ -1872,7 +1821,7 @@ static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
// Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC.
// It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
// will do a full repaint().
- if (layer->renderer()->document().didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isRoot())
+ if (layer->renderer()->document().didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isDocumentElement())
return true;
return false;
@@ -1880,21 +1829,22 @@ static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
static bool paintForFixedRootBackground(const RenderLayer* layer, PaintLayerFlags paintFlags)
{
- return layer->renderer()->isRoot() && (paintFlags & PaintLayerPaintingRootBackgroundOnly);
+ return layer->renderer()->isDocumentElement() && (paintFlags & PaintLayerPaintingRootBackgroundOnly);
+}
+
+static ShouldRespectOverflowClip shouldRespectOverflowClip(PaintLayerFlags paintFlags, const RenderObject* renderer)
+{
+ return (paintFlags & PaintLayerPaintingOverflowContents || (paintFlags & PaintLayerPaintingChildClippingMaskPhase && renderer->hasClipPath())) ? IgnoreOverflowClip : RespectOverflowClip;
}
void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
- if (compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking) {
- // The updatingControlTints() painting pass goes through compositing layers,
- // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
+ // https://code.google.com/p/chromium/issues/detail?id=343772
+ DisableCompositingQueryAsserts disabler;
+
+ if (compositingState() != NotComposited) {
if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)) {
paintFlags |= PaintLayerTemporaryClipRects;
- } else if (!compositedLayerMapping()->paintsIntoCompositedAncestor()
- && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)
- && !paintForFixedRootBackground(this, paintFlags)) {
- // If this RenderLayer should paint into its own backing, that will be done via CompositedLayerMapping::paintIntoLayer().
- return;
}
} else if (viewportConstrainedNotCompositedReason() == NotCompositedForBoundsOutOfView) {
// Don't paint out-of-view viewport constrained layers (when doing prepainting) because they will never be visible
@@ -1927,9 +1877,9 @@ void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo&
// layer from the parent now, assuming there is a parent
if (paintFlags & PaintLayerHaveTransparency) {
if (parent())
- parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+ parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
else
- beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+ beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
}
if (enclosingPaginationLayer()) {
@@ -1940,13 +1890,13 @@ void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo&
// Make sure the parent's clip rects have been calculated.
ClipRect clipRect = paintingInfo.paintDirtyRect;
if (parent()) {
- ClipRectsContext clipRectsContext(paintingInfo.rootLayer, paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
- IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
- clipRect = backgroundClipRect(clipRectsContext);
+ ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
+ IgnoreOverlayScrollbarSize, shouldRespectOverflowClip(paintFlags, renderer()));
+ clipRect = clipper().backgroundClipRect(clipRectsContext);
clipRect.intersect(paintingInfo.paintDirtyRect);
// Push the parent coordinate space's clip.
- parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
+ parent()->clipToRect(paintingInfo, context, clipRect, paintFlags);
}
paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
@@ -2003,7 +1953,7 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
GraphicsContext* transparencyLayerContext = context;
- if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isRoot())
+ if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isDocumentElement())
return;
// Ensure our lists are up-to-date.
@@ -2012,7 +1962,10 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
LayoutPoint offsetFromRoot;
convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
- IntRect rootRelativeBounds;
+ if (compositingState() == PaintsIntoOwnBacking)
+ offsetFromRoot.move(subpixelAccumulation());
+
+ LayoutRect rootRelativeBounds;
bool rootRelativeBoundsComputed = false;
// Apply clip-path to context.
@@ -2020,7 +1973,11 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
RenderStyle* style = renderer()->style();
RenderSVGResourceClipper* resourceClipper = 0;
ClipperContext clipperContext;
- if (renderer()->hasClipPath() && !context->paintingDisabled() && style) {
+
+ // Clip-path, like border radius, must not be applied to the contents of a composited-scrolling container.
+ // It must, however, still be applied to the mask layer, so that the compositor can properly mask the
+ // scrolling contents and scrollbars.
+ if (renderer()->hasClipPath() && !context->paintingDisabled() && style && (!needsCompositedScrolling() || paintFlags & PaintLayerPaintingChildClippingMaskPhase)) {
ASSERT(style->clipPath());
if (style->clipPath()->type() == ClipPathOperation::SHAPE) {
hasClipPath = true;
@@ -2028,7 +1985,7 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->clipPath());
if (!rootRelativeBoundsComputed) {
- rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+ rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
rootRelativeBoundsComputed = true;
}
@@ -2038,9 +1995,9 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
Document& document = renderer()->document();
// FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405)
Element* element = document.getElementById(referenceClipPathOperation->fragment());
- if (element && element->hasTagName(SVGNames::clipPathTag) && element->renderer()) {
+ if (isSVGClipPathElement(element) && element->renderer()) {
if (!rootRelativeBoundsComputed) {
- rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+ rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
rootRelativeBoundsComputed = true;
}
@@ -2056,10 +2013,10 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
// Blending operations must be performed only with the nearest ancestor stacking context.
// Note that there is no need to create a transparency layer if we're painting the root.
- bool createTransparencyLayerForBlendMode = !renderer()->isRoot() && m_stackingNode->isStackingContext() && m_childLayerHasBlendMode;
+ bool createTransparencyLayerForBlendMode = !renderer()->isDocumentElement() && m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
if (createTransparencyLayerForBlendMode)
- beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+ beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
LayerPaintingInfo localPaintingInfo(paintingInfo);
FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
@@ -2069,10 +2026,8 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y());
- if (!rootRelativeBoundsComputed) {
- rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
- rootRelativeBoundsComputed = true;
- }
+ if (!rootRelativeBoundsComputed)
+ rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, paintingInfo.paintDirtyRect, filterRepaintRect)) {
// Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
@@ -2097,7 +2052,7 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
if (filterPainter.hasStartedFilterEffect() && haveTransparency) {
// If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one with the wrong context.
- beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, localPaintingInfo.paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
}
// If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
@@ -2132,37 +2087,39 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
// Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
// fragment should paint.
- collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.region, localPaintingInfo.paintDirtyRect,
+ collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect,
(paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
- (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetFromRoot);
+ shouldRespectOverflowClip(paintFlags, renderer()), &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot);
}
- if (shouldPaintBackground)
+ if (shouldPaintBackground) {
paintBackgroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
- localPaintingInfo, paintBehavior, paintingRootForRenderer);
+ localPaintingInfo, paintBehavior, paintingRootForRenderer, paintFlags);
+ }
if (shouldPaintNegZOrderList)
paintChildren(NegativeZOrderChildren, context, localPaintingInfo, paintFlags);
- if (shouldPaintOwnContents)
+ if (shouldPaintOwnContents) {
paintForegroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
- localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText);
+ localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText, paintFlags);
+ }
if (shouldPaintOutline)
- paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer);
+ paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer, paintFlags);
if (shouldPaintNormalFlowAndPosZOrderLists)
paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, localPaintingInfo, paintFlags);
if (shouldPaintOverlayScrollbars)
- paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo);
+ paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags);
if (filterPainter.hasStartedFilterEffect()) {
// Apply the correct clipping (ie. overflow: hidden).
// FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
- clipToRect(localPaintingInfo.rootLayer, transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
+ clipToRect(localPaintingInfo, transparencyLayerContext, backgroundRect, paintFlags);
context = filterPainter.applyFilterEffect();
restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
}
@@ -2171,11 +2128,11 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
ASSERT(transparencyLayerContext == context);
if (shouldPaintMask)
- paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
+ paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags);
if (shouldPaintClippingMask) {
// Paint the border radius mask for the fragments.
- paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
+ paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags);
}
// End our transparency layer
@@ -2205,30 +2162,45 @@ void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const
LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
// Apply the transform.
- GraphicsContextStateSaver stateSaver(*context);
- context->concatCTM(transform.toAffineTransform());
+ GraphicsContextStateSaver stateSaver(*context, false);
+ if (!transform.isIdentity()) {
+ stateSaver.save();
+ context->concatCTM(transform.toAffineTransform());
+ }
// Now do a paint with the root layer shifted to be us.
LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior,
- adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.region, paintingInfo.overlapTestRequests);
+ adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.overlapTestRequests);
paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags);
}
+bool RenderLayer::shouldPaintLayerInSoftwareMode(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+ DisableCompositingQueryAsserts disabler;
+
+ return compositingState() == NotComposited
+ || compositingState() == HasOwnBackingButPaintsIntoAncestor
+ || context->updatingControlTints()
+ || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)
+ || ((paintFlags & PaintLayerPaintingReflection) && !has3DTransform())
+ || paintForFixedRootBackground(this, paintFlags);
+}
+
void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
if (!hasSelfPaintingLayerDescendant())
return;
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
LayerListMutationDetector mutationChecker(m_stackingNode.get());
#endif
RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit);
while (RenderLayerStackingNode* child = iterator.next()) {
RenderLayer* childLayer = child->layer();
-
- // Squashed RenderLayers should not paint into their ancestor.
- if (childLayer->compositingState() == PaintsIntoGroupedBacking)
+ // If this RenderLayer should paint into its own backing or a grouped backing, that will be done via CompositedLayerMapping::paintContents()
+ // and CompositedLayerMapping::doPaintTask().
+ if (!childLayer->shouldPaintLayerInSoftwareMode(context, paintingInfo, paintFlags))
continue;
if (!childLayer->isPaginated())
@@ -2238,15 +2210,15 @@ void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* conte
}
}
-void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, RenderRegion* region, const LayoutRect& dirtyRect,
+void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, const LayoutRect& dirtyRect,
ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot,
- const LayoutRect* layerBoundingBox)
+ const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox)
{
if (!enclosingPaginationLayer() || hasTransform()) {
// For unpaginated layers, there is only one fragment.
LayerFragment fragment;
- ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
- calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot);
+ ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, subPixelAccumulation);
+ clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot);
fragments.append(fragment);
return;
}
@@ -2257,16 +2229,16 @@ void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer*
// Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate
// layers between us and the pagination context. It's important to minimize the number of fragments we need to create and this helps with that.
- ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
+ ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
LayoutRect layerBoundsInFlowThread;
ClipRect backgroundRectInFlowThread;
ClipRect foregroundRectInFlowThread;
ClipRect outlineRectInFlowThread;
- calculateRects(paginationClipRectsContext, PaintInfo::infiniteRect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread,
+ clipper().calculateRects(paginationClipRectsContext, PaintInfo::infiniteRect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread,
outlineRectInFlowThread, &offsetWithinPaginatedLayer);
// Take our bounding box within the flow thread and clip it.
- LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : boundingBox(enclosingPaginationLayer(), 0, &offsetWithinPaginatedLayer);
+ LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : physicalBoundingBox(enclosingPaginationLayer(), &offsetWithinPaginatedLayer);
layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect());
// Shift the dirty rect into flow thread coordinates.
@@ -2286,8 +2258,8 @@ void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer*
// Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents.
ClipRect ancestorClipRect = dirtyRect;
if (enclosingPaginationLayer()->parent()) {
- ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
- ancestorClipRect = enclosingPaginationLayer()->backgroundClipRect(clipRectsContext);
+ ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
+ ancestorClipRect = enclosingPaginationLayer()->clipper().backgroundClipRect(clipRectsContext);
ancestorClipRect.intersect(dirtyRect);
}
@@ -2328,10 +2300,10 @@ void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, c
{
LayerFragments enclosingPaginationFragments;
LayoutPoint offsetOfPaginationLayerFromRoot;
- LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.paintBehavior);
- enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.region, paintingInfo.paintDirtyRect,
+ LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
+ enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect,
(paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
- (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetOfPaginationLayerFromRoot, &transformedExtent);
+ shouldRespectOverflowClip(paintFlags, renderer()), &offsetOfPaginationLayerFromRoot, paintingInfo.subPixelAccumulation, &transformedExtent);
for (size_t i = 0; i < enclosingPaginationFragments.size(); ++i) {
const LayerFragment& fragment = enclosingPaginationFragments.at(i);
@@ -2344,22 +2316,31 @@ void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, c
if (parent() != enclosingPaginationLayer()) {
enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot);
- ClipRectsContext clipRectsContext(enclosingPaginationLayer(), paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
- IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
- LayoutRect parentClipRect = backgroundClipRect(clipRectsContext).rect();
+ ClipRectsContext clipRectsContext(enclosingPaginationLayer(), (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
+ IgnoreOverlayScrollbarSize, shouldRespectOverflowClip(paintFlags, renderer()));
+ LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
clipRect.intersect(parentClipRect);
}
- parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
+ parent()->clipToRect(paintingInfo, context, clipRect, paintFlags);
paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
}
}
+static inline LayoutSize subPixelAccumulationIfNeeded(const LayoutSize& subPixelAccumulation, CompositingState compositingState)
+{
+ // Only apply the sub-pixel accumulation if we don't paint into our own backing layer, otherwise the position
+ // of the renderer already includes any sub-pixel offset.
+ if (compositingState == PaintsIntoOwnBacking)
+ return LayoutSize();
+ return subPixelAccumulation;
+}
+
void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
- RenderObject* paintingRootForRenderer)
+ RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
const LayerFragment& fragment = layerFragments.at(i);
@@ -2368,18 +2349,18 @@ void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragmen
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency || paintsWithBlendMode())
- beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
if (localPaintingInfo.clipToDirtyRect) {
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
+ clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
}
// Paint the background.
// FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
- PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
- renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+ PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
+ renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
if (localPaintingInfo.clipToDirtyRect)
restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
@@ -2388,14 +2369,14 @@ void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragmen
void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
- RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText)
+ RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText, PaintLayerFlags paintFlags)
{
// Begin transparency if we have something to paint.
if (haveTransparency || paintsWithBlendMode()) {
for (size_t i = 0; i < layerFragments.size(); ++i) {
const LayerFragment& fragment = layerFragments.at(i);
if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) {
- beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
break;
}
}
@@ -2406,17 +2387,17 @@ void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragmen
// Optimize clipping for the single fragment case.
bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
if (shouldClip)
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
+ clipToRect(localPaintingInfo, context, layerFragments[0].foregroundRect, paintFlags);
// We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for
// interleaving of the fragments to work properly.
paintForegroundForFragmentsWithPhase(selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, layerFragments,
- context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
+ context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags);
if (!selectionOnly) {
- paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
- paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
- paintForegroundForFragmentsWithPhase(PaintPhaseChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
+ paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags);
+ paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags);
+ paintForegroundForFragmentsWithPhase(PaintPhaseChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags);
}
if (shouldClip)
@@ -2424,7 +2405,7 @@ void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragmen
}
void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context,
- const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
+ const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
{
bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() > 1;
@@ -2434,12 +2415,12 @@ void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const L
continue;
if (shouldClip)
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
+ clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags);
- PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
+ PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
if (phase == PaintPhaseForeground)
paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
- renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+ renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
if (shouldClip)
restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
@@ -2447,7 +2428,7 @@ void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const L
}
void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
- PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
+ PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
const LayerFragment& fragment = layerFragments.at(i);
@@ -2455,15 +2436,15 @@ void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments,
continue;
// Paint our own outline
- PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.outlineRect, DoNotIncludeSelfForBorderRadius);
- renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+ PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
+ clipToRect(localPaintingInfo, context, fragment.outlineRect, paintFlags, DoNotIncludeSelfForBorderRadius);
+ renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect);
}
}
void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
- RenderObject* paintingRootForRenderer)
+ RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
const LayerFragment& fragment = layerFragments.at(i);
@@ -2471,12 +2452,12 @@ void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, Gr
continue;
if (localPaintingInfo.clipToDirtyRect)
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
+ clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
// Paint the mask.
// FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
- PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
- renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+ PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
+ renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
if (localPaintingInfo.clipToDirtyRect)
restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
@@ -2484,7 +2465,7 @@ void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, Gr
}
void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
- RenderObject* paintingRootForRenderer)
+ RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
const LayerFragment& fragment = layerFragments.at(i);
@@ -2492,24 +2473,24 @@ void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layer
continue;
if (localPaintingInfo.clipToDirtyRect)
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
+ clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
// Paint the the clipped mask.
- PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
- renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+ PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
+ renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
if (localPaintingInfo.clipToDirtyRect)
restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
}
}
-void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo)
+void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags paintFlags)
{
for (size_t i = 0; i < layerFragments.size(); ++i) {
const LayerFragment& fragment = layerFragments.at(i);
- clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+ clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags);
if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
- scrollableArea->paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation)), pixelSnappedIntRect(fragment.backgroundRect.rect()), true);
+ scrollableArea->paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))), pixelSnappedIntRect(fragment.backgroundRect.rect()), true);
restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
}
}
@@ -2518,7 +2499,7 @@ void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsCont
{
// We need to do multiple passes, breaking up our child layer into strips.
Vector<RenderLayer*> columnLayers;
- RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContainerNode();
+ RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContextNode();
for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
columnLayers.append(curr);
@@ -2527,8 +2508,8 @@ void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsCont
}
// It is possible for paintLayer() to be called after the child layer ceases to be paginated but before
- // updateLayerPositions() is called and resets the isPaginated() flag, see <rdar://problem/10098679>.
- // If this is the case, just bail out, since the upcoming call to updateLayerPositions() will repaint the layer.
+ // updateLayerPositionRecursive() is called and resets the isPaginated() flag, see <rdar://problem/10098679>.
+ // If this is the case, just bail out, since the upcoming call to updateLayerPositionRecursive() will repaint the layer.
if (!columnLayers.size())
return;
@@ -2582,7 +2563,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsCo
// Each strip pushes a clip, since column boxes are specified as being
// like overflow:hidden.
- context->clip(pixelSnappedIntRect(colRect));
+ context->clip(enclosingIntRect(colRect));
if (!colIndex) {
// Apply a translation transform to change where the layer paints.
@@ -2651,9 +2632,9 @@ bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation&
// RenderView should make sure to update layout before entering hit testing
ASSERT(!renderer()->frame()->view()->layoutPending());
- ASSERT(!renderer()->document().renderer()->needsLayout());
+ ASSERT(!renderer()->document().renderView()->needsLayout());
- LayoutRect hitTestArea = isOutOfFlowRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
+ LayoutRect hitTestArea = renderer()->view()->documentRect();
if (!request.ignoreClipping())
hitTestArea.intersect(frameVisibleRect(renderer()));
@@ -2694,15 +2675,6 @@ bool RenderLayer::isInTopLayer() const
return node && node->isElementNode() && toElement(node)->isInTopLayer();
}
-bool RenderLayer::isInTopLayerSubtree() const
-{
- for (const RenderLayer* layer = this; layer; layer = layer->parent()) {
- if (layer->isInTopLayer())
- return true;
- }
- return false;
-}
-
// Compute the z-offset of the point in the transformState.
// This is effectively projecting a ray normal to the plane of ancestor, finding where that
// ray intersects target, and computing the z delta between those two points.
@@ -2800,8 +2772,8 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- ClipRectsContext clipRectsContext(rootLayer, hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
- ClipRect clipRect = backgroundClipRect(clipRectsContext);
+ ClipRectsContext clipRectsContext(rootLayer, RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ ClipRect clipRect = clipper().backgroundClipRect(clipRectsContext);
// Go ahead and test the enclosing clip now.
if (!clipRect.intersects(hitTestLocation))
return 0;
@@ -2886,7 +2858,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
// Collect the fragments. This will compute the clip rectangles for each layer fragment.
LayerFragments layerFragments;
- collectFragments(layerFragments, rootLayer, hitTestLocation.region(), hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize);
if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFragments, hitTestLocation)) {
renderer()->updateHitTestResult(result, hitTestLocation.point());
@@ -2968,9 +2940,10 @@ RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLa
{
LayerFragments enclosingPaginationFragments;
LayoutPoint offsetOfPaginationLayerFromRoot;
- LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox);
- enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestLocation.region(), hitTestRect,
- RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, &transformedExtent);
+ // FIXME: We're missing a sub-pixel offset here crbug.com/348728
+ LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox, LayoutSize());
+ enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestRect,
+ RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent);
for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) {
const LayerFragment& fragment = enclosingPaginationFragments.at(i);
@@ -2983,8 +2956,8 @@ RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLa
if (parent() != enclosingPaginationLayer()) {
enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
- ClipRectsContext clipRectsContext(enclosingPaginationLayer(), hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
- LayoutRect parentClipRect = backgroundClipRect(clipRectsContext).rect();
+ ClipRectsContext clipRectsContext(enclosingPaginationLayer(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
clipRect.intersect(parentClipRect);
}
@@ -3100,7 +3073,7 @@ RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, Re
const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
{
Vector<RenderLayer*> columnLayers;
- RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContainerNode();
+ RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContextNode();
for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
columnLayers.append(curr);
@@ -3216,166 +3189,16 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
return 0;
}
-void RenderLayer::parentClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
-{
- ASSERT(parent());
- if (clipRectsContext.clipRectsType == TemporaryClipRects) {
- parent()->clipper().calculateClipRects(clipRectsContext, clipRects);
- return;
- }
-
- parent()->m_clipper.updateClipRects(clipRectsContext);
- clipRects = *parent()->clipper().clipRects(clipRectsContext);
-}
-
-static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
+void RenderLayer::blockSelectionGapsBoundsChanged()
{
- if (position == FixedPosition)
- return parentRects.fixedClipRect();
-
- if (position == AbsolutePosition)
- return parentRects.posClipRect();
-
- return parentRects.overflowClipRect();
-}
-
-ClipRect RenderLayer::backgroundClipRect(const ClipRectsContext& clipRectsContext) const
-{
- ASSERT(parent());
-
- ClipRects parentRects;
-
- // If we cross into a different pagination context, then we can't rely on the cache.
- // Just switch over to using TemporaryClipRects.
- if (clipRectsContext.clipRectsType != TemporaryClipRects && parent()->enclosingPaginationLayer() != enclosingPaginationLayer()) {
- ClipRectsContext tempContext(clipRectsContext);
- tempContext.clipRectsType = TemporaryClipRects;
- parentClipRects(tempContext, parentRects);
- } else
- parentClipRects(clipRectsContext, parentRects);
-
- ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
- RenderView* view = renderer()->view();
- ASSERT(view);
-
- // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
- if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
- backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition());
-
- return backgroundClipRect;
-}
-
-void RenderLayer::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
- ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
-{
- if (clipRectsContext.rootLayer != this && parent()) {
- backgroundRect = backgroundClipRect(clipRectsContext);
- backgroundRect.intersect(paintDirtyRect);
- } else
- backgroundRect = paintDirtyRect;
-
- foregroundRect = backgroundRect;
- outlineRect = backgroundRect;
-
- LayoutPoint offset;
- if (offsetFromRoot)
- offset = *offsetFromRoot;
- else
- convertToLayerCoords(clipRectsContext.rootLayer, offset);
- layerBounds = LayoutRect(offset, size());
-
- // Update the clip rects that will be passed to child layers.
- if (renderer()->hasOverflowClip()) {
- // This layer establishes a clip of some kind.
- if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip) {
- foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy));
- if (renderer()->style()->hasBorderRadius())
- foregroundRect.setHasRadius(true);
- }
-
- // If we establish an overflow clip at all, then go ahead and make sure our background
- // rect is intersected with our layer's bounds including our visual overflow,
- // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
- if (renderBox()->hasVisualOverflow()) {
- // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though
- // we may need to inflate our clip specifically for shadows or outsets.
- // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
- // individual region boxes as overflow.
- LayoutRect layerBoundsWithVisualOverflow = renderBox()->visualOverflowRect();
- renderBox()->flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
- layerBoundsWithVisualOverflow.moveBy(offset);
- if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
- backgroundRect.intersect(layerBoundsWithVisualOverflow);
- } else {
- // Shift the bounds to be for our region only.
- LayoutRect bounds = renderBox()->borderBoxRectInRegion(clipRectsContext.region);
- bounds.moveBy(offset);
- if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
- backgroundRect.intersect(bounds);
- }
- }
-
- // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
- if (renderer()->hasClip()) {
- // Clip applies to *us* as well, so go ahead and update the damageRect.
- LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, clipRectsContext.region);
- backgroundRect.intersect(newPosClip);
- foregroundRect.intersect(newPosClip);
- outlineRect.intersect(newPosClip);
- }
-}
-
-LayoutRect RenderLayer::childrenClipRect() const
-{
- // FIXME: border-radius not accounted for.
- // FIXME: Regions not accounted for.
- RenderView* renderView = renderer()->view();
- RenderLayer* clippingRootLayer = clippingRootForPainting();
- LayoutRect layerBounds;
- ClipRect backgroundRect, foregroundRect, outlineRect;
- ClipRectsContext clipRectsContext(clippingRootLayer, 0, TemporaryClipRects);
- // Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
- calculateRects(clipRectsContext, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
- return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
-}
-
-LayoutRect RenderLayer::selfClipRect() const
-{
- // FIXME: border-radius not accounted for.
- // FIXME: Regions not accounted for.
- RenderView* renderView = renderer()->view();
- RenderLayer* clippingRootLayer = clippingRootForPainting();
- LayoutRect layerBounds;
- ClipRect backgroundRect, foregroundRect, outlineRect;
- ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
- calculateRects(clipRectsContext, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
- 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 = clippingRootForPainting();
- LayoutRect layerBounds;
- ClipRect backgroundRect, foregroundRect, outlineRect;
- ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
- calculateRects(clipRectsContext, 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;
+ setNeedsCompositingInputsUpdate();
+ compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
}
void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
{
m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds));
+ blockSelectionGapsBoundsChanged();
}
void RenderLayer::clearBlockSelectionGapsBounds()
@@ -3383,6 +3206,7 @@ void RenderLayer::clearBlockSelectionGapsBounds()
m_blockSelectionGapsBounds = IntRect();
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
child->clearBlockSelectionGapsBounds();
+ blockSelectionGapsBoundsChanged();
}
void RenderLayer::repaintBlockSelectionGaps()
@@ -3398,25 +3222,43 @@ void RenderLayer::repaintBlockSelectionGaps()
RenderBox* box = renderBox();
rect.move(-box->scrolledContentOffset());
if (!scrollableArea()->usesCompositedScrolling())
- rect.intersect(box->overflowClipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
+ rect.intersect(box->overflowClipRect(LayoutPoint()));
}
if (renderer()->hasClip())
- rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
+ rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint()));
if (!rect.isEmpty())
- renderer()->repaintRectangle(rect);
+ renderer()->invalidatePaintRectangle(rect);
+}
+
+IntRect RenderLayer::blockSelectionGapsBounds() const
+{
+ if (!renderer()->isRenderBlock())
+ return IntRect();
+
+ RenderBlock* renderBlock = toRenderBlock(renderer());
+ LayoutRect gapRects = renderBlock->selectionGapRectsForRepaint(renderBlock);
+
+ return pixelSnappedIntRect(gapRects);
}
bool RenderLayer::hasBlockSelectionGapBounds() const
{
- return !m_blockSelectionGapsBounds.isEmpty();
+ // FIXME: it would be more accurate to return !blockSelectionGapsBounds().isEmpty(), but this is impossible
+ // at the moment because it causes invalid queries to layout-dependent code (crbug.com/372802).
+ // ASSERT(renderer()->document().lifecycle().state() >= DocumentLifecycle::LayoutClean);
+
+ if (!renderer()->isRenderBlock())
+ return false;
+
+ return toRenderBlock(renderer())->shouldPaintSelectionGaps();
}
bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) const
{
// Always examine the canvas and the root.
- // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
+ // FIXME: Could eliminate the isDocumentElement() check if we fix background painting so that the RenderView
// paints the root's background.
- if (isRootLayer() || renderer()->isRoot())
+ if (isRootLayer() || renderer()->isDocumentElement())
return true;
// If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
@@ -3424,18 +3266,16 @@ bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const Layo
RenderView* view = renderer()->view();
ASSERT(view);
if (view && !renderer()->isRenderInline()) {
- LayoutRect b = layerBounds;
- b.inflate(view->maximalOutlineSize());
- if (b.intersects(damageRect))
+ if (layerBounds.intersects(damageRect))
return true;
}
// Otherwise we need to compute the bounding box of this single layer and see if it intersects
// the damage rect.
- return boundingBox(rootLayer, 0, offsetFromRoot).intersects(damageRect);
+ return physicalBoundingBox(rootLayer, offsetFromRoot).intersects(damageRect);
}
-LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) const
+LayoutRect RenderLayer::logicalBoundingBox() const
{
// There are three special cases we need to consider.
// (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
@@ -3447,11 +3287,11 @@ LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) const
// as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those
// floats.
LayoutRect result;
- if (renderer()->isInline() && renderer()->isRenderInline())
+ if (renderer()->isInline() && renderer()->isRenderInline()) {
result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
- else if (renderer()->isTableRow()) {
+ } else if (renderer()->isTableRow()) {
// Our bounding box is just the union of all of our cells' border/overflow rects.
- for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = renderer()->slowFirstChild(); child; child = child->nextSibling()) {
if (child->isTableCell()) {
LayoutRect bbox = toRenderBox(child)->borderBoxRect();
result.unite(bbox);
@@ -3463,52 +3303,21 @@ LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) const
} else {
RenderBox* box = renderBox();
ASSERT(box);
- if (!(flags & DontConstrainForMask) && box->hasMask()) {
- result = box->maskClipRect();
- box->flipForWritingMode(result); // The mask clip rect is in physical coordinates, so we have to flip, since localBoundingBox is not.
- } else {
- LayoutRect bbox = box->borderBoxRect();
- result = bbox;
- LayoutRect overflowRect = box->visualOverflowRect();
- if (bbox != overflowRect)
- result.unite(overflowRect);
- }
+ result = box->borderBoxRect();
+ result.unite(box->visualOverflowRect());
}
- RenderView* view = renderer()->view();
- ASSERT(view);
- if (view)
- result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
-
+ ASSERT(renderer()->view());
return result;
}
-LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags, const LayoutPoint* offsetFromRoot) const
+LayoutRect RenderLayer::physicalBoundingBox(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot) const
{
- LayoutRect result = localBoundingBox(flags);
- if (renderer()->isBox())
+ LayoutRect result = logicalBoundingBox();
+ if (m_renderer->isBox())
renderBox()->flipForWritingMode(result);
else
- renderer()->containingBlock()->flipForWritingMode(result);
-
- if (enclosingPaginationLayer() && (flags & UseFragmentBoxes)) {
- // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
- // get our true bounding box.
- LayoutPoint offsetWithinPaginationLayer;
- convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginationLayer);
- result.moveBy(offsetWithinPaginationLayer);
-
- RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
- result = enclosingFlowThread->fragmentsBoundingBox(result);
-
- LayoutPoint delta;
- if (offsetFromRoot)
- delta = *offsetFromRoot;
- else
- enclosingPaginationLayer()->convertToLayerCoords(ancestorLayer, delta);
- result.moveBy(delta);
- return result;
- }
+ m_renderer->containingBlock()->flipForWritingMode(result);
LayoutPoint delta;
if (offsetFromRoot)
@@ -3520,125 +3329,120 @@ LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, CalculateL
return result;
}
-IntRect RenderLayer::absoluteBoundingBox() const
+LayoutRect RenderLayer::physicalBoundingBoxIncludingReflectionAndStackingChildren(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const
{
- return pixelSnappedIntRect(boundingBox(root()));
-}
+ LayoutPoint origin;
+ LayoutRect result = physicalBoundingBox(ancestorLayer, &origin);
-IntRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot, CalculateLayerBoundsFlags flags) const
-{
- if (!isSelfPaintingLayer())
- return IntRect();
+ if (m_reflectionInfo && !m_reflectionInfo->reflectionLayer()->hasCompositedLayerMapping())
+ result.unite(m_reflectionInfo->reflectionLayer()->physicalBoundingBox(this));
- // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
- if ((flags & ExcludeHiddenDescendants) && this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
- return IntRect();
+ ASSERT(m_stackingNode->isStackingContext() || !m_stackingNode->hasPositiveZOrderList());
- RenderLayerModelObject* renderer = this->renderer();
+ const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
- if (isRootLayer()) {
- // The root layer is always just the size of the document.
- return renderer->view()->unscaledDocumentRect();
+#if ASSERT_ENABLED
+ LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode());
+#endif
+
+ RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), AllChildren);
+ while (RenderLayerStackingNode* node = iterator.next()) {
+ if (node->layer()->hasCompositedLayerMapping())
+ continue;
+ // FIXME: Can we call physicalBoundingBoxIncludingReflectionAndStackingChildren instead of boundingBoxForCompositing?
+ result.unite(node->layer()->boundingBoxForCompositing(this));
}
- LayoutRect boundingBoxRect = localBoundingBox(flags);
+ result.moveBy(offsetFromRoot);
+ return result;
+}
- if (renderer->isBox())
- toRenderBox(renderer)->flipForWritingMode(boundingBoxRect);
- else
- renderer->containingBlock()->flipForWritingMode(boundingBoxRect);
-
- if (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 = 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()));
- }
+static void expandCompositingRectForStackingChildren(const RenderLayer* ancestorLayer, RenderLayer::CalculateBoundsOptions options, LayoutRect& result)
+{
+ RenderLayerStackingNodeIterator iterator(*ancestorLayer->stackingNode(), AllChildren);
+ while (RenderLayerStackingNode* node = iterator.next()) {
+ // Here we exclude both directly composited layers and squashing layers
+ // because those RenderLayers don't paint into the graphics layer
+ // for this RenderLayer. For example, the bounds of squashed RenderLayers
+ // will be included in the computation of the appropriate squashing
+ // GraphicsLayer.
+ if (options != RenderLayer::ApplyBoundsChickenEggHacks && node->layer()->compositingState() != NotComposited)
+ continue;
+ result.unite(node->layer()->boundingBoxForCompositing(ancestorLayer, options));
}
+}
- LayoutRect unionBounds = boundingBoxRect;
- bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (transform() && flags & PretendLayerHasOwnBacking);
+LayoutRect RenderLayer::boundingBoxForCompositing(const RenderLayer* ancestorLayer, CalculateBoundsOptions options) const
+{
+ if (!isSelfPaintingLayer())
+ return LayoutRect();
- if (flags & UseLocalClipRectIfPossible) {
- LayoutRect localClipRect = this->localClipRect();
- if (localClipRect != PaintInfo::infiniteRect()) {
- if ((flags & IncludeSelfTransform) && shouldIncludeTransform)
- localClipRect = transform()->mapRect(localClipRect);
+ if (!ancestorLayer)
+ ancestorLayer = this;
- LayoutPoint ancestorRelOffset;
- convertToLayerCoords(ancestorLayer, ancestorRelOffset);
- localClipRect.moveBy(ancestorRelOffset);
- return pixelSnappedIntRect(localClipRect);
- }
+ // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
+ if (this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
+ return LayoutRect();
+
+ // The root layer is always just the size of the document.
+ if (isRootLayer())
+ return m_renderer->view()->unscaledDocumentRect();
+
+ const bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (options == ApplyBoundsChickenEggHacks && transform());
+
+ LayoutRect localClipRect = clipper().localClipRect();
+ if (localClipRect != PaintInfo::infiniteRect()) {
+ if (shouldIncludeTransform)
+ localClipRect = transform()->mapRect(localClipRect);
+
+ LayoutPoint delta;
+ convertToLayerCoords(ancestorLayer, delta);
+ localClipRect.moveBy(delta);
+ return localClipRect;
}
- // FIXME: should probably just pass 'flags' down to descendants.
- CalculateLayerBoundsFlags descendantFlags = DefaultCalculateLayerBoundsFlags | (flags & ExcludeHiddenDescendants) | (flags & IncludeCompositedDescendants);
+ LayoutPoint origin;
+ LayoutRect result = physicalBoundingBox(ancestorLayer, &origin);
const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
- if (m_reflectionInfo) {
- RenderLayer* reflectionLayer = m_reflectionInfo->reflectionLayer();
- if (!reflectionLayer->hasCompositedLayerMapping()) {
- IntRect childUnionBounds = reflectionLayer->calculateLayerBounds(this, 0, descendantFlags);
- unionBounds.unite(childUnionBounds);
- }
- }
+ if (m_reflectionInfo && !m_reflectionInfo->reflectionLayer()->hasCompositedLayerMapping())
+ result.unite(m_reflectionInfo->reflectionLayer()->boundingBoxForCompositing(this));
- ASSERT(m_stackingNode->isStackingContainer() || !m_stackingNode->hasPositiveZOrderList());
+ ASSERT(m_stackingNode->isStackingContext() || !m_stackingNode->hasPositiveZOrderList());
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode());
#endif
- // FIXME: Descendants that are composited should not necessarily be skipped, if they don't paint into their own
- // separate backing. Instead, they ought to contribute to the bounds of the layer we're trying to compute.
- // This applies to all z-order lists below.
- RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), AllChildren);
- while (RenderLayerStackingNode* node = iterator.next()) {
- // Node's compositing ancestor may have changed its draw content status
- // prior to updating its bounds. The requires-own-backing-store-for-ancestor-reasons
- // could be stale. Refresh them now.
- if (node->layer()->hasCompositedLayerMapping()) {
- RenderLayer* enclosingCompositingLayer = node->layer()->enclosingCompositingLayer(false);
- node->layer()->compositedLayerMapping()->updateRequiresOwnBackingStoreForAncestorReasons(enclosingCompositingLayer);
- }
-
- if (flags & IncludeCompositedDescendants || !node->layer()->hasCompositedLayerMapping()) {
- IntRect childUnionBounds = node->layer()->calculateLayerBounds(this, 0, descendantFlags);
- unionBounds.unite(childUnionBounds);
- }
- }
+ // Reflections are implemented with RenderLayers that hang off of the reflected layer. However,
+ // the reflection layer subtree does not include the subtree of the parent RenderLayer, so
+ // a recursive computation of stacking children yields no results. This breaks cases when there are stacking
+ // children of the parent, that need to be included in reflected composited bounds.
+ // Fix this by including composited bounds of stacking children of the reflected RenderLayer.
+ if (parent() && parent()->reflectionInfo() && parent()->reflectionInfo()->reflectionLayer() == this)
+ expandCompositingRectForStackingChildren(parent(), options, result);
+ else
+ expandCompositingRectForStackingChildren(this, options, result);
// 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)
- renderer->style()->filterOutsets().expandRect(unionBounds);
-
- if ((flags & IncludeSelfTransform) && shouldIncludeTransform) {
- TransformationMatrix* affineTrans = transform();
- boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
- unionBounds = affineTrans->mapRect(unionBounds);
- }
+ m_renderer->style()->filterOutsets().expandRect(result);
- LayoutPoint ancestorRelOffset;
- if (offsetFromRoot)
- ancestorRelOffset = *offsetFromRoot;
- else
- convertToLayerCoords(ancestorLayer, ancestorRelOffset);
- unionBounds.moveBy(ancestorRelOffset);
+ if (shouldIncludeTransform)
+ result = transform()->mapRect(result);
- return pixelSnappedIntRect(unionBounds);
+ LayoutPoint delta;
+ convertToLayerCoords(ancestorLayer, delta);
+ result.moveBy(delta);
+ return result;
}
CompositingState RenderLayer::compositingState() const
{
+ ASSERT(isAllowedToQueryCompositingState());
+
// This is computed procedurally so there is no redundant state variable that
// can get out of sync from the real actual compositing state.
@@ -3651,34 +3455,70 @@ CompositingState RenderLayer::compositingState() const
if (!m_compositedLayerMapping)
return NotComposited;
- if (m_compositedLayerMapping && compositedLayerMapping()->paintsIntoCompositedAncestor())
+ if (compositedLayerMapping()->paintsIntoCompositedAncestor())
return HasOwnBackingButPaintsIntoAncestor;
- ASSERT(m_compositedLayerMapping);
return PaintsIntoOwnBacking;
}
+bool RenderLayer::isAllowedToQueryCompositingState() const
+{
+ if (gCompositingQueryMode == CompositingQueriesAreAllowed)
+ return true;
+ return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate;
+}
+
+CompositedLayerMappingPtr RenderLayer::compositedLayerMapping() const
+{
+ ASSERT(isAllowedToQueryCompositingState());
+ return m_compositedLayerMapping.get();
+}
+
CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping()
{
if (!m_compositedLayerMapping) {
- m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(this));
+ m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(*this));
+ m_compositedLayerMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
updateOrRemoveFilterEffectRenderer();
if (RuntimeEnabledFeatures::cssCompositingEnabled())
- compositedLayerMapping()->setBlendMode(m_blendMode);
+ compositedLayerMapping()->setBlendMode(m_blendInfo.blendMode());
}
return m_compositedLayerMapping.get();
}
void RenderLayer::clearCompositedLayerMapping(bool layerBeingDestroyed)
{
+ if (!layerBeingDestroyed) {
+ // We need to make sure our decendants get a geometry update. In principle,
+ // we could call setNeedsGraphicsLayerUpdate on our children, but that would
+ // require walking the z-order lists to find them. Instead, we over-invalidate
+ // by marking our parent as needing a geometry update.
+ if (RenderLayer* compositingParent = enclosingCompositingLayer(ExcludeSelf))
+ compositingParent->compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+ }
+
m_compositedLayerMapping.clear();
if (!layerBeingDestroyed)
updateOrRemoveFilterEffectRenderer();
}
+void RenderLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping, bool layerBeingDestroyed)
+{
+ if (groupedMapping == m_groupedMapping)
+ return;
+
+ if (!layerBeingDestroyed && m_groupedMapping) {
+ m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+ m_groupedMapping->removeRenderLayerFromSquashingGraphicsLayer(this);
+ }
+ m_groupedMapping = groupedMapping;
+ if (!layerBeingDestroyed && m_groupedMapping)
+ m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+}
+
bool RenderLayer::hasCompositedMask() const
{
return m_compositedLayerMapping && m_compositedLayerMapping->hasMaskLayer();
@@ -3703,6 +3543,11 @@ bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || compositingState() != PaintsIntoOwnBacking);
}
+bool RenderLayer::paintsWithBlendMode() const
+{
+ return m_blendInfo.hasBlendMode() && compositingState() != PaintsIntoOwnBacking;
+}
+
bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
{
if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
@@ -3764,32 +3609,13 @@ bool RenderLayer::childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect& local
return false;
}
-void RenderLayer::setParent(RenderLayer* parent)
-{
- if (parent == m_parent)
- return;
-
- if (m_parent && !renderer()->documentBeingDestroyed())
- compositor()->layerWillBeRemoved(m_parent, this);
-
- m_parent = parent;
-
- if (m_parent && !renderer()->documentBeingDestroyed())
- compositor()->layerWasAdded(m_parent, this);
-}
-
bool RenderLayer::shouldBeSelfPaintingLayer() const
{
- return !m_stackingNode->isNormalFlowOnly()
+ if (renderer()->isRenderPart() && toRenderPart(renderer())->requiresAcceleratedCompositing())
+ return true;
+ return m_layerType == NormalLayer
|| (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars())
- || needsCompositedScrolling()
- || renderer()->hasReflection()
- || renderer()->hasMask()
- || renderer()->isTableRow()
- || renderer()->isCanvas()
- || renderer()->isVideo()
- || renderer()->isEmbeddedObject()
- || renderer()->isRenderIFrame();
+ || needsCompositedScrolling();
}
void RenderLayer::updateSelfPaintingLayer()
@@ -3814,7 +3640,7 @@ bool RenderLayer::hasNonEmptyChildRenderers() const
// <img src=...>
// </div>
// so test for 0x0 RenderTexts here
- for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = renderer()->slowFirstChild(); child; child = child->nextSibling()) {
if (!child->hasLayer()) {
if (child->isRenderInline() || !child->isBox())
return true;
@@ -3860,114 +3686,12 @@ bool RenderLayer::isVisuallyNonEmpty() const
return false;
}
-void RenderLayer::updateVisibilityAfterStyleChange(const RenderStyle* oldStyle)
-{
- if (!oldStyle || (oldStyle->visibility() != renderer()->style()->visibility()))
- compositor()->setNeedsUpdateCompositingRequirementsState();
-}
-
-void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle)
-{
- if (oldStyle && (renderer()->style()->position() == oldStyle->position()))
- return;
-
- bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition);
- bool isOutOfFlowPositioned = renderer()->isOutOfFlowPositioned();
- if (!wasOutOfFlowPositioned && !isOutOfFlowPositioned)
- return;
-
- // Even if the layer remains out-of-flow, a change to this property
- // will likely change its containing block. We must clear these bits
- // so that they can be set properly by the RenderLayerCompositor.
- for (RenderLayer* ancestor = parent(); ancestor; ancestor = ancestor->parent())
- ancestor->setHasUnclippedDescendant(false);
-
- // Ensures that we reset the above bits correctly.
- compositor()->setNeedsUpdateCompositingRequirementsState();
-
- if (wasOutOfFlowPositioned && isOutOfFlowPositioned)
- return;
-
- if (isOutOfFlowPositioned) {
- setAncestorChainHasOutOfFlowPositionedDescendant();
- compositor()->addOutOfFlowPositionedLayer(this);
- } else {
- dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
- compositor()->removeOutOfFlowPositionedLayer(this);
-
- // We need to reset the isUnclippedDescendant bit here because normally
- // the "unclipped-ness" property is only updated in
- // RenderLayerCompositor::updateCompositingRequirementsState(). However,
- // it is only updated for layers which are known to be out of flow.
- // Since this is no longer out of flow, we have to explicitly ensure
- // that it doesn't think it is unclipped.
- setIsUnclippedDescendant(false);
- }
-}
-
static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
{
ASSERT(newStyle);
return (oldStyle && oldStyle->hasFilter()) || newStyle->hasFilter();
}
-inline bool RenderLayer::needsCompositingLayersRebuiltForClip(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
-{
- ASSERT(newStyle);
- return oldStyle && (oldStyle->clip() != newStyle->clip() || oldStyle->hasClip() != newStyle->hasClip());
-}
-
-inline bool RenderLayer::needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
-{
- ASSERT(newStyle);
- return !hasCompositedLayerMapping() && oldStyle && (oldStyle->overflowX() != newStyle->overflowX()) && m_stackingNode->ancestorStackingContainerNode()->layer()->hasCompositingDescendant();
-}
-
-inline bool RenderLayer::needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const
-{
- if (!hasOrHadFilters(oldStyle, newStyle))
- return false;
-
- if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()
- ? hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)
- : renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter)) {
-
- // When the compositor is performing the filter animation, we shouldn't touch the compositing layers.
- // All of the layers above us should have been promoted to compositing layers already.
- return false;
- }
-
- FilterOutsets newOutsets = newStyle->filterOutsets();
- if (oldStyle && (oldStyle->filterOutsets() != newOutsets)) {
- // When filter outsets change, we need to:
- // (1) Recompute the overlap map to promote the correct layers to composited layers.
- // (2) Update the composited layer bounds (and child GraphicsLayer positions) on platforms
- // whose compositors can't compute their own filter outsets.
- return true;
- }
-
-#if HAVE(COMPOSITOR_FILTER_OUTSETS)
- if ((didPaintWithFilters != paintsWithFilters()) && !newOutsets.isZero()) {
- // When the layer used to paint filters in software and now paints filters in the
- // compositor, the compositing layer bounds need to change from including filter outsets to
- // excluding filter outsets, on platforms whose compositors compute their own outsets.
- // Similarly for the reverse change from compositor-painted to software-painted filters.
- return true;
- }
-#endif
-
- return false;
-}
-
-inline bool RenderLayer::needsCompositingLayersRebuiltForBlending(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
-{
- ASSERT(newStyle);
- if (!hasCompositedLayerMapping())
- return false;
- return (shouldIsolateCompositedDescendants() && !stackingNode()->isStackingContext())
- || (oldStyle && (oldStyle->hasBlendMode() != newStyle->hasBlendMode()));
-}
-
void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
{
if (!hasOrHadFilters(oldStyle, newStyle))
@@ -3976,59 +3700,50 @@ void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle*
updateOrRemoveFilterClients();
// During an accelerated animation, both WebKit and the compositor animate properties.
// However, WebKit shouldn't ask the compositor to update its filters if the compositor is performing the animation.
- if (hasCompositedLayerMapping() && (RuntimeEnabledFeatures::webAnimationsCSSEnabled()
- ? !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)
- : !renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter)))
+ if (hasCompositedLayerMapping() && !newStyle->isRunningFilterAnimationOnCompositor())
compositedLayerMapping()->updateFilters(renderer()->style());
updateOrRemoveFilterEffectRenderer();
}
-void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
+void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
{
m_stackingNode->updateIsNormalFlowOnly();
+ m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle);
if (m_scrollableArea)
m_scrollableArea->updateAfterStyleChange(oldStyle);
- m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle);
- updateVisibilityAfterStyleChange(oldStyle);
+
// Overlay scrollbars can make this layer self-painting so we need
// to recompute the bit once scrollbars have been updated.
updateSelfPaintingLayer();
- updateOutOfFlowPositioned(oldStyle);
- updateReflectionInfo(oldStyle);
+ if (!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)) {
+ ASSERT(!oldStyle || diff.needsFullLayout());
+ updateReflectionInfo(oldStyle);
+ }
if (RuntimeEnabledFeatures::cssCompositingEnabled())
- updateBlendMode();
+ m_blendInfo.updateBlendMode();
updateDescendantDependentFlags();
- updateTransform();
-
- bool didPaintWithFilters = false;
-
- if (paintsWithFilters())
- didPaintWithFilters = true;
- updateFilters(oldStyle, renderer()->style());
-
- const RenderStyle* newStyle = renderer()->style();
- if (compositor()->updateLayerCompositingState(this)
- || needsCompositingLayersRebuiltForClip(oldStyle, newStyle)
- || needsCompositingLayersRebuiltForOverflow(oldStyle, newStyle)
- || needsCompositingLayersRebuiltForFilters(oldStyle, newStyle, didPaintWithFilters)
- || needsCompositingLayersRebuiltForBlending(oldStyle, newStyle)) {
- compositor()->setCompositingLayersNeedRebuild();
- } else if (compositingState() == PaintsIntoOwnBacking || compositingState() == HasOwnBackingButPaintsIntoAncestor) {
- ASSERT(hasCompositedLayerMapping());
- compositedLayerMapping()->updateGraphicsLayerGeometry();
- } else if (compositingState() == PaintsIntoGroupedBacking) {
- ASSERT(compositor()->layerSquashingEnabled());
- ASSERT(groupedMapping());
- // updateGraphicsLayerGeometry() is called to update the squashingLayer in case its size/position has changed.
- // FIXME: Make sure to create a layout test that covers this scenario.
- // FIXME: It is not expected that any other layers on the compositedLayerMapping would change. we should
- // be able to just update the squashing layer only and save a lot of computation.
- groupedMapping()->updateGraphicsLayerGeometry();
+
+ updateTransform(oldStyle, renderer()->style());
+
+ {
+ // https://code.google.com/p/chromium/issues/detail?id=343759
+ DisableCompositingQueryAsserts disabler;
+ updateFilters(oldStyle, renderer()->style());
}
+
+ compositor()->updateStyleDeterminedCompositingReasons(this);
+
+ setNeedsCompositingInputsUpdate();
+
+ // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues
+ // https://code.google.com/p/chromium/issues/detail?id=343756
+ DisableCompositingQueryAsserts disabler;
+
+ compositor()->updateLayerCompositingState(this, RenderLayerCompositor::UseChickenEggHacks);
}
bool RenderLayer::scrollsOverflow() const
@@ -4039,13 +3754,6 @@ bool RenderLayer::scrollsOverflow() const
return false;
}
-bool RenderLayer::isCSSCustomFilterEnabled() const
-{
- // We only want to enable shaders if WebGL is also enabled on this platform.
- const Settings* settings = renderer()->document().settings();
- return settings && RuntimeEnabledFeatures::cssCustomFilterEnabled() && settings->webGLEnabled();
-}
-
FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
{
const FilterOperations& filters = style->filter();
@@ -4057,48 +3765,19 @@ FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation);
// FIXME: Cache the ReferenceFilter if it didn't change.
RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create();
+#ifdef BLINK_SCALE_FILTERS_AT_RECORD_TIME
float zoom = style->effectiveZoom() * WebCore::deviceScaleFactor(renderer()->frame());
- referenceFilter->setFilterResolution(FloatSize(zoom, zoom));
+#else
+ float zoom = style->effectiveZoom();
+#endif
+ referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom));
referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(),
referenceOperation));
referenceOperation->setFilter(referenceFilter.release());
}
}
- if (!filters.hasCustomFilter())
- return filters;
-
- if (!isCSSCustomFilterEnabled()) {
- // CSS Custom filters should not parse at all in this case, but there might be
- // remaining styles that were parsed when the flag was enabled. Reproduces in DumpRenderTree
- // because it resets the flag while the previous test is still loaded.
- return FilterOperations();
- }
-
- FilterOperations outputFilters;
- for (size_t i = 0; i < filters.size(); ++i) {
- RefPtr<FilterOperation> filterOperation = filters.operations().at(i);
- if (filterOperation->type() == FilterOperation::CUSTOM) {
- // We have to wait until the program of CSS Shaders is loaded before setting it on the layer.
- // Note that we will handle the loading of the shaders and repainting of the layer in updateOrRemoveFilterClients.
- const CustomFilterOperation* customOperation = toCustomFilterOperation(filterOperation.get());
- RefPtr<CustomFilterProgram> program = customOperation->program();
- if (!program->isLoaded())
- continue;
-
- CustomFilterGlobalContext* globalContext = renderer()->view()->customFilterGlobalContext();
- RefPtr<CustomFilterValidatedProgram> validatedProgram = globalContext->getValidatedProgram(program->programInfo());
- if (!validatedProgram->isInitialized())
- continue;
-
- RefPtr<ValidatedCustomFilterOperation> validatedOperation = ValidatedCustomFilterOperation::create(validatedProgram.release(),
- customOperation->parameters(), customOperation->meshRows(), customOperation->meshColumns(), customOperation->meshType());
- outputFilters.operations().append(validatedOperation.release());
- continue;
- }
- outputFilters.operations().append(filterOperation.release());
- }
- return outputFilters;
+ return filters;
}
void RenderLayer::updateOrRemoveFilterClients()
@@ -4108,11 +3787,6 @@ void RenderLayer::updateOrRemoveFilterClients()
return;
}
- if (renderer()->style()->filter().hasCustomFilter())
- ensureFilterInfo()->updateCustomFilterClients(renderer()->style()->filter());
- else if (hasFilterInfo())
- filterInfo()->removeCustomFilterClients();
-
if (renderer()->style()->filter().hasReferenceFilter())
ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter());
else if (hasFilterInfo())
@@ -4128,7 +3802,7 @@ void RenderLayer::updateOrRemoveFilterEffectRenderer()
// 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);
+ filterInfo->setRenderer(nullptr);
return;
}
@@ -4136,7 +3810,6 @@ void RenderLayer::updateOrRemoveFilterEffectRenderer()
RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
if (!filterInfo->renderer()) {
RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
- filterRenderer->setIsAccelerated(renderer()->frame()->settings()->acceleratedFiltersEnabled());
filterInfo->setRenderer(filterRenderer.release());
// We can optimize away code paths in other places if we know that there are no software filters.
@@ -4146,43 +3819,71 @@ void RenderLayer::updateOrRemoveFilterEffectRenderer()
// 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(), computeFilterOperations(renderer()->style())))
- filterInfo->setRenderer(0);
+ filterInfo->setRenderer(nullptr);
}
void RenderLayer::filterNeedsRepaint()
{
- toElement(renderer()->node())->scheduleLayerUpdate();
- if (renderer()->view())
- renderer()->repaint();
+ {
+ DeprecatedScheduleStyleRecalcDuringLayout marker(renderer()->document().lifecycle());
+ // It's possible for scheduleSVGFilterLayerUpdateHack to schedule a style recalc, which
+ // is a problem because this function can be called while performing layout.
+ // Presumably this represents an illegal data flow of layout or compositing
+ // information into the style system.
+ toElement(renderer()->node())->scheduleSVGFilterLayerUpdateHack();
+ }
+
+ if (renderer()->view()) {
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && renderer()->frameView()->isInPerformLayout())
+ renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
+ else
+ renderer()->paintInvalidationForWholeRenderer();
+ }
}
void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const
{
+ computeSelfHitTestRects(rects);
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->addLayerHitTestRects(rects);
+}
+
+void RenderLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const
+{
if (!size().isEmpty()) {
Vector<LayoutRect> rect;
if (renderBox() && renderBox()->scrollsOverflow()) {
// For scrolling layers, rects are taken to be in the space of the contents.
- // We need to include both the entire contents, and also the bounding box
- // of the layer in the space of it's parent (eg. for border / scroll bars).
- rect.append(m_scrollableArea->overflowRect());
+ // We need to include the bounding box of the layer in the space of its parent
+ // (eg. for border / scroll bars) and if it's composited then the entire contents
+ // as well as they may be on another composited layer. Skip reporting contents
+ // for non-composited layers as they'll get projected to the same layer as the
+ // bounding box.
+ if (compositingState() != NotComposited)
+ rect.append(m_scrollableArea->overflowRect());
+
rects.set(this, rect);
if (const RenderLayer* parentLayer = parent()) {
LayerHitTestRects::iterator iter = rects.find(parentLayer);
- if (iter == rects.end())
- iter = rects.add(parentLayer, Vector<LayoutRect>()).iterator;
- iter->value.append(boundingBox(parentLayer));
+ if (iter == rects.end()) {
+ rects.add(parentLayer, Vector<LayoutRect>()).storedValue->value.append(physicalBoundingBox(parentLayer));
+ } else {
+ iter->value.append(physicalBoundingBox(parentLayer));
+ }
}
} else {
- rect.append(localBoundingBox());
+ rect.append(logicalBoundingBox());
rects.set(this, rect);
}
}
-
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->addLayerHitTestRects(rects);
}
+DisableCompositingQueryAsserts::DisableCompositingQueryAsserts()
+ : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { }
+
+COMPILE_ASSERT(1 << RenderLayer::ViewportConstrainedNotCompositedReasonBits >= RenderLayer::NumNotCompositedReasons, too_many_viewport_constrained_not_compositing_reasons);
+
} // namespace WebCore
#ifndef NDEBUG
@@ -4191,7 +3892,7 @@ void showLayerTree(const WebCore::RenderLayer* layer)
if (!layer)
return;
- if (WebCore::Frame* frame = layer->renderer()->frame()) {
+ if (WebCore::LocalFrame* frame = layer->renderer()->frame()) {
WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
fprintf(stderr, "%s\n", output.utf8().data());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.h
index 06dd644f8b7..6e43a0b7fe5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayer.h
@@ -45,11 +45,10 @@
#ifndef RenderLayer_h
#define RenderLayer_h
-#include "core/rendering/CompositedLayerMappingPtr.h"
-#include "core/rendering/CompositingReasons.h"
+#include "core/rendering/compositing/CompositedLayerMappingPtr.h"
#include "core/rendering/LayerPaintingInfo.h"
-#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderLayerBlendInfo.h"
#include "core/rendering/RenderLayerClipper.h"
#include "core/rendering/RenderLayerFilterInfo.h"
#include "core/rendering/RenderLayerReflectionInfo.h"
@@ -57,6 +56,7 @@
#include "core/rendering/RenderLayerScrollableArea.h"
#include "core/rendering/RenderLayerStackingNode.h"
#include "core/rendering/RenderLayerStackingNodeIterator.h"
+#include "platform/graphics/CompositingReasons.h"
#include "wtf/OwnPtr.h"
namespace WebCore {
@@ -66,29 +66,32 @@ class FilterOperations;
class HitTestRequest;
class HitTestResult;
class HitTestingTransformState;
-class PlatformEvent;
-class RenderFlowThread;
-class RenderGeometryMap;
class CompositedLayerMapping;
class RenderLayerCompositor;
-class RenderReplica;
-class RenderScrollbarPart;
class RenderStyle;
-class RenderView;
-class Scrollbar;
class TransformationMatrix;
enum BorderRadiusClippingRule { IncludeSelfForBorderRadius, DoNotIncludeSelfForBorderRadius };
+enum IncludeSelfOrNot { IncludeSelf, ExcludeSelf };
-class RenderLayer {
+enum CompositingQueryMode {
+ CompositingQueriesAreAllowed,
+ CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases
+};
+
+// FIXME: remove this once the compositing query ASSERTS are no longer hit.
+class DisableCompositingQueryAsserts {
+ WTF_MAKE_NONCOPYABLE(DisableCompositingQueryAsserts);
public:
- friend class RenderReplica;
- // FIXME: Needed until we move all the necessary bits to the new class.
- friend class RenderLayerStackingNode;
- // FIXME: Needed until we move all the necessary bits to the new class.
- friend class RenderLayerScrollableArea;
+ DisableCompositingQueryAsserts();
+private:
+ TemporaryChange<CompositingQueryMode> m_disabler;
+};
- RenderLayer(RenderLayerModelObject*);
+class RenderLayer {
+ WTF_MAKE_NONCOPYABLE(RenderLayer);
+public:
+ RenderLayer(RenderLayerModelObject*, LayerType);
~RenderLayer();
String debugName() const;
@@ -101,6 +104,8 @@ public:
RenderLayer* firstChild() const { return m_first; }
RenderLayer* lastChild() const { return m_last; }
+ const RenderLayer* compositingContainer() const;
+
void addChild(RenderLayer* newChild, RenderLayer* beforeChild = 0);
RenderLayer* removeChild(RenderLayer*);
@@ -111,11 +116,13 @@ public:
bool isSelfPaintingLayer() const { return m_isSelfPaintingLayer; }
+ void setLayerType(LayerType layerType) { m_layerType = layerType; }
+
bool cannotBlitToWindow() const;
- bool isTransparent() const;
+ bool isTransparent() const { return renderer()->isTransparent() || renderer()->hasMask(); }
RenderLayer* transparentPaintingAncestor();
- void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
+ void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior);
bool isReflection() const { return renderer()->isReplica(); }
RenderLayerReflectionInfo* reflectionInfo() { return m_reflectionInfo.get(); }
@@ -145,35 +152,34 @@ public:
// Allows updates of layer content without repainting.
void contentChanged(ContentChangeType);
- bool canRender3DTransforms() const;
-
enum UpdateLayerPositionsFlag {
CheckForRepaint = 1 << 0,
NeedsFullRepaintInBacking = 1 << 1,
- IsCompositingUpdateRoot = 1 << 2,
- UpdateCompositingLayers = 1 << 3,
- UpdatePagination = 1 << 4
+ UpdatePagination = 1 << 2,
+ ForceMayNeedPaintInvalidation = 1 << 3,
};
typedef unsigned UpdateLayerPositionsFlags;
- static const UpdateLayerPositionsFlags defaultFlags = CheckForRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers;
void updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags);
-
void updateLayerPositionsAfterOverflowScroll();
void updateLayerPositionsAfterDocumentScroll();
+ // FIXME: Should updateLayerPositions be private?
+ void updateLayerPositionRecursive(UpdateLayerPositionsFlags = CheckForRepaint);
+
bool isPaginated() const { return m_isPaginated; }
RenderLayer* enclosingPaginationLayer() const { return m_enclosingPaginationLayer; }
- void updateTransform();
-
- void updateBlendMode();
+ void updateTransformationMatrix();
+ RenderLayer* renderingContextRoot();
const LayoutSize& offsetForInFlowPosition() const { return m_offsetForInFlowPosition; }
+ void blockSelectionGapsBoundsChanged();
void addBlockSelectionGapsBounds(const LayoutRect&);
void clearBlockSelectionGapsBounds();
void repaintBlockSelectionGaps();
+ IntRect blockSelectionGapsBounds() const;
bool hasBlockSelectionGapBounds() const;
RenderLayerStackingNode* stackingNode() { return m_stackingNode.get(); }
@@ -200,46 +206,30 @@ public:
// Part of the issue is with subtree relayout: we don't check if our ancestors have some descendant flags dirty, missing some updates.
bool hasSelfPaintingLayerDescendant() const { return m_hasSelfPaintingLayerDescendant; }
- // FIXME: We should ASSERT(!m_hasOutOfFlowPositionedDescendantDirty) here. See above.
- bool hasOutOfFlowPositionedDescendant() const { return m_hasOutOfFlowPositionedDescendant; }
-
- void setHasOutOfFlowPositionedDescendant(bool hasDescendant) { m_hasOutOfFlowPositionedDescendant = hasDescendant; }
- void setHasOutOfFlowPositionedDescendantDirty(bool dirty) { m_hasOutOfFlowPositionedDescendantDirty = dirty; }
-
- bool childLayerHasBlendMode() const { ASSERT(!m_childLayerHasBlendModeStatusDirty); return m_childLayerHasBlendMode; }
-
- bool hasUnclippedDescendant() const { return m_hasUnclippedDescendant; }
- void setHasUnclippedDescendant(bool hasDescendant) { m_hasUnclippedDescendant = hasDescendant; }
- void updateHasUnclippedDescendant();
- bool isUnclippedDescendant() const { return m_isUnclippedDescendant; }
-
+ // Will ensure that hasNonCompositiedChild are up to date.
+ void updateScrollingStateAfterCompositingChange();
bool hasVisibleNonLayerContent() const { return m_hasVisibleNonLayerContent; }
- void updateHasVisibleNonLayerContent();
+ bool hasNonCompositedChild() const { ASSERT(isAllowedToQueryCompositingState()); return m_hasNonCompositedChild; }
+
+ bool usedTransparency() const { return m_usedTransparency; }
// Gets the nearest enclosing positioned ancestor layer (also includes
// the <html> layer and the root layer).
RenderLayer* enclosingPositionedAncestor() const;
- // Returns the nearest enclosing layer that is scrollable.
- RenderLayer* enclosingScrollableLayer() const;
-
- // The layer relative to which clipping rects for this layer are computed.
- RenderLayer* clippingRootForPainting() const;
+ RenderLayer* enclosingOverflowClipLayer(IncludeSelfOrNot = IncludeSelf) const;
+ bool isRepaintContainer() const;
// Enclosing compositing layer; if includeSelf is true, may return this.
- RenderLayer* enclosingCompositingLayer(bool includeSelf = true) const;
- RenderLayer* enclosingCompositingLayerForRepaint(bool includeSelf = true) const;
+ RenderLayer* enclosingCompositingLayer(IncludeSelfOrNot = IncludeSelf) const;
+ RenderLayer* enclosingCompositingLayerForRepaint(IncludeSelfOrNot = IncludeSelf) const;
// Ancestor compositing layer, excluding this.
- RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(false); }
-
- // Ancestor composited scrolling layer at or above our containing block.
- RenderLayer* ancestorCompositedScrollingLayer() const;
+ RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(ExcludeSelf); }
// Ancestor scrolling layer at or above our containing block.
RenderLayer* ancestorScrollingLayer() const;
- RenderLayer* enclosingFilterLayer(bool includeSelf = true) const;
- RenderLayer* enclosingFilterRepaintLayer() const;
+ RenderLayer* enclosingFilterLayer(IncludeSelfOrNot = IncludeSelf) const;
bool hasAncestorWithFilterOutsets() const;
bool canUseConvertToLayerCoords() const
@@ -248,8 +238,6 @@ public:
return !renderer()->hasColumns() && !renderer()->hasTransform() && !renderer()->isSVGRoot();
}
- void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& location) const;
- void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect&) const;
void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const;
void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect&) const;
@@ -257,58 +245,31 @@ public:
// paints the layers that intersect the damage rect from back to
// front. The hitTest method looks for mouse events by walking
// layers that intersect the point from front to back.
- void paint(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior = PaintBehaviorNormal, RenderObject* paintingRoot = 0,
- RenderRegion* = 0, PaintLayerFlags = 0);
+ // paint() assumes that the caller will clip to the bounds of damageRect if necessary.
+ void paint(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior = PaintBehaviorNormal, RenderObject* paintingRoot = 0, PaintLayerFlags = 0);
bool hitTest(const HitTestRequest&, HitTestResult&);
bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior, RenderObject* paintingRoot = 0);
- // This method figures out our layerBounds in coordinates relative to
- // |rootLayer}. It also computes our background and foreground clip rects
- // for painting/event handling.
- // Pass offsetFromRoot if known.
- void calculateRects(const ClipRectsContext&, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
- ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot = 0) const;
-
- 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.
-
// Pass offsetFromRoot if known.
bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0) const;
- enum CalculateLayerBoundsFlag {
- IncludeSelfTransform = 1 << 0,
- UseLocalClipRectIfPossible = 1 << 1,
- IncludeLayerFilterOutsets = 1 << 2,
- ExcludeHiddenDescendants = 1 << 3,
- DontConstrainForMask = 1 << 4,
- IncludeCompositedDescendants = 1 << 5,
- UseFragmentBoxes = 1 << 6,
- PretendLayerHasOwnBacking = 1 << 7,
- DefaultCalculateLayerBoundsFlags = IncludeSelfTransform | UseLocalClipRectIfPossible | IncludeLayerFilterOutsets | UseFragmentBoxes
- };
- typedef unsigned CalculateLayerBoundsFlags;
-
// Bounding box relative to some ancestor layer. Pass offsetFromRoot if known.
- LayoutRect boundingBox(const RenderLayer* rootLayer, CalculateLayerBoundsFlags = 0, const LayoutPoint* offsetFromRoot = 0) const;
- // Bounding box in the coordinates of this layer.
- LayoutRect localBoundingBox(CalculateLayerBoundsFlags = 0) const;
- // Pixel snapped bounding box relative to the root.
- IntRect absoluteBoundingBox() const;
+ LayoutRect physicalBoundingBox(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot = 0) const;
+ LayoutRect physicalBoundingBoxIncludingReflectionAndStackingChildren(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const;
- // Bounds used for layer overlap testing in RenderLayerCompositor.
- LayoutRect overlapBounds() const { return overlapBoundsIncludeChildren() ? calculateLayerBounds(this) : localBoundingBox(); }
+ // FIXME: This function is inconsistent as to whether the returned rect has been flipped for writing mode.
+ LayoutRect boundingBoxForCompositingOverlapTest() const { return overlapBoundsIncludeChildren() ? boundingBoxForCompositing() : logicalBoundingBox(); }
// If true, this layer's children are included in its bounds for overlap testing.
// We can't rely on the children's positions if this layer has a filter that could have moved the children's pixels around.
bool overlapBoundsIncludeChildren() const { return hasFilter() && renderer()->style()->filter().hasFilterThatMovesPixels(); }
- // Can pass offsetFromRoot if known.
- IntRect calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot = 0, CalculateLayerBoundsFlags = DefaultCalculateLayerBoundsFlags) const;
-
- // WARNING: This method returns the offset for the parent as this is what updateLayerPositions expects.
- LayoutPoint computeOffsetFromRoot(bool& hasLayerOffset) const;
+ enum CalculateBoundsOptions {
+ ApplyBoundsChickenEggHacks,
+ DoNotApplyBoundsChickenEggHacks,
+ };
+ LayoutRect boundingBoxForCompositing(const RenderLayer* ancestorLayer = 0, CalculateBoundsOptions = DoNotApplyBoundsChickenEggHacks) const;
LayoutUnit staticInlinePosition() const { return m_staticInlinePosition; }
LayoutUnit staticBlockPosition() const { return m_staticBlockPosition; }
@@ -316,6 +277,9 @@ public:
void setStaticInlinePosition(LayoutUnit position) { m_staticInlinePosition = position; }
void setStaticBlockPosition(LayoutUnit position) { m_staticBlockPosition = position; }
+ LayoutSize subpixelAccumulation() const;
+ void setSubpixelAccumulation(const LayoutSize&);
+
bool hasTransform() const { return renderer()->hasTransform(); }
// Note that this transform has the transform-origin baked in.
TransformationMatrix* transform() const { return m_transform.get(); }
@@ -333,11 +297,13 @@ public:
bool preserves3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; }
bool has3DTransform() const { return m_transform && !m_transform->isAffine(); }
+ // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
+ bool shouldPreserve3D() const { return !renderer()->hasReflection() && renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; }
+
void filterNeedsRepaint();
bool hasFilter() const { return renderer()->hasFilter(); }
- bool hasBlendMode() const;
- bool paintsWithBlendMode() const { return hasBlendMode() && compositingState() != PaintsIntoOwnBacking; }
+ bool paintsWithBlendMode() const;
void* operator new(size_t);
// Only safe to call from RenderLayerModelObject::destroyLayer()
@@ -345,7 +311,11 @@ public:
CompositingState compositingState() const;
- CompositedLayerMappingPtr compositedLayerMapping() const { return m_compositedLayerMapping.get(); }
+ // This returns true if our document is in a phase of its lifestyle during which
+ // compositing state may legally be read.
+ bool isAllowedToQueryCompositingState() const;
+
+ CompositedLayerMappingPtr compositedLayerMapping() const;
CompositedLayerMappingPtr ensureCompositedLayerMapping();
// NOTE: If you are using hasCompositedLayerMapping to determine the state of compositing for this layer,
@@ -355,7 +325,7 @@ public:
void clearCompositedLayerMapping(bool layerBeingDestroyed = false);
CompositedLayerMapping* groupedMapping() const { return m_groupedMapping; }
- void setGroupedMapping(CompositedLayerMapping* groupedMapping) { m_groupedMapping = groupedMapping; }
+ void setGroupedMapping(CompositedLayerMapping* groupedMapping, bool layerBeingDestroyed = false);
bool hasCompositedMask() const;
bool hasCompositedClippingMask() const;
@@ -366,10 +336,16 @@ public:
RenderLayer* scrollParent() const;
RenderLayer* clipParent() const;
- bool needsCompositingLayersRebuiltForClip(const RenderStyle* oldStyle, const RenderStyle* newStyle) const;
- bool needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const;
- bool needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const;
- bool needsCompositingLayersRebuiltForBlending(const RenderStyle* oldStyle, const RenderStyle* newStyle) const;
+ // Computes the position of the given render object in the space of |repaintContainer|.
+ // FIXME: invert the logic to have repaint containers take care of painting objects into them, rather than the reverse.
+ // This will allow us to clean up this static method messiness.
+ static LayoutPoint positionFromPaintInvalidationContainer(const RenderObject*, const RenderLayerModelObject* repaintContainer);
+
+ // Adjusts the given rect (in the coordinate space of the RenderObject) to the coordinate space of |repaintContainer|'s GraphicsLayer backing.
+ static void mapRectToRepaintBacking(const RenderObject*, const RenderLayerModelObject* repaintContainer, LayoutRect&);
+
+ // Computes the bounding repaint rect for |renderObject|, in the coordinate space of |repaintContainer|'s GraphicsLayer backing.
+ static LayoutRect computeRepaintRect(const RenderObject*, const RenderLayer* repaintContainer);
bool paintsWithTransparency(PaintBehavior paintBehavior) const
{
@@ -385,8 +361,6 @@ public:
bool containsDirtyOverlayScrollbars() const { return m_containsDirtyOverlayScrollbars; }
void setContainsDirtyOverlayScrollbars(bool dirtyScrollbars) { m_containsDirtyOverlayScrollbars = dirtyScrollbars; }
- bool isCSSCustomFilterEnabled() const;
-
FilterOperations computeFilterOperations(const RenderStyle*);
bool paintsWithFilters() const;
bool requiresFullLayerImageForFilters() const;
@@ -412,29 +386,36 @@ public:
Node* enclosingElement() const;
bool isInTopLayer() const;
- bool isInTopLayerSubtree() const;
enum ViewportConstrainedNotCompositedReason {
- NoNotCompositedReason,
+ NoNotCompositedReason = 0,
NotCompositedForBoundsOutOfView,
NotCompositedForNonViewContainer,
NotCompositedForNoVisibleContent,
NotCompositedForUnscrollableAncestors,
- };
+ NumNotCompositedReasons,
- void setViewportConstrainedNotCompositedReason(ViewportConstrainedNotCompositedReason reason) { m_compositingProperties.viewportConstrainedNotCompositedReason = reason; }
- ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason() const { return static_cast<ViewportConstrainedNotCompositedReason>(m_compositingProperties.viewportConstrainedNotCompositedReason); }
+ // This is the number of bits used to store the viewport constrained not composited
+ // reasons. We define this constant since sizeof won't return the number of bits, and we
+ // shouldn't duplicate the constant.
+ ViewportConstrainedNotCompositedReasonBits = 3
+ };
- bool isOutOfFlowRenderFlowThread() const { return renderer()->isOutOfFlowRenderFlowThread(); }
+ void setViewportConstrainedNotCompositedReason(ViewportConstrainedNotCompositedReason reason) { m_viewportConstrainedNotCompositedReason = reason; }
+ ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason() const { ASSERT(isAllowedToQueryCompositingState()); return static_cast<ViewportConstrainedNotCompositedReason>(m_viewportConstrainedNotCompositedReason); }
bool scrollsWithRespectTo(const RenderLayer*) const;
void addLayerHitTestRects(LayerHitTestRects&) const;
+ // Compute rects only for this layer
+ void computeSelfHitTestRects(LayerHitTestRects&) const;
+
// FIXME: This should probably return a ScrollableArea but a lot of internal methods are mistakenly exposed.
RenderLayerScrollableArea* scrollableArea() const { return m_scrollableArea.get(); }
RenderLayerRepainter& repainter() { return m_repainter; }
RenderLayerClipper& clipper() { return m_clipper; }
+ const RenderLayerClipper& clipper() const { return m_clipper; }
inline bool isPositionedContainer() const
{
@@ -445,45 +426,87 @@ public:
return isRootLayer() || layerRenderer->isPositioned() || hasTransform();
}
+ // paintLayer() assumes that the caller will clip to the bounds of the painting dirty if necessary.
void paintLayer(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
PassOwnPtr<Vector<FloatRect> > collectTrackedRepaintRects() const;
- void setOffsetFromSquashingLayerOrigin(IntSize offset) { m_compositingProperties.offsetFromSquashingLayerOrigin = offset; }
- IntSize offsetFromSquashingLayerOrigin() const { return m_compositingProperties.offsetFromSquashingLayerOrigin; }
+ RenderLayerBlendInfo& blendInfo() { return m_blendInfo; }
-private:
- bool hasOverflowControls() const;
+ void setOffsetFromSquashingLayerOrigin(IntSize offset) { m_offsetFromSquashingLayerOrigin = offset; }
+ IntSize offsetFromSquashingLayerOrigin() const { ASSERT(isAllowedToQueryCompositingState()); return m_offsetFromSquashingLayerOrigin; }
- void setIsUnclippedDescendant(bool isUnclippedDescendant) { m_isUnclippedDescendant = isUnclippedDescendant; }
+ bool scrollsOverflow() const;
- void setAncestorChainHasSelfPaintingLayerDescendant();
- void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+ CompositingReasons styleDeterminedCompositingReasons() const { return m_styleDeterminedCompositingReasons; }
+ void setStyleDeterminedCompositingReasons(CompositingReasons reasons) { ASSERT(reasons == (reasons & CompositingReasonComboAllStyleDeterminedReasons)); m_styleDeterminedCompositingReasons = reasons; }
- void setAncestorChainHasOutOfFlowPositionedDescendant();
- void dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+ class CompositingInputs {
+ public:
+ CompositingInputs()
+ : opacityAncestor(0)
+ , transformAncestor(0)
+ , filterAncestor(0)
+ , isUnclippedDescendant(false)
+ { }
- bool acceleratedCompositingForOverflowScrollEnabled() const;
- // FIXME: This is a temporary flag and should be removed once accelerated
- // overflow scroll is ready (crbug.com/254111).
- bool compositorDrivenAcceleratedScrollingEnabled() const;
+ IntRect clippedAbsoluteBoundingBox;
+ const RenderLayer* opacityAncestor;
+ const RenderLayer* transformAncestor;
+ const RenderLayer* filterAncestor;
+ unsigned isUnclippedDescendant : 1;
+ };
- void clipToRect(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&,
- BorderRadiusClippingRule = IncludeSelfForBorderRadius);
- void restoreClip(GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&);
+ void setNeedsCompositingInputsUpdate();
+ bool childNeedsCompositingInputsUpdate() const { return m_childNeedsCompositingInputsUpdate; }
+ bool needsCompositingInputsUpdate() const { return m_needsCompositingInputsUpdate; }
+
+ void updateCompositingInputs(const CompositingInputs&);
+ void clearChildNeedsCompositingInputsUpdate();
+
+ const CompositingInputs& compositingInputs() const { ASSERT(!m_needsCompositingInputsUpdate); return m_compositingInputs; }
+
+ bool lostGroupedMapping() const { ASSERT(isAllowedToQueryCompositingState()); return m_lostGroupedMapping; }
+ void setLostGroupedMapping(bool b) { m_lostGroupedMapping = b; }
+
+ CompositingReasons compositingReasons() const { ASSERT(isAllowedToQueryCompositingState()); return m_compositingReasons; }
+ void setCompositingReasons(CompositingReasons, CompositingReasons mask = CompositingReasonAll);
+
+ bool hasCompositingDescendant() const { ASSERT(isAllowedToQueryCompositingState()); return m_hasCompositingDescendant; }
+ void setHasCompositingDescendant(bool);
+
+ bool shouldIsolateCompositedDescendants() const { ASSERT(isAllowedToQueryCompositingState()); return m_shouldIsolateCompositedDescendants; }
+ void setShouldIsolateCompositedDescendants(bool);
+
+ void updateDescendantDependentFlags();
+
+ void updateOrRemoveFilterEffectRenderer();
void updateSelfPaintingLayer();
- void updateVisibilityAfterStyleChange(const RenderStyle* oldStyle);
- void updateOutOfFlowPositioned(const RenderStyle* oldStyle);
+ // paintLayerContents() assumes that the caller will clip to the bounds of the painting dirty rect if necessary.
+ void paintLayerContents(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+
+ RenderLayer* enclosingTransformedAncestor() const;
+ LayoutPoint computeOffsetFromTransformedAncestor() const;
void didUpdateNeedsCompositedScrolling();
+private:
+ // Bounding box in the coordinates of this layer.
+ LayoutRect logicalBoundingBox() const;
+
+ bool hasOverflowControls() const;
+
+ void setAncestorChainHasSelfPaintingLayerDescendant();
+ void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+
+ void clipToRect(const LayerPaintingInfo&, GraphicsContext*, const ClipRect&, PaintLayerFlags, BorderRadiusClippingRule = IncludeSelfForBorderRadius);
+ void restoreClip(GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&);
+
// Returns true if the position changed.
bool updateLayerPosition();
- void updateLayerPositions(RenderGeometryMap* = 0, UpdateLayerPositionsFlags = defaultFlags);
-
enum UpdateLayerPositionsAfterScrollFlag {
NoFlag = 0,
IsOverflowScroll = 1 << 0,
@@ -492,11 +515,10 @@ private:
HasChangedAncestor = 1 << 3
};
typedef unsigned UpdateLayerPositionsAfterScrollFlags;
- void updateLayerPositionsAfterScroll(RenderGeometryMap*, UpdateLayerPositionsAfterScrollFlags = NoFlag);
+ void updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags = NoFlag);
void setNextSibling(RenderLayer* next) { m_next = next; }
void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
- void setParent(RenderLayer* parent);
void setFirstChild(RenderLayer* first) { m_first = first; }
void setLastChild(RenderLayer* last) { m_last = last; }
@@ -504,25 +526,30 @@ private:
void paintLayerContentsAndReflection(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
void paintLayerByApplyingTransform(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags, const LayoutPoint& translationOffset = LayoutPoint());
- void paintLayerContents(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+
+ // Returns whether this layer should be painted during sofware painting (i.e., not via calls from CompositedLayerMapping to draw into composited
+ // layers).
+ bool shouldPaintLayerInSoftwareMode(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags paintFlags);
+
void paintChildren(unsigned childrenToVisit, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
void paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
void paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
- void collectFragments(LayerFragments&, const RenderLayer* rootLayer, RenderRegion*, const LayoutRect& dirtyRect,
+ void collectFragments(LayerFragments&, const RenderLayer* rootLayer, const LayoutRect& dirtyRect,
ClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize,
- ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0, const LayoutRect* layerBoundingBox = 0);
+ ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0,
+ const LayoutSize& subPixelAccumulation = LayoutSize(), const LayoutRect* layerBoundingBox = 0);
void updatePaintingInfoForFragments(LayerFragments&, const LayerPaintingInfo&, PaintLayerFlags, bool shouldPaintContent, const LayoutPoint* offsetFromRoot);
void paintBackgroundForFragments(const LayerFragments&, GraphicsContext*, GraphicsContext* transparencyLayerContext,
- const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
+ const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags);
void paintForegroundForFragments(const LayerFragments&, GraphicsContext*, GraphicsContext* transparencyLayerContext,
const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer,
- bool selectionOnly, bool forceBlackText);
- void paintForegroundForFragmentsWithPhase(PaintPhase, const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
- void paintOutlineForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
- void paintOverflowControlsForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&);
- void paintMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer);
- void paintChildClippingMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer);
+ bool selectionOnly, bool forceBlackText, PaintLayerFlags);
+ void paintForegroundForFragmentsWithPhase(PaintPhase, const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags);
+ void paintOutlineForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags);
+ void paintOverflowControlsForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+ void paintMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer, PaintLayerFlags);
+ void paintChildClippingMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer, PaintLayerFlags);
void paintTransformedLayerIntoFragments(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
@@ -557,7 +584,6 @@ private:
bool shouldBeSelfPaintingLayer() const;
-private:
// FIXME: We should only create the stacking node if needed.
bool requiresStackingNode() const { return true; }
void updateStackingNode();
@@ -569,58 +595,29 @@ private:
bool requiresScrollableArea() const { return renderBox(); }
void updateScrollableArea();
- // Returns true our scrollable area is in the FrameView's collection of scrollable areas. This can
- // only happen if we're both scrollable, and we do in fact overflow.
- bool scrollsOverflow() const;
-
void dirtyAncestorChainVisibleDescendantStatus();
void setAncestorChainHasVisibleDescendant();
- void dirtyAncestorChainBlendedDescendantStatus();
- void setAncestorChainBlendedDescendant();
-
- void updateDescendantDependentFlags();
-
- // This flag is computed by RenderLayerCompositor, which knows more about 3d hierarchies than we do.
- void setHas3DTransformedDescendant(bool b) { m_has3DTransformedDescendant = b; }
- bool has3DTransformedDescendant() const { return m_has3DTransformedDescendant; }
+ void updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle);
void dirty3DTransformedDescendantStatus();
// Both updates the status, and returns true if descendants of this have 3d.
bool update3DTransformedDescendantStatus();
void updateOrRemoveFilterClients();
- void updateOrRemoveFilterEffectRenderer();
-
- void parentClipRects(const ClipRectsContext&, ClipRects&) const;
- ClipRect backgroundClipRect(const ClipRectsContext&) const;
- LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
-
- RenderLayer* enclosingTransformedAncestor() const;
+ LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior);
void updatePagination();
// FIXME: Temporary. Remove when new columns come online.
bool useRegionBasedColumns() const;
- bool hasCompositingDescendant() const { return m_compositingProperties.hasCompositingDescendant; }
- void setHasCompositingDescendant(bool b) { m_compositingProperties.hasCompositingDescendant = b; }
-
- bool hasNonCompositedChild() const { return m_compositingProperties.hasNonCompositedChild; }
- void setHasNonCompositedChild(bool b) { m_compositingProperties.hasNonCompositedChild = b; }
-
- bool shouldIsolateCompositedDescendants() const { return m_compositingProperties.shouldIsolateCompositedDescendants; }
- void setShouldIsolateCompositedDescendants(bool b) { m_compositingProperties.shouldIsolateCompositedDescendants = b; }
-
- void setCompositingReasons(CompositingReasons reasons) { m_compositingProperties.compositingReasons = reasons; }
- CompositingReasons compositingReasons() const { return m_compositingProperties.compositingReasons; }
+ LayerType m_layerType;
- friend class CompositedLayerMapping;
- friend class RenderLayerCompositor;
- friend class RenderLayerModelObject;
-
-protected:
+ // Self-painting layer is an optimization where we avoid the heavy RenderLayer painting
+ // machinery for a RenderLayer allocated only to handle the overflow clip case.
+ // FIXME(crbug.com/332791): Self-painting layer should be merged into the overflow-only concept.
unsigned m_isSelfPaintingLayer : 1;
// If have no self-painting descendants, we don't have to walk our children during painting. This can lead to
@@ -628,26 +625,12 @@ protected:
unsigned m_hasSelfPaintingLayerDescendant : 1;
unsigned m_hasSelfPaintingLayerDescendantDirty : 1;
- unsigned m_hasOutOfFlowPositionedDescendant : 1;
- unsigned m_hasOutOfFlowPositionedDescendantDirty : 1;
-
- // This is true if we have an out-of-flow positioned descendant whose
- // containing block is our ancestor. If this is the case, the descendant
- // may fall outside of our clip preventing things like opting into
- // composited scrolling (which causes clipping of all descendants).
- unsigned m_hasUnclippedDescendant : 1;
-
- unsigned m_isUnclippedDescendant : 1;
-
const unsigned m_isRootLayer : 1;
unsigned m_usedTransparency : 1; // Tracks whether we need to close a transparent layer, i.e., whether
// we ended up painting this layer or any descendants (and therefore need to
// blend).
- unsigned m_childLayerHasBlendMode : 1;
- unsigned m_childLayerHasBlendModeStatusDirty : 1;
-
unsigned m_visibleContentStatusDirty : 1;
unsigned m_hasVisibleContent : 1;
unsigned m_visibleDescendantStatusDirty : 1;
@@ -670,8 +653,25 @@ protected:
const unsigned m_canSkipRepaintRectsUpdateOnScroll : 1;
unsigned m_hasFilterInfo : 1;
+ unsigned m_needsCompositingInputsUpdate : 1;
+ unsigned m_childNeedsCompositingInputsUpdate : 1;
+
+ // Used only while determining what layers should be composited. Applies to the tree of z-order lists.
+ unsigned m_hasCompositingDescendant : 1;
- blink::WebBlendMode m_blendMode;
+ // Applies to the real render layer tree (i.e., the tree determined by the layer's parent and children and
+ // as opposed to the tree formed by the z-order and normal flow lists).
+ unsigned m_hasNonCompositedChild : 1;
+
+ // Should be for stacking contexts having unisolated blending descendants.
+ unsigned m_shouldIsolateCompositedDescendants : 1;
+
+ // True if this render layer just lost its grouped mapping due to the CompositedLayerMapping being destroyed,
+ // and we don't yet know to what graphics layer this RenderLayer will be assigned.
+ unsigned m_lostGroupedMapping : 1;
+
+ // The reason, if any exists, that a fixed-position layer is chosen not to be composited.
+ unsigned m_viewportConstrainedNotCompositedReason : ViewportConstrainedNotCompositedReasonBits;
RenderLayerModelObject* m_renderer;
@@ -699,46 +699,17 @@ protected:
// Pointer to the enclosing RenderLayer that caused us to be paginated. It is 0 if we are not paginated.
RenderLayer* m_enclosingPaginationLayer;
- // Properties that are computed while updating compositing layers. These values may be dirty/invalid if
- // compositing status is not up-to-date before using them.
- struct CompositingProperties {
- CompositingProperties()
- : hasCompositingDescendant(false)
- , hasNonCompositedChild(false)
- , shouldIsolateCompositedDescendants(false)
- , viewportConstrainedNotCompositedReason(NoNotCompositedReason)
- , compositingReasons(CompositingReasonNone)
- { }
+ // These compositing reasons are updated whenever style changes, not while updating compositing layers.
+ // They should not be used to infer the compositing state of this layer.
+ CompositingReasons m_styleDeterminedCompositingReasons;
- // Used only while determining what layers should be composited. Applies to the tree of z-order lists.
- bool hasCompositingDescendant : 1;
+ // Once computed, indicates all that a layer needs to become composited using the CompositingReasons enum bitfield.
+ CompositingReasons m_compositingReasons;
- // Applies to the real render layer tree (i.e., the tree determined by the layer's parent and children and
- // as opposed to the tree formed by the z-order and normal flow lists).
- bool hasNonCompositedChild : 1;
+ // Used for invalidating this layer's contents on the squashing GraphicsLayer.
+ IntSize m_offsetFromSquashingLayerOrigin;
- // Should be for stacking contexts having unisolated blending descendants.
- bool shouldIsolateCompositedDescendants : 1;
-
- // The reason, if any exists, that a fixed-position layer is chosen not to be composited.
- unsigned viewportConstrainedNotCompositedReason : 2;
-
- // Once computed, indicates all that a layer needs to become composited using the CompositingReasons enum bitfield.
- CompositingReasons compositingReasons;
-
- // Used for invalidating this layer's contents on the squashing GraphicsLayer.
- IntSize offsetFromSquashingLayerOrigin;
- };
-
- CompositingProperties m_compositingProperties;
-
-private:
- enum CompositedScrollingHistogramBuckets {
- IsScrollableAreaBucket = 0,
- NeedsToBeStackingContainerBucket = 1,
- WillUseCompositedScrollingBucket = 2,
- CompositedScrollingHistogramMax = 3
- };
+ CompositingInputs m_compositingInputs;
IntRect m_blockSelectionGapsBounds;
@@ -751,6 +722,9 @@ private:
RenderLayerClipper m_clipper; // FIXME: Lazily allocate?
OwnPtr<RenderLayerStackingNode> m_stackingNode;
OwnPtr<RenderLayerReflectionInfo> m_reflectionInfo;
+ RenderLayerBlendInfo m_blendInfo;
+
+ LayoutSize m_subpixelAccumulation; // The accumulated subpixel offset of a composited layer's composited bounds compared to absolute coordinates.
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.cpp
new file mode 100644
index 00000000000..d8158b4cc40
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "core/rendering/RenderLayerBlendInfo.h"
+
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerModelObject.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+
+namespace WebCore {
+
+RenderLayerBlendInfo::RenderLayerBlendInfo(RenderLayerModelObject& renderer)
+ : m_renderer(renderer)
+ , m_blendMode(blink::WebBlendModeNormal)
+ , m_childLayerHasBlendMode(false)
+ , m_childLayerHasBlendModeStatusDirty(false)
+{
+}
+
+bool RenderLayerBlendInfo::hasBlendMode() const
+{
+ return RuntimeEnabledFeatures::cssCompositingEnabled() && m_renderer.hasBlendMode();
+}
+
+void RenderLayerBlendInfo::updateBlendMode()
+{
+ if (!RuntimeEnabledFeatures::cssCompositingEnabled())
+ return;
+
+ blink::WebBlendMode newBlendMode = m_renderer.style()->blendMode();
+ if (newBlendMode == m_blendMode)
+ return;
+
+ bool hadBlendMode = m_blendMode != blink::WebBlendModeNormal;
+ m_blendMode = newBlendMode;
+
+ RenderLayer* layer = m_renderer.layer();
+ // Only update the flag if a blend mode is set or unset.
+ if (layer->parent() && (!hadBlendMode || !hasBlendMode()))
+ layer->parent()->blendInfo().dirtyAncestorChainBlendedDescendantStatus();
+
+ if (layer->hasCompositedLayerMapping())
+ layer->compositedLayerMapping()->setBlendMode(newBlendMode);
+}
+
+void RenderLayerBlendInfo::dirtyAncestorChainBlendedDescendantStatus()
+{
+ for (RenderLayer* layer = m_renderer.layer(); layer; layer = layer->parent()) {
+ if (layer->blendInfo().childLayerHasBlendModeStatusDirty())
+ break;
+
+ layer->blendInfo().setChildLayerHasBlendModeStatusDirty(true);
+
+ if (layer->stackingNode()->isStackingContext())
+ break;
+ }
+}
+
+void RenderLayerBlendInfo::setAncestorChainBlendedDescendant()
+{
+ for (RenderLayer* layer = m_renderer.layer(); layer; layer = layer->parent()) {
+ if (!layer->blendInfo().childLayerHasBlendModeStatusDirty() && layer->blendInfo().childLayerHasBlendMode())
+ break;
+
+ layer->blendInfo().setChildLayerHasBlendMode(true);
+ layer->blendInfo().setChildLayerHasBlendModeStatusDirty(false);
+
+ if (layer->stackingNode()->isStackingContext())
+ break;
+ }
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.h
new file mode 100644
index 00000000000..6800baa6eef
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerBlendInfo.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef RenderLayerBlendInfo_h
+#define RenderLayerBlendInfo_h
+
+#include "public/platform/WebBlendMode.h"
+#include "wtf/Assertions.h"
+#include "wtf/Noncopyable.h"
+
+namespace WebCore {
+
+class RenderLayerModelObject;
+
+class RenderLayerBlendInfo {
+ WTF_MAKE_NONCOPYABLE(RenderLayerBlendInfo);
+public:
+ explicit RenderLayerBlendInfo(RenderLayerModelObject&);
+
+ bool hasBlendMode() const;
+ void updateBlendMode();
+
+ bool childLayerHasBlendMode() const
+ {
+ ASSERT(!m_childLayerHasBlendModeStatusDirty);
+ return m_childLayerHasBlendMode;
+ }
+ bool childLayerHasBlendModeWhileDirty() const { return m_childLayerHasBlendMode; }
+
+ void setChildLayerHasBlendMode(bool b) { m_childLayerHasBlendMode = b; }
+
+ bool childLayerHasBlendModeStatusDirty() const { return m_childLayerHasBlendModeStatusDirty; }
+ void setChildLayerHasBlendModeStatusDirty(bool b) { m_childLayerHasBlendModeStatusDirty = b; }
+
+ void setAncestorChainBlendedDescendant();
+ void dirtyAncestorChainBlendedDescendantStatus();
+
+ blink::WebBlendMode blendMode() const { return m_blendMode; }
+
+private:
+ RenderLayerModelObject& m_renderer;
+ blink::WebBlendMode m_blendMode;
+
+ unsigned m_childLayerHasBlendMode : 1;
+ unsigned m_childLayerHasBlendModeStatusDirty : 1;
+};
+
+} // namespace WebCore
+
+#endif // RenderLayerBlendInfo_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.cpp
index f14aa06ee27..786a17f7440 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.cpp
@@ -53,9 +53,12 @@ void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContex
{
ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
ASSERT(clipRectsType < NumCachedClipRectsTypes);
- if (m_clipRectsCache && m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip)) {
- // FIXME: these asserts trigger for squashing. Need to update this code to support squashing as appropriate.
- ASSERT(clipRectsContext.rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
+ if (m_clipRectsCache
+ && clipRectsContext.rootLayer == m_clipRectsCache->clipRectsRoot(clipRectsType)
+ && m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip)) {
+ // FIXME: We used to ASSERT that we always got a consistent root layer.
+ // We should add a test that has an inconsistent root. See
+ // http://crbug.com/366118 for an example.
ASSERT(m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] == clipRectsContext.overlayScrollbarSizeRelevancy);
#ifdef CHECK_CACHED_CLIP_RECTS
@@ -71,7 +74,7 @@ void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContex
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
- RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0;
+ RenderLayer* parentLayer = !isClippingRootForContext(clipRectsContext) ? m_renderer.layer()->parent() : 0;
if (parentLayer)
parentLayer->clipper().updateClipRects(clipRectsContext);
@@ -82,12 +85,11 @@ void RenderLayerClipper::updateClipRects(const ClipRectsContext& clipRectsContex
m_clipRectsCache = adoptPtr(new ClipRectsCache);
if (parentLayer && parentLayer->clipper().clipRects(clipRectsContext) && clipRects == *parentLayer->clipper().clipRects(clipRectsContext))
- m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, parentLayer->clipper().clipRects(clipRectsContext));
+ m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, parentLayer->clipper().clipRects(clipRectsContext), clipRectsContext.rootLayer);
else
- m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, ClipRects::create(clipRects));
+ m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, ClipRects::create(clipRects), clipRectsContext.rootLayer);
#ifndef NDEBUG
- m_clipRectsCache->m_clipRectsRoot[clipRectsType] = clipRectsContext.rootLayer;
m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] = clipRectsContext.overlayScrollbarSizeRelevancy;
#endif
}
@@ -100,7 +102,7 @@ void RenderLayerClipper::clearClipRectsIncludingDescendants(ClipRectsType typeTo
clearClipRects(typeToClear);
- for (RenderLayer* layer = m_renderer->layer()->firstChild(); layer; layer = layer->nextSibling())
+ for (RenderLayer* layer = m_renderer.layer()->firstChild(); layer; layer = layer->nextSibling())
layer->clipper().clearClipRectsIncludingDescendants(typeToClear);
}
@@ -108,17 +110,118 @@ void RenderLayerClipper::clearClipRects(ClipRectsType typeToClear)
{
if (typeToClear == AllClipRectTypes) {
m_clipRectsCache = nullptr;
+ m_compositingClipRectsDirty = false;
} else {
+ if (typeToClear == CompositingClipRects)
+ m_compositingClipRectsDirty = false;
+
ASSERT(typeToClear < NumCachedClipRectsTypes);
RefPtr<ClipRects> dummy;
- m_clipRectsCache->setClipRects(typeToClear, RespectOverflowClip, dummy);
- m_clipRectsCache->setClipRects(typeToClear, IgnoreOverflowClip, dummy);
+ m_clipRectsCache->setClipRects(typeToClear, RespectOverflowClip, dummy, 0);
+ m_clipRectsCache->setClipRects(typeToClear, IgnoreOverflowClip, dummy, 0);
+ }
+}
+
+LayoutRect RenderLayerClipper::childrenClipRect() const
+{
+ // FIXME: border-radius not accounted for.
+ // FIXME: Regions not accounted for.
+ RenderView* renderView = m_renderer.view();
+ RenderLayer* clippingRootLayer = clippingRootForPainting();
+ LayoutRect layerBounds;
+ ClipRect backgroundRect, foregroundRect, outlineRect;
+ ClipRectsContext clipRectsContext(clippingRootLayer, TemporaryClipRects);
+ // Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
+ calculateRects(clipRectsContext, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
+}
+
+LayoutRect RenderLayerClipper::localClipRect() const
+{
+ // FIXME: border-radius not accounted for.
+ RenderLayer* clippingRootLayer = clippingRootForPainting();
+ LayoutRect layerBounds;
+ ClipRect backgroundRect, foregroundRect, outlineRect;
+ ClipRectsContext clipRectsContext(clippingRootLayer, PaintingClipRects);
+ calculateRects(clipRectsContext, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+
+ LayoutRect clipRect = backgroundRect.rect();
+ if (clipRect == PaintInfo::infiniteRect())
+ return clipRect;
+
+ LayoutPoint clippingRootOffset;
+ m_renderer.layer()->convertToLayerCoords(clippingRootLayer, clippingRootOffset);
+ clipRect.moveBy(-clippingRootOffset);
+
+ return clipRect;
+}
+
+void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+ ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
+{
+ bool isClippingRoot = isClippingRootForContext(clipRectsContext);
+
+ if (!isClippingRoot && m_renderer.layer()->parent()) {
+ backgroundRect = backgroundClipRect(clipRectsContext);
+ backgroundRect.move(roundedIntSize(clipRectsContext.subPixelAccumulation));
+ backgroundRect.intersect(paintDirtyRect);
+ } else {
+ backgroundRect = paintDirtyRect;
+ }
+
+ foregroundRect = backgroundRect;
+ outlineRect = backgroundRect;
+
+ LayoutPoint offset;
+ if (offsetFromRoot)
+ offset = *offsetFromRoot;
+ else
+ m_renderer.layer()->convertToLayerCoords(clipRectsContext.rootLayer, offset);
+ layerBounds = LayoutRect(offset, m_renderer.layer()->size());
+
+ // Update the clip rects that will be passed to child layers.
+ if (m_renderer.hasOverflowClip()) {
+ // This layer establishes a clip of some kind.
+ if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip) {
+ foregroundRect.intersect(toRenderBox(m_renderer).overflowClipRect(offset, clipRectsContext.overlayScrollbarSizeRelevancy));
+ if (m_renderer.style()->hasBorderRadius())
+ foregroundRect.setHasRadius(true);
+ }
+
+ // If we establish an overflow clip at all, then go ahead and make sure our background
+ // rect is intersected with our layer's bounds including our visual overflow,
+ // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
+ if (toRenderBox(m_renderer).hasVisualOverflow()) {
+ // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though
+ // we may need to inflate our clip specifically for shadows or outsets.
+ // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
+ // individual region boxes as overflow.
+ LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer).visualOverflowRect();
+ toRenderBox(m_renderer).flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
+ layerBoundsWithVisualOverflow.moveBy(offset);
+ if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
+ backgroundRect.intersect(layerBoundsWithVisualOverflow);
+ } else {
+ LayoutRect bounds = toRenderBox(m_renderer).borderBoxRect();
+ bounds.moveBy(offset);
+ if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOverflowClip)
+ backgroundRect.intersect(bounds);
+ }
+ }
+
+ // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
+ if (m_renderer.hasClip()) {
+ // Clip applies to *us* as well, so go ahead and update the damageRect.
+ LayoutRect newPosClip = toRenderBox(m_renderer).clipRect(offset);
+ backgroundRect.intersect(newPosClip);
+ foregroundRect.intersect(newPosClip);
+ outlineRect.intersect(newPosClip);
}
}
void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
- if (!m_renderer->layer()->parent()) {
+ if (!m_renderer.layer()->parent()) {
// The root layer's clip rect is always infinite.
clipRects.reset(PaintInfo::infiniteRect());
return;
@@ -127,9 +230,11 @@ void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon
ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
bool useCached = clipRectsType != TemporaryClipRects;
+ bool isClippingRoot = isClippingRootForContext(clipRectsContext);
+
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
- RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0;
+ RenderLayer* parentLayer = !isClippingRoot ? m_renderer.layer()->parent() : 0;
// Ensure that our parent's clip has been calculated so that we can examine the values.
if (parentLayer) {
@@ -146,41 +251,41 @@ void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon
// A fixed object is essentially the root of its containing block hierarchy, so when
// we encounter such an object, we reset our clip rects to the fixedClipRect.
- if (m_renderer->style()->position() == FixedPosition) {
+ if (m_renderer.style()->position() == FixedPosition) {
clipRects.setPosClipRect(clipRects.fixedClipRect());
clipRects.setOverflowClipRect(clipRects.fixedClipRect());
clipRects.setFixed(true);
- } else if (m_renderer->style()->hasInFlowPosition()) {
+ } else if (m_renderer.style()->hasInFlowPosition()) {
clipRects.setPosClipRect(clipRects.overflowClipRect());
- } else if (m_renderer->style()->position() == AbsolutePosition) {
+ } else if (m_renderer.style()->position() == AbsolutePosition) {
clipRects.setOverflowClipRect(clipRects.posClipRect());
}
// Update the clip rects that will be passed to child layers.
- if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || m_renderer->layer() != clipRectsContext.rootLayer)) || m_renderer->hasClip()) {
+ if ((m_renderer.hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || !isClippingRoot)) || m_renderer.hasClip()) {
// This layer establishes a clip of some kind.
// This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
// some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
// clipRects are needed in view space.
LayoutPoint offset;
- offset = roundedLayoutPoint(m_renderer->localToContainerPoint(FloatPoint(), clipRectsContext.rootLayer->renderer()));
- RenderView* view = m_renderer->view();
+ offset = roundedLayoutPoint(m_renderer.localToContainerPoint(FloatPoint(), clipRectsContext.rootLayer->renderer()));
+ RenderView* view = m_renderer.view();
ASSERT(view);
if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) {
offset -= view->frameView()->scrollOffsetForFixedPosition();
}
- if (m_renderer->hasOverflowClip()) {
- ClipRect newOverflowClip = toRenderBox(m_renderer)->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy);
- if (m_renderer->style()->hasBorderRadius())
+ if (m_renderer.hasOverflowClip()) {
+ ClipRect newOverflowClip = toRenderBox(m_renderer).overflowClipRect(offset, clipRectsContext.overlayScrollbarSizeRelevancy);
+ if (m_renderer.style()->hasBorderRadius())
newOverflowClip.setHasRadius(true);
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
- if (m_renderer->isPositioned())
+ if (m_renderer.isPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
}
- if (m_renderer->hasClip()) {
- LayoutRect newPosClip = toRenderBox(m_renderer)->clipRect(offset, clipRectsContext.region);
+ if (m_renderer.hasClip()) {
+ LayoutRect newPosClip = toRenderBox(m_renderer).clipRect(offset);
clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
@@ -188,4 +293,95 @@ void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon
}
}
+static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
+{
+ if (position == FixedPosition)
+ return parentRects.fixedClipRect();
+
+ if (position == AbsolutePosition)
+ return parentRects.posClipRect();
+
+ return parentRects.overflowClipRect();
+}
+
+void RenderLayerClipper::setCompositingClipRectsDirty()
+{
+ m_compositingClipRectsDirty = true;
+}
+
+ClipRect RenderLayerClipper::backgroundClipRect(const ClipRectsContext& clipRectsContext) const
+{
+ ASSERT(m_renderer.layer()->parent());
+
+ if (clipRectsContext.clipRectsType == CompositingClipRects)
+ const_cast<RenderLayerClipper*>(this)->clearClipRectsIncludingDescendants(CompositingClipRects);
+
+ ClipRects parentRects;
+
+ // If we cross into a different pagination context, then we can't rely on the cache.
+ // Just switch over to using TemporaryClipRects.
+ if (clipRectsContext.clipRectsType != TemporaryClipRects && m_renderer.layer()->parent()->enclosingPaginationLayer() != m_renderer.layer()->enclosingPaginationLayer()) {
+ ClipRectsContext tempContext(clipRectsContext);
+ tempContext.clipRectsType = TemporaryClipRects;
+ parentClipRects(tempContext, parentRects);
+ } else {
+ parentClipRects(clipRectsContext, parentRects);
+ }
+
+ ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, m_renderer.style()->position());
+ RenderView* view = m_renderer.view();
+ ASSERT(view);
+
+ // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
+ if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
+ backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition());
+
+ return backgroundClipRect;
+}
+
+bool RenderLayerClipper::isClippingRootForContext(const ClipRectsContext& clipRectsContext) const
+{
+ return clipRectsContext.rootLayer == m_renderer.layer();
+}
+
+void RenderLayerClipper::parentClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
+{
+ // The root is not clipped.
+ if (isClippingRootForContext(clipRectsContext)) {
+ clipRects.reset(PaintInfo::infiniteRect());
+ return;
+ }
+
+ ASSERT(m_renderer.layer()->parent());
+
+ RenderLayerClipper& parentClipper = m_renderer.layer()->parent()->clipper();
+ if (clipRectsContext.clipRectsType == TemporaryClipRects) {
+ parentClipper.calculateClipRects(clipRectsContext, clipRects);
+ return;
+ }
+
+ parentClipper.updateClipRects(clipRectsContext);
+ clipRects = *parentClipper.clipRects(clipRectsContext);
+}
+
+RenderLayer* RenderLayerClipper::clippingRootForPainting() const
+{
+ if (m_renderer.hasCompositedLayerMapping() || m_renderer.groupedMapping())
+ return const_cast<RenderLayer*>(m_renderer.layer());
+
+ const RenderLayer* current = m_renderer.layer();
+ while (current) {
+ if (current->isRootLayer())
+ return const_cast<RenderLayer*>(current);
+
+ current = current->compositingContainer();
+ ASSERT(current);
+ if (current->transform() || (current->compositingState() == PaintsIntoOwnBacking) || current->groupedMapping())
+ return const_cast<RenderLayer*>(current);
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.h
index 03a3ef1a603..362097929ff 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerClipper.h
@@ -51,28 +51,28 @@
namespace WebCore {
class RenderLayer;
-class RenderRegion;
struct ClipRectsContext {
- ClipRectsContext(const RenderLayer* inRootLayer, RenderRegion* inRegion, ClipRectsType inClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip inRespectOverflowClip = RespectOverflowClip)
+ ClipRectsContext(const RenderLayer* inRootLayer, ClipRectsType inClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip inRespectOverflowClip = RespectOverflowClip, const LayoutSize& inSubPixelAccumulation = LayoutSize())
: rootLayer(inRootLayer)
- , region(inRegion)
, clipRectsType(inClipRectsType)
, overlayScrollbarSizeRelevancy(inOverlayScrollbarSizeRelevancy)
, respectOverflowClip(inRespectOverflowClip)
+ , subPixelAccumulation(inSubPixelAccumulation)
{ }
const RenderLayer* rootLayer;
- RenderRegion* region;
ClipRectsType clipRectsType;
OverlayScrollbarSizeRelevancy overlayScrollbarSizeRelevancy;
ShouldRespectOverflowClip respectOverflowClip;
+ LayoutSize subPixelAccumulation;
};
-class RenderLayerClipper {
+class RenderLayerClipper FINAL {
WTF_MAKE_NONCOPYABLE(RenderLayerClipper);
public:
- RenderLayerClipper(RenderLayerModelObject* renderer)
- : m_renderer(renderer)
+ explicit RenderLayerClipper(RenderLayerModelObject& renderer)
+ : m_renderer(renderer)
+ , m_compositingClipRectsDirty(false)
{
}
@@ -88,15 +88,38 @@ public:
void clearClipRectsIncludingDescendants(ClipRectsType typeToClear = AllClipRectTypes);
void clearClipRects(ClipRectsType typeToClear = AllClipRectTypes);
+ void setCompositingClipRectsDirty();
+
+ LayoutRect childrenClipRect() const; // Returns the foreground 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.
+
+ ClipRect backgroundClipRect(const ClipRectsContext&) const;
+
+ // FIXME: The following functions should be private.
+
+ // This method figures out our layerBounds in coordinates relative to
+ // |rootLayer}. It also computes our background and foreground clip rects
+ // for painting/event handling.
+ // Pass offsetFromRoot if known.
+ void calculateRects(const ClipRectsContext&, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+ ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot = 0) const;
+
// Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
// (rather than computing them all from scratch up the parent chain).
void calculateClipRects(const ClipRectsContext&, ClipRects&) const;
private:
- // FIXME: Could this be a RenderBox?
- RenderLayerModelObject* m_renderer;
+ void parentClipRects(const ClipRectsContext&, ClipRects&) const;
+
+ // The layer relative to which clipping rects for this layer are computed.
+ RenderLayer* clippingRootForPainting() const;
+ bool isClippingRootForContext(const ClipRectsContext&) const;
+
+ // FIXME: Could this be a RenderBox?
+ RenderLayerModelObject& m_renderer;
OwnPtr<ClipRectsCache> m_clipRectsCache;
+ unsigned m_compositingClipRectsDirty : 1;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.cpp
deleted file mode 100644
index 45565a55007..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.cpp
+++ /dev/null
@@ -1,2605 +0,0 @@
-/*
- * Copyright (C) 2009, 2010 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 "core/rendering/RenderLayerCompositor.h"
-
-#include "CSSPropertyNames.h"
-#include "HTMLNames.h"
-#include "RuntimeEnabledFeatures.h"
-#include "core/animation/ActiveAnimations.h"
-#include "core/animation/DocumentAnimations.h"
-#include "core/dom/FullscreenElementStack.h"
-#include "core/dom/NodeList.h"
-#include "core/html/HTMLCanvasElement.h"
-#include "core/html/HTMLIFrameElement.h"
-#include "core/html/HTMLVideoElement.h"
-#include "core/html/canvas/CanvasRenderingContext.h"
-#include "core/inspector/InspectorInstrumentation.h"
-#include "core/page/Chrome.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
-#include "core/page/Page.h"
-#include "core/frame/Settings.h"
-#include "core/frame/animation/AnimationController.h"
-#include "core/page/scrolling/ScrollingConstraints.h"
-#include "core/page/scrolling/ScrollingCoordinator.h"
-#include "core/rendering/CompositedLayerMapping.h"
-#include "core/rendering/HitTestResult.h"
-#include "core/rendering/RenderApplet.h"
-#include "core/rendering/RenderEmbeddedObject.h"
-#include "core/rendering/RenderFullScreen.h"
-#include "core/rendering/RenderGeometryMap.h"
-#include "core/rendering/RenderIFrame.h"
-#include "core/rendering/RenderLayerStackingNode.h"
-#include "core/rendering/RenderLayerStackingNodeIterator.h"
-#include "core/rendering/RenderReplica.h"
-#include "core/rendering/RenderVideo.h"
-#include "core/rendering/RenderView.h"
-#include "platform/OverscrollTheme.h"
-#include "platform/TraceEvent.h"
-#include "platform/geometry/TransformState.h"
-#include "platform/graphics/GraphicsLayer.h"
-#include "platform/scroll/ScrollbarTheme.h"
-#include "public/platform/Platform.h"
-#include "wtf/TemporaryChange.h"
-
-#ifndef NDEBUG
-#include "core/rendering/RenderTreeAsText.h"
-#endif
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-class OverlapMapContainer {
-public:
- void add(const IntRect& bounds)
- {
- m_layerRects.append(bounds);
- m_boundingBox.unite(bounds);
- }
-
- bool overlapsLayers(const IntRect& bounds) const
- {
- // Checking with the bounding box will quickly reject cases when
- // layers are created for lists of items going in one direction and
- // never overlap with each other.
- if (!bounds.intersects(m_boundingBox))
- return false;
- for (unsigned i = 0; i < m_layerRects.size(); i++) {
- if (m_layerRects[i].intersects(bounds))
- return true;
- }
- return false;
- }
-
- void unite(const OverlapMapContainer& otherContainer)
- {
- m_layerRects.append(otherContainer.m_layerRects);
- m_boundingBox.unite(otherContainer.m_boundingBox);
- }
-private:
- Vector<IntRect> m_layerRects;
- IntRect m_boundingBox;
-};
-
-class RenderLayerCompositor::OverlapMap {
- WTF_MAKE_NONCOPYABLE(OverlapMap);
-public:
- OverlapMap()
- : m_geometryMap(UseTransforms)
- {
- // Begin by assuming the root layer will be composited so that there
- // is something on the stack. The root layer should also never get a
- // finishCurrentOverlapTestingContext() call.
- beginNewOverlapTestingContext();
- }
-
- void add(const RenderLayer* layer, const IntRect& bounds)
- {
- // Layers do not contribute to overlap immediately--instead, they will
- // contribute to overlap as soon as they have been recursively processed
- // and popped off the stack.
- ASSERT(m_overlapStack.size() >= 2);
- m_overlapStack[m_overlapStack.size() - 2].add(bounds);
- m_layers.add(layer);
- }
-
- bool contains(const RenderLayer* layer)
- {
- return m_layers.contains(layer);
- }
-
- bool overlapsLayers(const IntRect& bounds) const
- {
- return m_overlapStack.last().overlapsLayers(bounds);
- }
-
- bool isEmpty()
- {
- return m_layers.isEmpty();
- }
-
- void beginNewOverlapTestingContext()
- {
- // This effectively creates a new "clean slate" for overlap state.
- // This is used when we know that a subtree or remaining set of
- // siblings does not need to check overlap with things behind it.
- m_overlapStack.append(OverlapMapContainer());
- }
-
- void finishCurrentOverlapTestingContext()
- {
- // The overlap information on the top of the stack is still necessary
- // for checking overlap of any layers outside this context that may
- // overlap things from inside this context. Therefore, we must merge
- // the information from the top of the stack before popping the stack.
- //
- // FIXME: we may be able to avoid this deep copy by rearranging how
- // overlapMap state is managed.
- m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
- m_overlapStack.removeLast();
- }
-
- RenderGeometryMap& geometryMap() { return m_geometryMap; }
-
-private:
- Vector<OverlapMapContainer> m_overlapStack;
- HashSet<const RenderLayer*> m_layers;
- RenderGeometryMap m_geometryMap;
-};
-
-struct CompositingRecursionData {
- CompositingRecursionData(RenderLayer* compAncestor, bool testOverlap)
- : m_compositingAncestor(compAncestor)
- , m_subtreeIsCompositing(false)
- , m_hasUnisolatedCompositedBlendingDescendant(false)
- , m_testingOverlap(testOverlap)
-#ifndef NDEBUG
- , m_depth(0)
-#endif
- {
- }
-
- CompositingRecursionData(const CompositingRecursionData& other)
- : m_compositingAncestor(other.m_compositingAncestor)
- , m_subtreeIsCompositing(other.m_subtreeIsCompositing)
- , m_hasUnisolatedCompositedBlendingDescendant(other.m_hasUnisolatedCompositedBlendingDescendant)
- , m_testingOverlap(other.m_testingOverlap)
-#ifndef NDEBUG
- , m_depth(other.m_depth + 1)
-#endif
- {
- }
-
- RenderLayer* m_compositingAncestor;
- bool m_subtreeIsCompositing;
- bool m_hasUnisolatedCompositedBlendingDescendant;
- bool m_testingOverlap;
-#ifndef NDEBUG
- int m_depth;
-#endif
-};
-
-
-RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
- : m_renderView(renderView)
- , m_hasAcceleratedCompositing(true)
- , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers))
- , m_showRepaintCounter(false)
- , m_needsToRecomputeCompositingRequirements(false)
- , m_needsToUpdateLayerTreeGeometry(false)
- , m_compositing(false)
- , m_compositingLayersNeedRebuild(false)
- , m_forceCompositingMode(false)
- , m_inPostLayoutUpdate(false)
- , m_needsUpdateCompositingRequirementsState(false)
- , m_isTrackingRepaints(false)
- , m_rootLayerAttachment(RootLayerUnattached)
-{
-}
-
-RenderLayerCompositor::~RenderLayerCompositor()
-{
- ASSERT(m_rootLayerAttachment == RootLayerUnattached);
-}
-
-void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
-{
- if (enable != m_compositing) {
- m_compositing = enable;
-
- if (m_compositing) {
- ensureRootLayer();
- notifyIFramesOfCompositingChange();
- } else
- destroyRootLayer();
- }
-}
-
-void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
-{
- bool hasAcceleratedCompositing = false;
- bool showRepaintCounter = false;
- bool forceCompositingMode = false;
-
- if (Settings* settings = m_renderView->document().settings()) {
- hasAcceleratedCompositing = settings->acceleratedCompositingEnabled();
-
- // We allow the chrome to override the settings, in case the page is rendered
- // on a chrome that doesn't allow accelerated compositing.
- if (hasAcceleratedCompositing) {
- if (Page* page = this->page()) {
- m_compositingTriggers = page->chrome().client().allowedCompositingTriggers();
- hasAcceleratedCompositing = m_compositingTriggers;
- }
- }
-
- showRepaintCounter = settings->showRepaintCounter();
- forceCompositingMode = settings->forceCompositingMode() && hasAcceleratedCompositing;
-
- if (forceCompositingMode && !isMainFrame())
- forceCompositingMode = requiresCompositingForScrollableFrame();
- }
-
- if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
- setCompositingLayersNeedRebuild();
-
- m_hasAcceleratedCompositing = hasAcceleratedCompositing;
- m_showRepaintCounter = showRepaintCounter;
- m_forceCompositingMode = forceCompositingMode;
-}
-
-bool RenderLayerCompositor::layerSquashingEnabled() const
-{
- if (Settings* settings = m_renderView->document().settings())
- return settings->layerSquashingEnabled();
-
- return false;
-}
-
-bool RenderLayerCompositor::canRender3DTransforms() const
-{
- return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger);
-}
-
-void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild)
-{
- // FIXME: crbug,com/332248 ideally this could be merged with setNeedsCompositingUpdate().
- if (inCompositingMode())
- m_compositingLayersNeedRebuild = needRebuild;
-
- m_renderView->frameView()->scheduleAnimation();
-}
-
-void RenderLayerCompositor::didChangeVisibleRect()
-{
- GraphicsLayer* rootLayer = rootGraphicsLayer();
- if (!rootLayer)
- return;
-
- FrameView* frameView = m_renderView ? m_renderView->frameView() : 0;
- if (!frameView)
- return;
-
- IntRect visibleRect = m_containerLayer ? IntRect(IntPoint(), frameView->contentsSize()) : frameView->visibleContentRect();
- if (rootLayer->visibleRectChangeRequiresFlush(visibleRect)) {
- if (Page* page = this->page())
- page->chrome().client().scheduleCompositingLayerFlush();
- }
-}
-
-void RenderLayerCompositor::updateCompositingRequirementsState()
-{
- if (!m_needsUpdateCompositingRequirementsState)
- return;
-
- TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerCompositor::updateCompositingRequirementsState");
-
- m_needsUpdateCompositingRequirementsState = false;
-
- if (!rootRenderLayer() || !rootRenderLayer()->acceleratedCompositingForOverflowScrollEnabled())
- return;
-
- for (HashSet<RenderLayer*>::iterator it = m_outOfFlowPositionedLayers.begin(); it != m_outOfFlowPositionedLayers.end(); ++it)
- (*it)->updateHasUnclippedDescendant();
-
- const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView->frameView()->scrollableAreas();
- if (!scrollableAreas)
- return;
-
- for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it)
- (*it)->updateNeedsCompositedScrolling();
-}
-
-static RenderVideo* findFullscreenVideoRenderer(Document* document)
-{
- Element* fullscreenElement = FullscreenElementStack::currentFullScreenElementFrom(document);
- while (fullscreenElement && fullscreenElement->isFrameOwnerElement()) {
- document = toHTMLFrameOwnerElement(fullscreenElement)->contentDocument();
- if (!document)
- return 0;
- fullscreenElement = FullscreenElementStack::currentFullScreenElementFrom(document);
- }
- if (!fullscreenElement || !isHTMLVideoElement(fullscreenElement))
- return 0;
- RenderObject* renderer = fullscreenElement->renderer();
- if (!renderer)
- return 0;
- return toRenderVideo(renderer);
-}
-
-void RenderLayerCompositor::finishCompositingUpdateForFrameTree(Frame* frame)
-{
- for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling())
- finishCompositingUpdateForFrameTree(child);
-
- // Update compositing for current frame after all descendant frames are updated.
- if (frame && frame->contentRenderer()) {
- RenderLayerCompositor* frameCompositor = frame->contentRenderer()->compositor();
- if (frameCompositor && !frameCompositor->isMainFrame())
- frame->contentRenderer()->compositor()->updateCompositingLayers(CompositingUpdateFinishAllDeferredWork);
- }
-}
-
-void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType)
-{
- // Avoid updating the layers with old values. Compositing layers will be updated after the layout is finished.
- if (m_renderView->needsLayout())
- return;
-
- if (updateType == CompositingUpdateFinishAllDeferredWork && isMainFrame() && m_renderView->frameView())
- finishCompositingUpdateForFrameTree(&m_renderView->frameView()->frame());
-
- if (m_forceCompositingMode && !m_compositing)
- enableCompositingMode(true);
-
- if (!m_needsToRecomputeCompositingRequirements && !m_compositing)
- return;
-
- AnimationUpdateBlock animationUpdateBlock(m_renderView->frameView()->frame().animation());
-
- TemporaryChange<bool> postLayoutChange(m_inPostLayoutUpdate, true);
-
- bool needCompositingRequirementsUpdate = false;
- bool needHierarchyAndGeometryUpdate = false;
- bool needGeometryUpdate = false;
- bool needsToUpdateScrollingCoordinator = false;
-
- // CompositingUpdateFinishAllDeferredWork is the only updateType that will actually do any work in this
- // function. All other updateTypes will simply mark that something needed updating, and defer the actual
- // update. This way we only need to compute all compositing state once for every frame drawn (if needed).
- switch (updateType) {
- case CompositingUpdateAfterStyleChange:
- case CompositingUpdateAfterLayout:
- m_needsToRecomputeCompositingRequirements = true;
- break;
- case CompositingUpdateOnScroll:
- m_needsToRecomputeCompositingRequirements = true; // Overlap can change with scrolling, so need to check for hierarchy updates.
- m_needsToUpdateLayerTreeGeometry = true;
- break;
- case CompositingUpdateOnCompositedScroll:
- m_needsToUpdateLayerTreeGeometry = true;
- break;
- case CompositingUpdateFinishAllDeferredWork:
- needCompositingRequirementsUpdate = m_needsToRecomputeCompositingRequirements;
- needHierarchyAndGeometryUpdate = m_compositingLayersNeedRebuild;
- needGeometryUpdate = m_needsToUpdateLayerTreeGeometry;
- needsToUpdateScrollingCoordinator = scrollingCoordinator() ? scrollingCoordinator()->needsToUpdateAfterCompositingChange() : false;
- break;
- }
-
- if (!needCompositingRequirementsUpdate && !needHierarchyAndGeometryUpdate && !needGeometryUpdate && !needsToUpdateScrollingCoordinator)
- return;
-
- ASSERT(updateType == CompositingUpdateFinishAllDeferredWork);
-
- // Only clear the flags if we're updating the entire hierarchy.
- m_compositingLayersNeedRebuild = false;
- m_needsToUpdateLayerTreeGeometry = false;
- m_needsToRecomputeCompositingRequirements = false;
- RenderLayer* updateRoot = rootRenderLayer();
-
- if (needCompositingRequirementsUpdate) {
- // 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.
- CompositingRecursionData recursionData(updateRoot, true);
- bool layersChanged = false;
- bool saw3DTransform = false;
- {
- TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::computeCompositingRequirements");
- OverlapMap overlapTestRequestMap;
-
- // FIXME: Passing these unclippedDescendants down and keeping track
- // of them dynamically, we are requiring a full tree walk. This
- // should be removed as soon as proper overlap testing based on
- // scrolling and animation bounds is implemented (crbug.com/252472).
- Vector<RenderLayer*> unclippedDescendants;
- computeCompositingRequirements(0, updateRoot, &overlapTestRequestMap, recursionData, saw3DTransform, unclippedDescendants);
- }
-
- {
- TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::assignLayersToBackings");
- assignLayersToBackings(updateRoot, layersChanged);
- }
-
- {
- TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateHasVisibleNonLayerContentLoop");
- const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView->frameView()->scrollableAreas();
- if (scrollableAreas) {
- for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it)
- (*it)->updateHasVisibleNonLayerContent();
- }
- }
-
- needHierarchyAndGeometryUpdate |= layersChanged;
- }
-
- if (needHierarchyAndGeometryUpdate) {
- // Update the hierarchy of the compositing layers.
- Vector<GraphicsLayer*> childList;
- {
- TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::rebuildCompositingLayerTree");
- rebuildCompositingLayerTree(updateRoot, childList, 0);
- }
-
- // Host the document layer in the RenderView's root layer.
- if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && isMainFrame()) {
- RenderVideo* video = findFullscreenVideoRenderer(&m_renderView->document());
- if (video && video->hasCompositedLayerMapping()) {
- childList.clear();
- childList.append(video->compositedLayerMapping()->mainGraphicsLayer());
- }
- }
-
- if (childList.isEmpty())
- destroyRootLayer();
- else
- m_rootContentLayer->setChildren(childList);
- } 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);
- }
-
- ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
-
- if (!hasAcceleratedCompositing())
- enableCompositingMode(false);
-
- // The scrolling coordinator may realize that it needs updating while compositing was being updated in this function.
- needsToUpdateScrollingCoordinator |= scrollingCoordinator() ? scrollingCoordinator()->needsToUpdateAfterCompositingChange() : false;
- if (needsToUpdateScrollingCoordinator && isMainFrame() && scrollingCoordinator() && inCompositingMode())
- scrollingCoordinator()->updateAfterCompositingChange();
-
- // Inform the inspector that the layer tree has changed.
- if (isMainFrame())
- InspectorInstrumentation::layerTreeDidChange(page());
-}
-
-static bool requiresCompositing(CompositingReasons reasons)
-{
- // Any reasons other than overlap or assumed overlap will require the layer to be separately compositing.
- return reasons & ~CompositingReasonComboAllOverlapReasons;
-}
-
-static bool requiresSquashing(CompositingReasons reasons)
-{
- // If the layer has overlap or assumed overlap, but no other reasons, then it should be squashed.
- return !requiresCompositing(reasons) && (reasons & CompositingReasonComboAllOverlapReasons);
-}
-
-static bool requiresCompositingOrSquashing(CompositingReasons reasons)
-{
-#ifndef NDEBUG
- bool fastAnswer = reasons != CompositingReasonNone;
- bool slowAnswer = requiresCompositing(reasons) || requiresSquashing(reasons);
- ASSERT(fastAnswer == slowAnswer);
-#endif
- return reasons != CompositingReasonNone;
-}
-
-void RenderLayerCompositor::addOutOfFlowPositionedLayer(RenderLayer* layer)
-{
- m_outOfFlowPositionedLayers.add(layer);
-}
-
-void RenderLayerCompositor::removeOutOfFlowPositionedLayer(RenderLayer* layer)
-{
- m_outOfFlowPositionedLayers.remove(layer);
-}
-
-bool RenderLayerCompositor::allocateOrClearCompositedLayerMapping(RenderLayer* layer)
-{
- bool compositedLayerMappingChanged = false;
- RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason;
- requiresCompositingForPosition(layer->renderer(), layer, &viewportConstrainedNotCompositedReason);
-
- // FIXME: It would be nice to directly use the layer's compositing reason,
- // but allocateOrClearCompositedLayerMapping also gets called without having updated compositing
- // requirements fully.
- if (needsOwnBacking(layer)) {
- enableCompositingMode();
-
- if (!layer->hasCompositedLayerMapping()) {
- // If we need to repaint, do so before allocating the compositedLayerMapping
- repaintOnCompositingChange(layer);
-
- layer->ensureCompositedLayerMapping();
- compositedLayerMappingChanged = true;
-
- // At this time, the ScrollingCooridnator only supports the top-level frame.
- if (layer->isRootLayer() && isMainFrame()) {
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewRootLayerDidChange(m_renderView->frameView());
- }
-
- // If this layer was previously squashed, we need to remove its reference to a groupedMapping right away, so
- // that computing repaint rects will know the layer's correct compositingState.
- // FIXME: do we need to also remove the layer from it's location in the squashing list of its groupedMapping?
- // Need to create a test where a squashed layer pops into compositing. And also to cover all other
- // sorts of compositingState transitions.
- layer->setGroupedMapping(0);
-
- // FIXME: it seems premature to compute this before all compositing state has been updated?
- // This layer and all of its descendants have cached repaints rects that are relative to
- // the repaint container, so change when compositing changes; we need to update them here.
- if (layer->parent())
- layer->repainter().computeRepaintRectsIncludingDescendants();
- }
-
- if (layer->compositedLayerMapping()->updateRequiresOwnBackingStoreForIntrinsicReasons())
- compositedLayerMappingChanged = true;
- } else {
- if (layer->hasCompositedLayerMapping()) {
- // If we're removing the compositedLayerMapping from a reflection, clear the source GraphicsLayer's pointer to
- // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection
- // are both either composited, or not composited.
- if (layer->isReflection()) {
- RenderLayer* sourceLayer = toRenderLayerModelObject(layer->renderer()->parent())->layer();
- if (sourceLayer->hasCompositedLayerMapping()) {
- ASSERT(sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->replicaLayer() == layer->compositedLayerMapping()->mainGraphicsLayer());
- sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->setReplicatedByLayer(0);
- }
- }
-
- removeViewportConstrainedLayer(layer);
-
- layer->clearCompositedLayerMapping();
- compositedLayerMappingChanged = true;
-
- // This layer and all of its descendants have cached repaints rects that are relative to
- // the repaint container, so change when compositing changes; we need to update them here.
- layer->repainter().computeRepaintRectsIncludingDescendants();
-
- // If we need to repaint, do so now that we've removed the compositedLayerMapping
- repaintOnCompositingChange(layer);
- }
- }
-
- if (compositedLayerMappingChanged && layer->renderer()->isRenderPart()) {
- RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer()));
- if (innerCompositor && innerCompositor->inCompositingMode())
- innerCompositor->updateRootLayerAttachment();
- }
-
- if (compositedLayerMappingChanged)
- layer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
-
- // If a fixed position layer gained/lost a compositedLayerMapping or the reason not compositing it changed,
- // the scrolling coordinator needs to recalculate whether it can do fast scrolling.
- bool nonCompositedReasonChanged = false;
- if (layer->renderer()->style()->position() == FixedPosition) {
- if (layer->viewportConstrainedNotCompositedReason() != viewportConstrainedNotCompositedReason) {
- layer->setViewportConstrainedNotCompositedReason(viewportConstrainedNotCompositedReason);
- nonCompositedReasonChanged = true;
- }
- if (compositedLayerMappingChanged || nonCompositedReasonChanged) {
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView->frameView());
- }
- }
-
- return compositedLayerMappingChanged || nonCompositedReasonChanged;
-}
-
-bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer)
-{
- updateDirectCompositingReasons(layer);
- bool layerChanged = allocateOrClearCompositedLayerMapping(layer);
-
- if (layerSquashingEnabled()) {
- // FIXME: this is not correct... info may be out of date and squashing returning true doesn't indicate that the layer changed
- layerChanged = requiresSquashing(layer->compositingReasons());
- }
-
- // See if we need content or clipping layers. Methods called here should assume
- // that the compositing state of descendant layers has not been updated yet.
- if (layer->hasCompositedLayerMapping() && layer->compositedLayerMapping()->updateGraphicsLayerConfiguration())
- layerChanged = true;
-
- return layerChanged;
-}
-
-void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
-{
- // If the renderer is not attached yet, no need to repaint.
- if (layer->renderer() != m_renderView && !layer->renderer()->parent())
- return;
-
- RenderLayerModelObject* repaintContainer = layer->renderer()->containerForRepaint();
- if (!repaintContainer)
- repaintContainer = m_renderView;
-
- layer->repainter().repaintIncludingNonCompositingDescendants(repaintContainer);
-}
-
-// This method assumes that layout is up-to-date, unlike repaintOnCompositingChange().
-void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer* layer, const LayoutRect& rect)
-{
- RenderLayer* compositedAncestor = layer->enclosingCompositingLayerForRepaint(false /*exclude self*/);
- if (compositedAncestor) {
- // FIXME: make sure repaintRect is computed correctly for squashed scenario
- LayoutPoint offset;
- layer->convertToLayerCoords(compositedAncestor, offset);
-
- LayoutRect repaintRect = rect;
- repaintRect.moveBy(offset);
-
- if (compositedAncestor->compositingState() == PaintsIntoOwnBacking) {
- compositedAncestor->repainter().setBackingNeedsRepaintInRect(repaintRect);
- } else if (compositedAncestor->compositingState() == PaintsIntoGroupedBacking) {
- // FIXME: Need to perform the correct coordinate conversion for repaintRect here, including transforms
- compositedAncestor->groupedMapping()->squashingLayer()->setNeedsDisplayInRect(repaintRect);
- } else {
- ASSERT_NOT_REACHED();
- }
- }
-}
-
-// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
-// RenderLayers that are rendered by the composited RenderLayer.
-IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) const
-{
- if (!canBeComposited(layer))
- return IntRect();
-
- RenderLayer::CalculateLayerBoundsFlags flags = RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask;
-#if HAVE(COMPOSITOR_FILTER_OUTSETS)
- // If the compositor computes its own filter outsets, don't include them in the composited bounds.
- if (!layer->paintsWithFilters())
- flags &= ~RenderLayer::IncludeLayerFilterOutsets;
-#endif
- return layer->calculateLayerBounds(ancestorLayer, 0, flags);
-}
-
-void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
-{
- setCompositingLayersNeedRebuild();
-}
-
-void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
-{
- if (!child->hasCompositedLayerMapping() || parent->renderer()->documentBeingDestroyed())
- return;
-
- removeViewportConstrainedLayer(child);
- repaintInCompositedAncestor(child, child->compositedLayerMapping()->compositedBounds());
-
- setCompositingParent(child, 0);
- setCompositingLayersNeedRebuild();
-}
-
-RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const
-{
- for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) {
- if (curr->stackingNode()->isStackingContainer())
- return 0;
-
- if (curr->renderer()->hasClipOrOverflowClip())
- return curr;
- }
- return 0;
-}
-
-void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed)
-{
- if (layer->isRootLayer())
- return;
-
- if (!boundsComputed) {
- // FIXME: If this layer's overlap bounds include its children, we don't need to add its
- // children's bounds to the overlap map.
- layerBounds = enclosingIntRect(overlapMap.geometryMap().absoluteRect(layer->overlapBounds()));
- // 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;
- }
-
- IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(ClipRectsContext(rootRenderLayer(), 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
- clipRect.intersect(layerBounds);
- overlapMap.add(layer, clipRect);
-}
-
-void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, RenderLayer* layer, RenderLayer* ancestorLayer)
-{
- if (!canBeComposited(layer) || overlapMap.contains(layer))
- return;
-
- // A null ancestorLayer is an indication that 'layer' has already been pushed.
- if (ancestorLayer)
- overlapMap.geometryMap().pushMappingsToAncestor(layer, ancestorLayer);
-
- IntRect bounds;
- bool haveComputedBounds = false;
- addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds);
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(layer->stackingNode());
-#endif
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), AllChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- addToOverlapMapRecursive(overlapMap, curNode->layer(), layer);
-
- if (ancestorLayer)
- overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
-}
-
-// Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
-// For the z-order children of a compositing layer:
-// If a child layers has a compositing layer, then all subsequent layers must
-// be compositing in order to render above that layer.
-//
-// If a child in the negative z-order list is compositing, then the layer itself
-// 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* ancestorLayer, RenderLayer* layer, OverlapMap* overlapMap, CompositingRecursionData& currentRecursionData, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants)
-{
- layer->stackingNode()->updateLayerListsIfNeeded();
-
- if (overlapMap)
- overlapMap->geometryMap().pushMappingsToAncestor(layer, ancestorLayer);
-
- // Clear the flag
- layer->setHasCompositingDescendant(false);
- layer->setHasNonCompositedChild(false);
-
- // Start by assuming this layer will not need to composite.
- CompositingReasons reasonsToComposite = CompositingReasonNone;
-
- // First accumulate the straightforward compositing reasons.
- CompositingReasons directReasons = directReasonsForCompositing(layer);
-
- // Video is special. It's the only RenderLayer type that can both have
- // RenderLayer children and whose children can't use its backing to render
- // into. These children (the controls) always need to be promoted into their
- // own layers to draw on top of the accelerated video.
- if (currentRecursionData.m_compositingAncestor && currentRecursionData.m_compositingAncestor->renderer()->isVideo())
- directReasons |= CompositingReasonLayerForVideoOverlay;
-
- if (canBeComposited(layer))
- reasonsToComposite |= directReasons;
-
- // Next, accumulate reasons related to overlap.
- // If overlap testing is used, this reason will be overridden. If overlap testing is not
- // used, we must assume we overlap if there is anything composited behind us in paint-order.
- CompositingReasons overlapCompositingReason = currentRecursionData.m_subtreeIsCompositing ? CompositingReasonAssumedOverlap : CompositingReasonNone;
-
- if (rootRenderLayer()->compositorDrivenAcceleratedScrollingEnabled()) {
- Vector<size_t> unclippedDescendantsToRemove;
- for (size_t i = 0; i < unclippedDescendants.size(); i++) {
- RenderLayer* unclippedDescendant = unclippedDescendants.at(i);
- // If we've reached the containing block of one of the unclipped
- // descendants, that element is no longer relevant to whether or not we
- // should opt in. Unfortunately we can't easily remove from the list
- // while we're iterating, so we have to store it for later removal.
- if (unclippedDescendant->renderer()->containingBlock() == layer->renderer()) {
- unclippedDescendantsToRemove.append(i);
- continue;
- }
- if (layer->scrollsWithRespectTo(unclippedDescendant))
- reasonsToComposite |= CompositingReasonAssumedOverlap;
- }
-
- // Remove irrelevant unclipped descendants in reverse order so our stored
- // indices remain valid.
- for (size_t i = 0; i < unclippedDescendantsToRemove.size(); i++)
- unclippedDescendants.remove(unclippedDescendantsToRemove.at(unclippedDescendantsToRemove.size() - i - 1));
-
- if (reasonsToComposite & CompositingReasonOutOfFlowClipping)
- unclippedDescendants.append(layer);
- }
-
- bool haveComputedBounds = false;
- IntRect absBounds;
- // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map.
- if (overlapMap && !overlapMap->isEmpty() && currentRecursionData.m_testingOverlap && !requiresCompositingOrSquashing(directReasons)) {
- // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
- absBounds = enclosingIntRect(overlapMap->geometryMap().absoluteRect(layer->overlapBounds()));
-
- // 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;
- overlapCompositingReason = overlapMap->overlapsLayers(absBounds) ? CompositingReasonOverlap : CompositingReasonNone;
- }
-
- reasonsToComposite |= overlapCompositingReason;
-
- // 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.
- CompositingRecursionData childRecursionData(currentRecursionData);
- childRecursionData.m_subtreeIsCompositing = false;
-
- bool willBeComposited = canBeComposited(layer) && requiresCompositingOrSquashing(reasonsToComposite);
- if (willBeComposited) {
- // Tell the parent it has compositing descendants.
- currentRecursionData.m_subtreeIsCompositing = true;
- // This layer now acts as the ancestor for kids.
- childRecursionData.m_compositingAncestor = layer;
-
- // Here we know that all children and the layer's own contents can blindly paint into
- // this layer's backing, until a descendant is composited. So, we don't need to check
- // for overlap with anything behind this layer.
- if (overlapMap)
- overlapMap->beginNewOverlapTestingContext();
- // This layer is going to be composited, so children can safely ignore the fact that there's an
- // animation running behind this layer, meaning they can rely on the overlap map testing again.
- childRecursionData.m_testingOverlap = true;
- }
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(layer->stackingNode());
-#endif
-
- bool anyDescendantHas3DTransform = false;
- bool willHaveForegroundLayer = false;
-
- if (layer->stackingNode()->isStackingContainer()) {
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
- while (RenderLayerStackingNode* curNode = iterator.next()) {
- computeCompositingRequirements(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants);
-
- // If we have to make a layer for this child, make one now so we can have a contents layer
- // (since we need to ensure that the -ve z-order child renders underneath our contents).
- if (childRecursionData.m_subtreeIsCompositing) {
- reasonsToComposite |= CompositingReasonNegativeZIndexChildren;
-
- if (!willBeComposited) {
- // make layer compositing
- childRecursionData.m_compositingAncestor = layer;
- overlapMap->beginNewOverlapTestingContext();
- willBeComposited = true;
- willHaveForegroundLayer = true;
-
- // FIXME: temporary solution for the first negative z-index composited child:
- // re-compute the absBounds for the child so that we can add the
- // negative z-index child's bounds to the new overlap context.
- if (overlapMap) {
- overlapMap->geometryMap().pushMappingsToAncestor(curNode->layer(), layer);
- IntRect childAbsBounds = enclosingIntRect(overlapMap->geometryMap().absoluteRect(curNode->layer()->overlapBounds()));
- bool boundsComputed = true;
- overlapMap->beginNewOverlapTestingContext();
- addToOverlapMap(*overlapMap, curNode->layer(), childAbsBounds, boundsComputed);
- overlapMap->finishCurrentOverlapTestingContext();
- overlapMap->geometryMap().popMappingsToAncestor(layer);
- }
- }
- }
- }
- }
-
- if (overlapMap && willHaveForegroundLayer) {
- ASSERT(willBeComposited);
- // A foreground layer effectively is a new backing for all subsequent children, so
- // we don't need to test for overlap with anything behind this. So, we can finish
- // the previous context that was accumulating rects for the negative z-index
- // children, and start with a fresh new empty context.
- overlapMap->finishCurrentOverlapTestingContext();
- overlapMap->beginNewOverlapTestingContext();
- // This layer is going to be composited, so children can safely ignore the fact that there's an
- // animation running behind this layer, meaning they can rely on the overlap map testing again
- childRecursionData.m_testingOverlap = true;
- }
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- computeCompositingRequirements(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants);
-
- // Now that the subtree has been traversed, we can check for compositing reasons that depended on the state of the subtree.
-
- // If we entered compositing mode during the recursion, the root will also need to be composited (as long as accelerated compositing is enabled).
- if (layer->isRootLayer()) {
- if (inCompositingMode() && m_hasAcceleratedCompositing)
- willBeComposited = true;
- }
-
- // All layers (even ones that aren't being composited) need to get added to
- // the overlap map. Layers that are not separately composited will paint into their
- // compositing ancestor's backing, and so are still considered for overlap.
- if (overlapMap && childRecursionData.m_compositingAncestor && !childRecursionData.m_compositingAncestor->isRootLayer())
- addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
-
- if (layer->stackingNode()->isStackingContext()) {
- layer->setShouldIsolateCompositedDescendants(childRecursionData.m_hasUnisolatedCompositedBlendingDescendant);
- } else {
- layer->setShouldIsolateCompositedDescendants(false);
- currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = childRecursionData.m_hasUnisolatedCompositedBlendingDescendant;
- }
-
- // Now check for reasons to become composited that depend on the state of descendant layers.
- CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing(layer->renderer(), childRecursionData.m_subtreeIsCompositing, anyDescendantHas3DTransform);
- reasonsToComposite |= subtreeCompositingReasons;
- if (!willBeComposited && canBeComposited(layer) && requiresCompositingOrSquashing(subtreeCompositingReasons)) {
- childRecursionData.m_compositingAncestor = layer;
- if (overlapMap) {
- // FIXME: this context push is effectively a no-op but needs to exist for
- // now, because the code is designed to push overlap information to the
- // second-from-top context of the stack.
- overlapMap->beginNewOverlapTestingContext();
- addToOverlapMapRecursive(*overlapMap, layer);
- }
- willBeComposited = true;
- }
-
- // If the original layer is composited, the reflection needs to be, too.
- if (layer->reflectionInfo()) {
- // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
- CompositingReasons reflectionCompositingReason = willBeComposited ? CompositingReasonReflectionOfCompositedParent : CompositingReasonNone;
- layer->reflectionInfo()->reflectionLayer()->setCompositingReasons(layer->reflectionInfo()->reflectionLayer()->compositingReasons() | reflectionCompositingReason);
- }
-
- // Subsequent layers in the parent's stacking context may also need to composite.
- if (childRecursionData.m_subtreeIsCompositing)
- currentRecursionData.m_subtreeIsCompositing = true;
-
- if (willBeComposited && layer->hasBlendMode())
- currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = true;
-
- // Set the flag to say that this SC has compositing children.
- layer->setHasCompositingDescendant(childRecursionData.m_subtreeIsCompositing);
-
- // Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
- // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
- // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
- bool isCompositedClippingLayer = canBeComposited(layer) && (reasonsToComposite & CompositingReasonClipsCompositingDescendants);
- if ((!childRecursionData.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer->renderer()))
- currentRecursionData.m_testingOverlap = false;
-
- if (overlapMap && childRecursionData.m_compositingAncestor == layer && !layer->isRootLayer())
- overlapMap->finishCurrentOverlapTestingContext();
-
- if (layer->isRootLayer()) {
- // The root layer needs to be composited if anything else in the tree is composited.
- // Otherwise, we can disable compositing entirely.
- if (childRecursionData.m_subtreeIsCompositing || requiresCompositingOrSquashing(reasonsToComposite) || m_forceCompositingMode) {
- willBeComposited = true;
- reasonsToComposite |= CompositingReasonRoot;
- } else {
- enableCompositingMode(false);
- willBeComposited = false;
- reasonsToComposite = CompositingReasonNone;
- }
- }
-
- // At this point we have finished collecting all reasons to composite this layer.
- layer->setCompositingReasons(reasonsToComposite);
-
- if (!willBeComposited && layer->parent())
- layer->parent()->setHasNonCompositedChild(true);
-
- descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform();
-
- if (overlapMap)
- overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer);
-}
-
-void RenderLayerCompositor::SquashingState::updateSquashingStateForNewMapping(CompositedLayerMappingPtr newCompositedLayerMapping, bool hasNewCompositedLayerMapping, IntPoint newOffsetFromAbsolute)
-{
- // The most recent backing is done accumulating any more squashing layers.
- if (hasMostRecentMapping)
- mostRecentMapping->finishAccumulatingSquashingLayers(nextSquashedLayerIndex);
-
- nextSquashedLayerIndex = 0;
- mostRecentMapping = newCompositedLayerMapping;
- hasMostRecentMapping = hasNewCompositedLayerMapping;
- offsetFromAbsolute = newOffsetFromAbsolute;
-}
-
-static IntPoint computeOffsetFromAbsolute(RenderLayer* layer)
-{
- TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
- layer->renderer()->mapLocalToContainer(0, transformState, ApplyContainerFlip);
- transformState.flatten();
- return roundedIntPoint(transformState.lastPlanarPoint());
-}
-
-void RenderLayerCompositor::assignLayersToBackings(RenderLayer* updateRoot, bool& layersChanged)
-{
- SquashingState squashingState;
- assignLayersToBackingsInternal(updateRoot, squashingState, layersChanged);
- if (squashingState.hasMostRecentMapping)
- squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex);
-}
-
-void RenderLayerCompositor::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, bool& layersChanged)
-{
- if (allocateOrClearCompositedLayerMapping(layer))
- layersChanged = true;
-
- if (layer->reflectionInfo() && updateLayerCompositingState(layer->reflectionInfo()->reflectionLayer()))
- layersChanged = true;
-
- // Add this layer to a squashing backing if needed.
- if (layerSquashingEnabled()) {
- // NOTE: In the future as we generalize this, the background of this layer may need to be assigned to a different backing than
- // the layer's own primary contents. This would happen when we have a composited negative z-index element that needs to
- // paint on top of the background, but below the layer's main contents. For now, because we always composite layers
- // when they have a composited negative z-index child, such layers will never need squashing so it is not yet an issue.
- if (requiresSquashing(layer->compositingReasons())) {
- // A layer that is squashed with other layers cannot have its own CompositedLayerMapping.
- ASSERT(!layer->hasCompositedLayerMapping());
- ASSERT(squashingState.hasMostRecentMapping);
-
- IntPoint offsetFromAbsolute = computeOffsetFromAbsolute(layer);
-
- // FIXME: see if we can refactor this to be clearer
- IntSize offsetFromTargetBacking(offsetFromAbsolute.x() - squashingState.offsetFromAbsolute.x(),
- offsetFromAbsolute.y() - squashingState.offsetFromAbsolute.y());
-
- squashingState.mostRecentMapping->addRenderLayerToSquashingGraphicsLayer(layer, offsetFromTargetBacking, squashingState.nextSquashedLayerIndex);
- squashingState.nextSquashedLayerIndex++;
-
- // FIXME: does this need to be true here? Do we need more logic to decide when it should be true?
- layersChanged = true;
-
- // FIXME: this should be conditioned on whether this layer actually changed status
- layer->clipper().clearClipRectsIncludingDescendants();
- }
- }
-
- if (layer->stackingNode()->isStackingContainer()) {
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged);
- }
-
- if (layerSquashingEnabled()) {
- // At this point, if the layer is to be "separately" composited, then its backing becomes the most recent in paint-order.
- if (layer->compositingState() == PaintsIntoOwnBacking || layer->compositingState() == HasOwnBackingButPaintsIntoAncestor) {
- ASSERT(!requiresSquashing(layer->compositingReasons()));
- IntPoint offsetFromAbsolute = computeOffsetFromAbsolute(layer);
- squashingState.updateSquashingStateForNewMapping(layer->compositedLayerMapping(), layer->hasCompositedLayerMapping(), offsetFromAbsolute);
- }
- }
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged);
-}
-
-void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
-{
- ASSERT(!parentLayer || childLayer->ancestorCompositingLayer() == parentLayer);
- ASSERT(childLayer->hasCompositedLayerMapping());
-
- // It's possible to be called with a parent that isn't yet composited when we're doing
- // partial updates as required by painting or hit testing. Just bail in that case;
- // we'll do a full layer update soon.
- if (!parentLayer || !parentLayer->hasCompositedLayerMapping())
- return;
-
- if (parentLayer) {
- GraphicsLayer* hostingLayer = parentLayer->compositedLayerMapping()->parentForSublayers();
- GraphicsLayer* hostedLayer = childLayer->compositedLayerMapping()->childForSuperlayers();
-
- hostingLayer->addChild(hostedLayer);
- } else {
- childLayer->compositedLayerMapping()->childForSuperlayers()->removeFromParent();
- }
-}
-
-void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer)
-{
- ASSERT(layer->hasCompositedLayerMapping());
-
- GraphicsLayer* hostingLayer = layer->compositedLayerMapping()->parentForSublayers();
- hostingLayer->removeAllChildren();
-}
-
-bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
-{
- if (!m_hasAcceleratedCompositing)
- return false;
-
- return o->supportsAcceleratedRendering();
-}
-
-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
- // have been processed. computeCompositingRequirements() will already have done the repaint if necessary.
-
- layer->stackingNode()->updateLayerListsIfNeeded();
-
- // Used for gathering UMA data about the effect on memory usage of promoting all layers
- // that have a webkit-transition on opacity or transform and intersect the viewport.
- static double pixelsWithoutPromotingAllTransitions = 0.0;
- static double pixelsAddedByPromotingAllTransitions = 0.0;
-
- if (!depth) {
- pixelsWithoutPromotingAllTransitions = 0.0;
- pixelsAddedByPromotingAllTransitions = 0.0;
- }
-
- const bool hasCompositedLayerMapping = layer->hasCompositedLayerMapping();
- CompositedLayerMappingPtr currentCompositedLayerMapping = layer->compositedLayerMapping();
- if (hasCompositedLayerMapping) {
- // The compositing state of all our children has been updated already, so now
- // we can compute and cache the composited bounds for this layer.
- currentCompositedLayerMapping->updateCompositedBounds();
-
- if (layer->reflectionInfo()) {
- RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer();
- if (reflectionLayer->hasCompositedLayerMapping())
- reflectionLayer->compositedLayerMapping()->updateCompositedBounds();
- }
-
- currentCompositedLayerMapping->updateGraphicsLayerConfiguration();
- currentCompositedLayerMapping->updateGraphicsLayerGeometry();
-
- if (!layer->parent())
- updateRootLayerPosition();
-
- if (currentCompositedLayerMapping->hasUnpositionedOverflowControlsLayers())
- layer->scrollableArea()->positionOverflowControls();
-
- pixelsWithoutPromotingAllTransitions += layer->size().height() * layer->size().width();
- } else {
- if ((layer->renderer()->style()->transitionForProperty(CSSPropertyOpacity) ||
- layer->renderer()->style()->transitionForProperty(CSSPropertyWebkitTransform)) &&
- m_renderView->viewRect().intersects(layer->absoluteBoundingBox()))
- pixelsAddedByPromotingAllTransitions += layer->size().height() * layer->size().width();
- }
-
- // If this layer has a compositedLayerMapping, then that is where we place subsequent children GraphicsLayers.
- // Otherwise children continue to append to the child list of the enclosing layer.
- Vector<GraphicsLayer*> layerChildren;
- Vector<GraphicsLayer*>& childList = hasCompositedLayerMapping ? layerChildren : childLayersOfEnclosingLayer;
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(layer->stackingNode());
-#endif
-
- if (layer->stackingNode()->isStackingContainer()) {
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- rebuildCompositingLayerTree(curNode->layer(), childList, depth + 1);
-
- // If a negative z-order child is compositing, we get a foreground layer which needs to get parented.
- if (hasCompositedLayerMapping && currentCompositedLayerMapping->foregroundLayer())
- childList.append(currentCompositedLayerMapping->foregroundLayer());
- }
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- rebuildCompositingLayerTree(curNode->layer(), childList, depth + 1);
-
- if (hasCompositedLayerMapping) {
- bool parented = false;
- if (layer->renderer()->isRenderPart())
- parented = parentFrameContentLayers(toRenderPart(layer->renderer()));
-
- if (!parented)
- currentCompositedLayerMapping->parentForSublayers()->setChildren(layerChildren);
-
- // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
- // Otherwise, the overflow control layers are normal children.
- if (!currentCompositedLayerMapping->hasClippingLayer() && !currentCompositedLayerMapping->hasScrollingLayer()) {
- if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForHorizontalScrollbar()) {
- overflowControlLayer->removeFromParent();
- currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer);
- }
-
- if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForVerticalScrollbar()) {
- overflowControlLayer->removeFromParent();
- currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer);
- }
-
- if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForScrollCorner()) {
- overflowControlLayer->removeFromParent();
- currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer);
- }
- }
-
- childLayersOfEnclosingLayer.append(currentCompositedLayerMapping->childForSuperlayers());
- }
-
- if (!depth) {
- int percentageIncreaseInPixels = static_cast<int>(pixelsAddedByPromotingAllTransitions / pixelsWithoutPromotingAllTransitions * 100);
- blink::Platform::current()->histogramCustomCounts("Renderer.PixelIncreaseFromTransitions", percentageIncreaseInPixels, 0, 1000, 50);
- }
-}
-
-void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
-{
- if (m_overflowControlsHostLayer)
- m_overflowControlsHostLayer->setPosition(contentsOffset);
-}
-
-void RenderLayerCompositor::frameViewDidChangeSize()
-{
- if (m_containerLayer) {
- FrameView* frameView = m_renderView->frameView();
- m_containerLayer->setSize(frameView->unscaledVisibleContentSize());
-
- frameViewDidScroll();
- updateOverflowControlsLayers();
- }
-}
-
-enum AcceleratedFixedRootBackgroundHistogramBuckets {
- ScrolledMainFrameBucket = 0,
- ScrolledMainFrameWithAcceleratedFixedRootBackground = 1,
- ScrolledMainFrameWithUnacceleratedFixedRootBackground = 2,
- AcceleratedFixedRootBackgroundHistogramMax = 3
-};
-
-void RenderLayerCompositor::frameViewDidScroll()
-{
- FrameView* frameView = m_renderView->frameView();
- IntPoint scrollPosition = frameView->scrollPosition();
-
- if (!m_scrollLayer)
- return;
-
- bool scrollingCoordinatorHandlesOffset = false;
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
- if (Settings* settings = m_renderView->document().settings()) {
- if (isMainFrame() || settings->compositedScrollingForFramesEnabled())
- scrollingCoordinatorHandlesOffset = scrollingCoordinator->scrollableAreaScrollLayerDidChange(frameView);
- }
- }
-
- // Scroll position = scroll minimum + scroll offset. Adjust the layer's
- // position to handle whatever the scroll coordinator isn't handling.
- // The minimum scroll position is non-zero for RTL pages with overflow.
- if (scrollingCoordinatorHandlesOffset)
- m_scrollLayer->setPosition(-frameView->minimumScrollPosition());
- else
- m_scrollLayer->setPosition(-scrollPosition);
-
-
- blink::Platform::current()->histogramEnumeration("Renderer.AcceleratedFixedRootBackground",
- ScrolledMainFrameBucket,
- AcceleratedFixedRootBackgroundHistogramMax);
-
- if (!m_renderView->rootBackgroundIsEntirelyFixed())
- return;
-
- blink::Platform::current()->histogramEnumeration("Renderer.AcceleratedFixedRootBackground",
- !!fixedRootBackgroundLayer()
- ? ScrolledMainFrameWithAcceleratedFixedRootBackground
- : ScrolledMainFrameWithUnacceleratedFixedRootBackground,
- AcceleratedFixedRootBackgroundHistogramMax);
-}
-
-void RenderLayerCompositor::frameViewDidLayout()
-{
-}
-
-void RenderLayerCompositor::frameViewScrollbarsExistenceDidChange()
-{
- if (m_containerLayer)
- updateOverflowControlsLayers();
-}
-
-void RenderLayerCompositor::rootFixedBackgroundsChanged()
-{
- if (!supportsFixedRootBackgroundCompositing())
- return;
-
- // To avoid having to make the fixed root background layer fixed positioned to
- // stay put, we position it in the layer tree as follows:
- //
- // + Overflow controls host
- // + Frame clip
- // + (Fixed root background) <-- Here.
- // + Frame scroll
- // + Root content layer
- // + Scrollbars
- //
- // That is, it needs to be the first child of the frame clip, the sibling of
- // the frame scroll layer. The compositor does not own the background layer, it
- // just positions it (like the foreground layer).
- if (GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer())
- m_containerLayer->addChildBelow(backgroundLayer, m_scrollLayer.get());
-}
-
-bool RenderLayerCompositor::scrollingLayerDidChange(RenderLayer* layer)
-{
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- return scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer->scrollableArea());
- return false;
-}
-
-String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
-{
- // Before dumping the layer tree, finish any pending compositing update.
- updateCompositingLayers(CompositingUpdateFinishAllDeferredWork);
-
- if (!m_rootContentLayer)
- return String();
-
- // We skip dumping the scroll and clip layers to keep layerTreeAsText output
- // similar between platforms (unless we explicitly request dumping from the
- // root.
- GraphicsLayer* rootLayer = m_rootContentLayer.get();
- if (flags & LayerTreeIncludesRootLayer)
- rootLayer = rootGraphicsLayer();
-
- String layerTreeText = rootLayer->layerTreeAsText(flags);
-
- // The true root layer is not included in the dump, so if we want to report
- // its repaint rects, they must be included here.
- if (flags & LayerTreeIncludesRepaintRects)
- return m_renderView->frameView()->trackedRepaintRectsAsText() + layerTreeText;
-
- return layerTreeText;
-}
-
-RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer)
-{
- if (!renderer->node()->isFrameOwnerElement())
- return 0;
-
- HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(renderer->node());
- if (Document* contentDocument = element->contentDocument()) {
- if (RenderView* view = contentDocument->renderView())
- return view->compositor();
- }
- return 0;
-}
-
-bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
-{
- RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer);
- if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
- return false;
-
- RenderLayer* layer = renderer->layer();
- if (!layer->hasCompositedLayerMapping())
- return false;
-
- CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping();
- GraphicsLayer* hostingLayer = compositedLayerMapping->parentForSublayers();
- GraphicsLayer* rootLayer = innerCompositor->rootGraphicsLayer();
- if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) {
- hostingLayer->removeAllChildren();
- hostingLayer->addChild(rootLayer);
- }
- return true;
-}
-
-// This just updates layer geometry without changing the hierarchy.
-void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer)
-{
- if (layer->hasCompositedLayerMapping()) {
- CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping();
- // The compositing state of all our children has been updated already, so now
- // we can compute and cache the composited bounds for this layer.
- compositedLayerMapping->updateCompositedBounds();
-
- if (layer->reflectionInfo()) {
- RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer();
- if (reflectionLayer->hasCompositedLayerMapping())
- reflectionLayer->compositedLayerMapping()->updateCompositedBounds();
- }
-
- compositedLayerMapping->updateGraphicsLayerConfiguration();
- compositedLayerMapping->updateGraphicsLayerGeometry();
-
- if (!layer->parent())
- updateRootLayerPosition();
- }
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(layer->stackingNode());
-#endif
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), AllChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- updateLayerTreeGeometry(curNode->layer());
-}
-
-// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
-void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayerStackingNode* compositingAncestor, RenderLayer* layer, bool compositedChildrenOnly)
-{
- if (layer->stackingNode() != compositingAncestor) {
- if (layer->hasCompositedLayerMapping()) {
- CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping();
- compositedLayerMapping->updateCompositedBounds();
-
- if (layer->reflectionInfo()) {
- RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer();
- if (reflectionLayer->hasCompositedLayerMapping())
- reflectionLayer->compositedLayerMapping()->updateCompositedBounds();
- }
-
- compositedLayerMapping->updateGraphicsLayerGeometry();
- if (compositedChildrenOnly)
- return;
- }
- }
-
- if (layer->reflectionInfo())
- updateCompositingDescendantGeometry(compositingAncestor, layer->reflectionInfo()->reflectionLayer(), compositedChildrenOnly);
-
- if (!layer->hasCompositingDescendant())
- return;
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(layer->stackingNode());
-#endif
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), AllChildren);
- while (RenderLayerStackingNode* curNode = iterator.next())
- updateCompositingDescendantGeometry(compositingAncestor, curNode->layer(), compositedChildrenOnly);
-}
-
-
-void RenderLayerCompositor::repaintCompositedLayers(const IntRect* absRect)
-{
- recursiveRepaintLayer(rootRenderLayer(), absRect);
-}
-
-void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer* layer, const IntRect* rect)
-{
- // FIXME: This method does not work correctly with transforms.
- if (layer->compositingState() == PaintsIntoOwnBacking) {
- if (rect)
- layer->repainter().setBackingNeedsRepaintInRect(*rect);
- else
- layer->repainter().setBackingNeedsRepaint();
- }
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(layer->stackingNode());
-#endif
-
- unsigned childrenToVisit = NormalFlowChildren;
- if (layer->hasCompositingDescendant())
- childrenToVisit |= PositiveZOrderChildren | NegativeZOrderChildren;
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), childrenToVisit);
- while (RenderLayerStackingNode* curNode = iterator.next()) {
- if (rect) {
- IntRect childRect(*rect);
- curNode->layer()->convertToPixelSnappedLayerCoords(layer, childRect);
- recursiveRepaintLayer(curNode->layer(), &childRect);
- } else {
- recursiveRepaintLayer(curNode->layer());
- }
- }
-}
-
-RenderLayer* RenderLayerCompositor::rootRenderLayer() const
-{
- return m_renderView->layer();
-}
-
-GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const
-{
- if (m_overflowControlsHostLayer)
- return m_overflowControlsHostLayer.get();
- return m_rootContentLayer.get();
-}
-
-GraphicsLayer* RenderLayerCompositor::scrollLayer() const
-{
- return m_scrollLayer.get();
-}
-
-void RenderLayerCompositor::setIsInWindow(bool isInWindow)
-{
- if (!inCompositingMode())
- return;
-
- if (isInWindow) {
- if (m_rootLayerAttachment != RootLayerUnattached)
- return;
-
- RootLayerAttachment attachment = isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
- attachRootLayer(attachment);
- } else {
- if (m_rootLayerAttachment == RootLayerUnattached)
- return;
-
- detachRootLayer();
- }
-}
-
-void RenderLayerCompositor::clearMappingForRenderLayerIncludingDescendants(RenderLayer* layer)
-{
- if (!layer)
- return;
-
- if (layer->hasCompositedLayerMapping()) {
- removeViewportConstrainedLayer(layer);
- layer->clearCompositedLayerMapping();
- }
-
- for (RenderLayer* currLayer = layer->firstChild(); currLayer; currLayer = currLayer->nextSibling())
- clearMappingForRenderLayerIncludingDescendants(currLayer);
-}
-
-void RenderLayerCompositor::clearMappingForAllRenderLayers()
-{
- clearMappingForRenderLayerIncludingDescendants(m_renderView->layer());
-}
-
-void RenderLayerCompositor::updateRootLayerPosition()
-{
- if (m_rootContentLayer) {
- const IntRect& documentRect = m_renderView->documentRect();
- m_rootContentLayer->setSize(documentRect.size());
- m_rootContentLayer->setPosition(documentRect.location());
-#if USE(RUBBER_BANDING)
- if (m_layerForOverhangShadow)
- OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get());
-#endif
- }
- if (m_containerLayer) {
- FrameView* frameView = m_renderView->frameView();
- m_containerLayer->setSize(frameView->unscaledVisibleContentSize());
- }
-}
-
-bool RenderLayerCompositor::has3DContent() const
-{
- return layerHas3DContent(rootRenderLayer());
-}
-
-void RenderLayerCompositor::updateDirectCompositingReasons(RenderLayer* layer)
-{
- CompositingReasons layerReasons = layer->compositingReasons();
-
- layerReasons &= ~CompositingReasonComboAllDirectReasons;
- layerReasons |= directReasonsForCompositing(layer);
- layer->setCompositingReasons(layerReasons);
-}
-
-bool RenderLayerCompositor::needsOwnBacking(const RenderLayer* layer) const
-{
- if (!canBeComposited(layer))
- return false;
-
- // If squashing is disabled, then layers that would have been squashed should just be separately composited.
- bool needsOwnBackingForDisabledSquashing = !layerSquashingEnabled() && requiresSquashing(layer->compositingReasons());
-
- return requiresCompositing(layer->compositingReasons()) || needsOwnBackingForDisabledSquashing || (inCompositingMode() && layer->isRootLayer());
-}
-
-bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
-{
- // 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()->flowThreadState() == RenderObject::NotInsideFlowThread;
-}
-
-CompositingReasons RenderLayerCompositor::directReasonsForCompositing(const RenderLayer* layer) const
-{
- RenderObject* renderer = layer->renderer();
- CompositingReasons directReasons = CompositingReasonNone;
-
- if (requiresCompositingForTransform(renderer))
- directReasons |= CompositingReason3DTransform;
-
- // Only zero or one of the following conditions will be true for a given RenderLayer.
- if (requiresCompositingForVideo(renderer))
- directReasons |= CompositingReasonVideo;
- else if (requiresCompositingForCanvas(renderer))
- directReasons |= CompositingReasonCanvas;
- else if (requiresCompositingForPlugin(renderer))
- directReasons |= CompositingReasonPlugin;
- else if (requiresCompositingForFrame(renderer))
- directReasons |= CompositingReasonIFrame;
-
- if (requiresCompositingForBackfaceVisibilityHidden(renderer))
- directReasons |= CompositingReasonBackfaceVisibilityHidden;
-
- if (requiresCompositingForAnimation(renderer))
- directReasons |= CompositingReasonAnimation;
-
- if (requiresCompositingForTransition(renderer))
- directReasons |= CompositingReasonAnimation;
-
- if (requiresCompositingForFilters(renderer))
- directReasons |= CompositingReasonFilters;
-
- if (requiresCompositingForPosition(renderer, layer))
- directReasons |= renderer->style()->position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky;
-
- if (requiresCompositingForOverflowScrolling(layer))
- directReasons |= CompositingReasonOverflowScrollingTouch;
-
- if (requiresCompositingForOverflowScrollingParent(layer))
- directReasons |= CompositingReasonOverflowScrollingParent;
-
- if (requiresCompositingForOutOfFlowClipping(layer))
- directReasons |= CompositingReasonOutOfFlowClipping;
-
- return directReasons;
-}
-
-// 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.
-// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
-// but a sibling in the z-order hierarchy.
-bool RenderLayerCompositor::clippedByAncestor(const RenderLayer* layer) const
-{
- if (!layer->hasCompositedLayerMapping() || !layer->parent())
- return false;
-
- // FIXME: need to double-check if semantics of ancestorCompositingLayer() work correctly here?
- const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
- if (!compositingAncestor)
- return false;
-
- // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
- // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
- // and layer.
- const RenderLayer* computeClipRoot = 0;
- const RenderLayer* curr = layer;
- while (curr) {
- const RenderLayer* next = curr->parent();
- if (next == compositingAncestor) {
- computeClipRoot = curr;
- break;
- }
- curr = next;
- }
-
- if (!computeClipRoot || computeClipRoot == layer)
- return false;
-
- return layer->backgroundClipRect(ClipRectsContext(computeClipRoot, 0, TemporaryClipRects)).rect() != PaintInfo::infiniteRect(); // FIXME: Incorrect for CSS regions.
-}
-
-// Return true if the given layer is a stacking context and has compositing child
-// layers that it needs to clip. In this case we insert a clipping GraphicsLayer
-// into the hierarchy between this layer and its children in the z-order hierarchy.
-bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
-{
- return layer->hasCompositingDescendant() && layer->renderer()->hasClipOrOverflowClip();
-}
-
-bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const
-{
- // Need this done first to determine overflow.
- ASSERT(!m_renderView->needsLayout());
- if (isMainFrame())
- return false;
-
- if (!(m_compositingTriggers & ChromeClient::ScrollableInnerFrameTrigger))
- return false;
-
- FrameView* frameView = m_renderView->frameView();
- return frameView->isScrollable();
-}
-
-bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
- return false;
-
- RenderStyle* style = renderer->style();
- // Note that we ask the renderer if it has a transform, because the style may have transforms,
- // but the renderer may be an inline that doesn't suppport them.
- return renderer->hasTransform() && style->transform().has3DOperation();
-}
-
-bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const
-{
- if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && renderer->isVideo()) {
- HTMLMediaElement* media = toHTMLMediaElement(renderer->node());
- if (media->isFullscreen())
- return true;
- }
-
- if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
- return false;
-
- if (renderer->isVideo()) {
- RenderVideo* video = toRenderVideo(renderer);
- return video->shouldDisplayVideo() && canAccelerateVideoRendering(video);
- }
- return false;
-}
-
-bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
- return false;
-
- if (renderer->isCanvas()) {
- HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
- return canvas->renderingContext() && canvas->renderingContext()->isAccelerated();
- }
- return false;
-}
-
-bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
- return false;
-
- bool composite = renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
- if (!composite)
- return false;
-
- // FIXME: this seems bogus. If we don't know the layout position/size of the plugin yet, would't that be handled elsewhere?
- m_needsToRecomputeCompositingRequirements = true;
-
- RenderWidget* pluginRenderer = toRenderWidget(renderer);
- // If we can't reliably know the size of the plugin yet, don't change compositing state.
- if (pluginRenderer->needsLayout())
- return pluginRenderer->hasLayer() && pluginRenderer->layer()->hasCompositedLayerMapping();
-
- // Don't go into compositing mode if height or width are zero, or size is 1x1.
- IntRect contentBox = pixelSnappedIntRect(pluginRenderer->contentBoxRect());
- return contentBox.height() * contentBox.width() > 1;
-}
-
-bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) const
-{
- if (!renderer->isRenderPart())
- return false;
-
- RenderPart* frameRenderer = toRenderPart(renderer);
-
- if (!frameRenderer->requiresAcceleratedCompositing())
- return false;
-
- if (frameRenderer->node() && frameRenderer->node()->isFrameOwnerElement() && toHTMLFrameOwnerElement(frameRenderer->node())->contentFrame() && toHTMLFrameOwnerElement(frameRenderer->node())->contentFrame()->remotePlatformLayer())
- return true;
-
- // FIXME: this seems bogus. If we don't know the layout position/size of the frame yet, wouldn't that be handled elsehwere?
- m_needsToRecomputeCompositingRequirements = true;
-
- RenderLayerCompositor* innerCompositor = frameContentsCompositor(frameRenderer);
- if (!innerCompositor)
- return false;
-
- // If we can't reliably know the size of the iframe yet, don't change compositing state.
- if (renderer->needsLayout())
- return frameRenderer->hasLayer() && frameRenderer->layer()->hasCompositedLayerMapping();
-
- // Don't go into compositing mode if height or width are zero.
- IntRect contentBox = pixelSnappedIntRect(frameRenderer->contentBoxRect());
- return contentBox.height() * contentBox.width() > 0;
-}
-
-bool RenderLayerCompositor::requiresCompositingForBackfaceVisibilityHidden(RenderObject* renderer) const
-{
- return canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden;
-}
-
-bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
- return false;
-
- if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
- return renderer->animation().isRunningAcceleratableAnimationOnRenderer(renderer);
-
- return shouldCompositeForActiveAnimations(*renderer);
-}
-
-bool RenderLayerCompositor::requiresCompositingForTransition(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
- return false;
-
- if (Settings* settings = m_renderView->document().settings()) {
- if (!settings->acceleratedCompositingForTransitionEnabled())
- return false;
- }
-
- return renderer->style()->transitionForProperty(CSSPropertyOpacity)
- || renderer->style()->transitionForProperty(CSSPropertyWebkitFilter)
- || renderer->style()->transitionForProperty(CSSPropertyWebkitTransform);
-}
-
-CompositingReasons RenderLayerCompositor::subtreeReasonsForCompositing(RenderObject* renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants) const
-{
- CompositingReasons subtreeReasons = CompositingReasonNone;
-
- // FIXME: this seems to be a potentially different layer than the layer for which this was called. May not be an error, but is very confusing.
- RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
-
- // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
- // via compositing so that they also apply to those composited descdendants.
- if (hasCompositedDescendants) {
- if (layer->transform())
- subtreeReasons |= CompositingReasonTransformWithCompositedDescendants;
-
- if (layer->shouldIsolateCompositedDescendants()) {
- ASSERT(layer->stackingNode()->isStackingContext());
- subtreeReasons |= CompositingReasonIsolateCompositedDescendants;
- }
-
- // If the implementation of createsGroup changes, we need to be aware of that in this part of code.
- ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->hasFilter() || renderer->hasBlendMode()) == renderer->createsGroup());
- if (renderer->isTransparent())
- subtreeReasons |= CompositingReasonOpacityWithCompositedDescendants;
- if (renderer->hasMask())
- subtreeReasons |= CompositingReasonMaskWithCompositedDescendants;
- if (renderer->hasFilter())
- subtreeReasons |= CompositingReasonFilterWithCompositedDescendants;
- if (renderer->hasBlendMode())
- subtreeReasons |= CompositingReasonBlendingWithCompositedDescendants;
-
- if (renderer->hasReflection())
- subtreeReasons |= CompositingReasonReflectionWithCompositedDescendants;
-
- if (renderer->hasClipOrOverflowClip())
- subtreeReasons |= CompositingReasonClipsCompositingDescendants;
- }
-
-
- // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that
- // will be affected by the preserve-3d or perspective.
- if (has3DTransformedDescendants) {
- if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D)
- subtreeReasons |= CompositingReasonPreserve3D;
-
- if (renderer->style()->hasPerspective())
- subtreeReasons |= CompositingReasonPerspective;
- }
-
- return subtreeReasons;
-}
-
-bool RenderLayerCompositor::requiresCompositingForFilters(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::FilterTrigger))
- return false;
-
- return renderer->hasFilter();
-}
-
-bool RenderLayerCompositor::requiresCompositingForOverflowScrollingParent(const RenderLayer* layer) const
-{
- return !!layer->scrollParent();
-}
-
-bool RenderLayerCompositor::requiresCompositingForOutOfFlowClipping(const RenderLayer* layer) const
-{
- return layer->compositorDrivenAcceleratedScrollingEnabled() && layer->isUnclippedDescendant();
-}
-
-bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
-{
- // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
- // opacity, transform) can get their own composited layer. A stacking context is required otherwise
- // z-index and clipping will be broken.
- if (!renderer->isPositioned())
- return false;
-
- EPosition position = renderer->style()->position();
- bool isFixed = renderer->isOutOfFlowPositioned() && position == FixedPosition;
- if (isFixed && !layer->stackingNode()->isStackingContainer())
- return false;
-
- bool isSticky = renderer->isInFlowPositioned() && position == StickyPosition;
- if (!isFixed && !isSticky)
- return false;
-
- // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled().
- if (Settings* settings = m_renderView->document().settings()) {
- if (!settings->acceleratedCompositingForFixedPositionEnabled())
- return false;
- }
-
- if (isSticky)
- return true;
-
- RenderObject* container = renderer->container();
- // If the renderer is not hooked up yet then we have to wait until it is.
- if (!container) {
- m_needsToRecomputeCompositingRequirements = true;
- return false;
- }
-
- // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
- // They will stay fixed wrt the container rather than the enclosing frame.
- if (container != m_renderView) {
- if (viewportConstrainedNotCompositedReason)
- *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer;
- return false;
- }
-
- // If the fixed-position element does not have any scrollable ancestor between it and
- // its container, then we do not need to spend compositor resources for it. Start by
- // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below.
- bool hasScrollableAncestor = false;
-
- // The FrameView has the scrollbars associated with the top level viewport, so we have to
- // check the FrameView in addition to the hierarchy of ancestors.
- FrameView* frameView = m_renderView->frameView();
- if (frameView && frameView->isScrollable())
- hasScrollableAncestor = true;
-
- RenderLayer* ancestor = layer->parent();
- while (ancestor && !hasScrollableAncestor) {
- if (frameView->containsScrollableArea(ancestor->scrollableArea()))
- hasScrollableAncestor = true;
- if (ancestor->renderer() == m_renderView)
- break;
- ancestor = ancestor->parent();
- }
-
- if (!hasScrollableAncestor) {
- if (viewportConstrainedNotCompositedReason)
- *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors;
- return false;
- }
-
- // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done.
- if (!m_inPostLayoutUpdate) {
- m_needsToRecomputeCompositingRequirements = true;
- return layer->hasCompositedLayerMapping();
- }
-
- bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant();
- if (!paintsContent) {
- if (viewportConstrainedNotCompositedReason)
- *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent;
- return false;
- }
-
- // Fixed position elements that are invisible in the current view don't get their own layer.
- if (FrameView* frameView = m_renderView->frameView()) {
- LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect();
- LayoutRect layerBounds = layer->calculateLayerBounds(rootRenderLayer(), 0,
- RenderLayer::DefaultCalculateLayerBoundsFlags
- | RenderLayer::ExcludeHiddenDescendants
- | RenderLayer::DontConstrainForMask
- | RenderLayer::IncludeCompositedDescendants
- | RenderLayer::PretendLayerHasOwnBacking);
- if (!viewBounds.intersects(enclosingIntRect(layerBounds))) {
- if (viewportConstrainedNotCompositedReason) {
- *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
- m_needsToRecomputeCompositingRequirements = true;
- }
- return false;
- }
- }
-
- return true;
-}
-
-bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer* layer) const
-{
- return layer->needsCompositedScrolling();
-}
-
-bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
-{
- if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
- return false;
- if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
- return renderer->animation().isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
- return hasActiveAnimations(*renderer, CSSPropertyWebkitTransform);
-}
-
-// 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.
-bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
-{
- return layer->stackingNode()->hasNegativeZOrderList();
-}
-
-static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
-{
- if (!scrollbar)
- return;
-
- context.save();
- const IntRect& scrollbarRect = scrollbar->frameRect();
- context.translate(-scrollbarRect.x(), -scrollbarRect.y());
- IntRect transformedClip = clip;
- transformedClip.moveBy(scrollbarRect.location());
- scrollbar->paint(&context, transformedClip);
- context.restore();
-}
-
-void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
-{
- if (graphicsLayer == layerForHorizontalScrollbar())
- paintScrollbar(m_renderView->frameView()->horizontalScrollbar(), context, clip);
- else if (graphicsLayer == layerForVerticalScrollbar())
- paintScrollbar(m_renderView->frameView()->verticalScrollbar(), context, clip);
- else if (graphicsLayer == layerForScrollCorner()) {
- const IntRect& scrollCorner = m_renderView->frameView()->scrollCornerRect();
- context.save();
- context.translate(-scrollCorner.x(), -scrollCorner.y());
- IntRect transformedClip = clip;
- transformedClip.moveBy(scrollCorner.location());
- m_renderView->frameView()->paintScrollCorner(&context, transformedClip);
- context.restore();
- }
-}
-
-bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
-{
- if (Settings* settings = m_renderView->document().settings()) {
- if (settings->acceleratedCompositingForFixedRootBackgroundEnabled())
- return true;
- }
- return false;
-}
-
-bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer* layer) const
-{
- if (layer != m_renderView->layer())
- return false;
-
- return supportsFixedRootBackgroundCompositing() && m_renderView->rootBackgroundIsEntirelyFixed();
-}
-
-GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
-{
- // Get the fixed root background from the RenderView layer's compositedLayerMapping.
- RenderLayer* viewLayer = m_renderView->layer();
- if (!viewLayer)
- return 0;
-
- if (viewLayer->compositingState() == PaintsIntoOwnBacking && viewLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBackground())
- return viewLayer->compositedLayerMapping()->backgroundLayer();
-
- return 0;
-}
-
-static void resetTrackedRepaintRectsRecursive(GraphicsLayer* graphicsLayer)
-{
- if (!graphicsLayer)
- return;
-
- graphicsLayer->resetTrackedRepaints();
-
- for (size_t i = 0; i < graphicsLayer->children().size(); ++i)
- resetTrackedRepaintRectsRecursive(graphicsLayer->children()[i]);
-
- if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer())
- resetTrackedRepaintRectsRecursive(replicaLayer);
-
- if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer())
- resetTrackedRepaintRectsRecursive(maskLayer);
-
- if (GraphicsLayer* clippingMaskLayer = graphicsLayer->contentsClippingMaskLayer())
- resetTrackedRepaintRectsRecursive(clippingMaskLayer);
-}
-
-void RenderLayerCompositor::resetTrackedRepaintRects()
-{
- if (GraphicsLayer* rootLayer = rootGraphicsLayer())
- resetTrackedRepaintRectsRecursive(rootLayer);
-}
-
-void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints)
-{
- updateCompositingLayers(CompositingUpdateFinishAllDeferredWork);
- m_isTrackingRepaints = tracksRepaints;
-}
-
-bool RenderLayerCompositor::isTrackingRepaints() const
-{
- return m_isTrackingRepaints;
-}
-
-void RenderLayerCompositor::didCommitChangesForLayer(const GraphicsLayer*) const
-{
- // Nothing to do here yet.
-}
-
-static bool shouldCompositeOverflowControls(FrameView* view)
-{
- if (Page* page = view->frame().page()) {
- if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
- if (scrollingCoordinator->coordinatesScrollingForFrameView(view))
- return true;
- }
-
- return true;
-}
-
-bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
-{
- FrameView* view = m_renderView->frameView();
- return shouldCompositeOverflowControls(view) && view->horizontalScrollbar();
-}
-
-bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
-{
- FrameView* view = m_renderView->frameView();
- return shouldCompositeOverflowControls(view) && view->verticalScrollbar();
-}
-
-bool RenderLayerCompositor::requiresScrollCornerLayer() const
-{
- FrameView* view = m_renderView->frameView();
- return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible();
-}
-
-#if USE(RUBBER_BANDING)
-bool RenderLayerCompositor::requiresOverhangLayers() const
-{
- // We don't want a layer if this is a subframe.
- if (!isMainFrame())
- return false;
-
- // We do want a layer if we have a scrolling coordinator and can scroll.
- if (scrollingCoordinator() && m_renderView->frameView()->hasOpaqueBackground())
- return true;
-
- // Chromium always wants a layer.
- return true;
-}
-#endif
-
-void RenderLayerCompositor::updateOverflowControlsLayers()
-{
-#if USE(RUBBER_BANDING)
- if (requiresOverhangLayers()) {
- if (!m_layerForOverhangShadow) {
- m_layerForOverhangShadow = GraphicsLayer::create(graphicsLayerFactory(), this);
- OverscrollTheme::theme()->setUpOverhangShadowLayer(m_layerForOverhangShadow.get());
- OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get());
- m_scrollLayer->addChild(m_layerForOverhangShadow.get());
- }
- } else {
- if (m_layerForOverhangShadow) {
- m_layerForOverhangShadow->removeFromParent();
- m_layerForOverhangShadow = nullptr;
- }
- }
-#endif
-
- if (requiresHorizontalScrollbarLayer()) {
- if (!m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
- m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
-
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), HorizontalScrollbar);
- }
- } else if (m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar->removeFromParent();
- m_layerForHorizontalScrollbar = nullptr;
-
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), HorizontalScrollbar);
- }
-
- if (requiresVerticalScrollbarLayer()) {
- if (!m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
- m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
-
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), VerticalScrollbar);
- }
- } else if (m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar->removeFromParent();
- m_layerForVerticalScrollbar = nullptr;
-
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), VerticalScrollbar);
- }
-
- if (requiresScrollCornerLayer()) {
- if (!m_layerForScrollCorner) {
- m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this);
- m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());
- }
- } else if (m_layerForScrollCorner) {
- m_layerForScrollCorner->removeFromParent();
- m_layerForScrollCorner = nullptr;
- }
-
- m_renderView->frameView()->positionScrollbarLayers();
-}
-
-void RenderLayerCompositor::ensureRootLayer()
-{
- RootLayerAttachment expectedAttachment = isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
- if (expectedAttachment == m_rootLayerAttachment)
- return;
-
- if (!m_rootContentLayer) {
- m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
- IntRect overflowRect = m_renderView->pixelSnappedLayoutOverflowRect();
- m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
- m_rootContentLayer->setPosition(FloatPoint());
-
- // Need to clip to prevent transformed content showing outside this frame
- m_rootContentLayer->setMasksToBounds(true);
- }
-
- if (!m_overflowControlsHostLayer) {
- ASSERT(!m_scrollLayer);
- ASSERT(!m_containerLayer);
-
- // Create a layer to host the clipping layer and the overflow controls layers.
- m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
-
- // Create a clipping layer if this is an iframe or settings require to clip.
- m_containerLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
- bool containerMasksToBounds = !isMainFrame();
- if (Settings* settings = m_renderView->document().settings()) {
- if (settings->mainFrameClipsContent())
- containerMasksToBounds = true;
- }
- m_containerLayer->setMasksToBounds(containerMasksToBounds);
-
- m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true);
-
- // Hook them up
- m_overflowControlsHostLayer->addChild(m_containerLayer.get());
- m_containerLayer->addChild(m_scrollLayer.get());
- m_scrollLayer->addChild(m_rootContentLayer.get());
-
- frameViewDidChangeSize();
- frameViewDidScroll();
- }
-
- // Check to see if we have to change the attachment
- if (m_rootLayerAttachment != RootLayerUnattached)
- detachRootLayer();
-
- attachRootLayer(expectedAttachment);
-}
-
-void RenderLayerCompositor::destroyRootLayer()
-{
- if (!m_rootContentLayer)
- return;
-
- detachRootLayer();
-
-#if USE(RUBBER_BANDING)
- if (m_layerForOverhangShadow) {
- m_layerForOverhangShadow->removeFromParent();
- m_layerForOverhangShadow = nullptr;
- }
-#endif
-
- if (m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar->removeFromParent();
- m_layerForHorizontalScrollbar = nullptr;
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), HorizontalScrollbar);
- if (Scrollbar* horizontalScrollbar = m_renderView->frameView()->verticalScrollbar())
- m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
- }
-
- if (m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar->removeFromParent();
- m_layerForVerticalScrollbar = nullptr;
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), VerticalScrollbar);
- if (Scrollbar* verticalScrollbar = m_renderView->frameView()->verticalScrollbar())
- m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
- }
-
- if (m_layerForScrollCorner) {
- m_layerForScrollCorner = nullptr;
- m_renderView->frameView()->invalidateScrollCorner(m_renderView->frameView()->scrollCornerRect());
- }
-
- if (m_overflowControlsHostLayer) {
- m_overflowControlsHostLayer = nullptr;
- m_containerLayer = nullptr;
- m_scrollLayer = nullptr;
- }
- ASSERT(!m_scrollLayer);
- m_rootContentLayer = nullptr;
-}
-
-void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment)
-{
- if (!m_rootContentLayer)
- return;
-
- switch (attachment) {
- case RootLayerUnattached:
- ASSERT_NOT_REACHED();
- break;
- case RootLayerAttachedViaChromeClient: {
- Frame& frame = m_renderView->frameView()->frame();
- Page* page = frame.page();
- if (!page)
- return;
- page->chrome().client().attachRootGraphicsLayer(&frame, rootGraphicsLayer());
- break;
- }
- case RootLayerAttachedViaEnclosingFrame: {
- // The layer will get hooked up via CompositedLayerMapping::updateGraphicsLayerConfiguration()
- // for the frame's renderer in the parent document.
- m_renderView->document().ownerElement()->scheduleLayerUpdate();
- break;
- }
- }
-
- m_rootLayerAttachment = attachment;
-}
-
-void RenderLayerCompositor::detachRootLayer()
-{
- if (!m_rootContentLayer || m_rootLayerAttachment == RootLayerUnattached)
- return;
-
- switch (m_rootLayerAttachment) {
- case RootLayerAttachedViaEnclosingFrame: {
- // The layer will get unhooked up via CompositedLayerMapping::updateGraphicsLayerConfiguration()
- // for the frame's renderer in the parent document.
- if (m_overflowControlsHostLayer)
- m_overflowControlsHostLayer->removeFromParent();
- else
- m_rootContentLayer->removeFromParent();
-
- if (HTMLFrameOwnerElement* ownerElement = m_renderView->document().ownerElement())
- ownerElement->scheduleLayerUpdate();
- break;
- }
- case RootLayerAttachedViaChromeClient: {
- Frame& frame = m_renderView->frameView()->frame();
- Page* page = frame.page();
- if (!page)
- return;
- page->chrome().client().attachRootGraphicsLayer(&frame, 0);
- }
- break;
- case RootLayerUnattached:
- break;
- }
-
- m_rootLayerAttachment = RootLayerUnattached;
-}
-
-void RenderLayerCompositor::updateRootLayerAttachment()
-{
- ensureRootLayer();
-}
-
-bool RenderLayerCompositor::isMainFrame() const
-{
- // FIXME: Frame::isMainFrame() is probably better.
- return !m_renderView->document().ownerElement();
-}
-
-// IFrames are special, because we hook compositing layers together across iframe boundaries
-// when both parent and iframe content are composited. So when this frame becomes composited, we have
-// to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite.
-void RenderLayerCompositor::notifyIFramesOfCompositingChange()
-{
- if (!m_renderView->frameView())
- return;
- Frame& frame = m_renderView->frameView()->frame();
-
- for (Frame* child = frame.tree().firstChild(); child; child = child->tree().traverseNext(&frame)) {
- if (child->document() && child->document()->ownerElement())
- child->document()->ownerElement()->scheduleLayerUpdate();
- }
-
- // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so
- // we need to schedule a style recalc in our parent document.
- if (HTMLFrameOwnerElement* ownerElement = m_renderView->document().ownerElement())
- ownerElement->scheduleLayerUpdate();
-}
-
-bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
-{
- const RenderStyle* style = layer->renderer()->style();
- RenderLayerStackingNode* stackingNode = const_cast<RenderLayer*>(layer)->stackingNode();
-
- if (style &&
- (style->transformStyle3D() == TransformStyle3DPreserve3D ||
- style->hasPerspective() ||
- style->transform().has3DOperation()))
- return true;
-
- stackingNode->updateLayerListsIfNeeded();
-
-#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(stackingNode);
-#endif
-
- RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), AllChildren);
- while (RenderLayerStackingNode* curNode = iterator.next()) {
- if (layerHas3DContent(curNode->layer()))
- return true;
- }
-
- return false;
-}
-
-static bool isRootmostFixedOrStickyLayer(RenderLayer* layer)
-{
- if (layer->renderer()->isStickyPositioned())
- return true;
-
- if (layer->renderer()->style()->position() != FixedPosition)
- return false;
-
- for (RenderLayerStackingNode* stackingContainerNode = layer->stackingNode()->ancestorStackingContainerNode(); stackingContainerNode; stackingContainerNode = stackingContainerNode->ancestorStackingContainerNode()) {
- if (stackingContainerNode->layer()->hasCompositedLayerMapping() && stackingContainerNode->layer()->renderer()->style()->position() == FixedPosition)
- return false;
- }
-
- return true;
-}
-
-void RenderLayerCompositor::updateViewportConstraintStatus(RenderLayer* layer)
-{
- if (isRootmostFixedOrStickyLayer(layer))
- addViewportConstrainedLayer(layer);
- else
- removeViewportConstrainedLayer(layer);
-}
-
-void RenderLayerCompositor::addViewportConstrainedLayer(RenderLayer* layer)
-{
- m_viewportConstrainedLayers.add(layer);
-}
-
-void RenderLayerCompositor::removeViewportConstrainedLayer(RenderLayer* layer)
-{
- if (!m_viewportConstrainedLayers.contains(layer))
- return;
-
- m_viewportConstrainedLayers.remove(layer);
-}
-
-FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportConstraints(RenderLayer* layer) const
-{
- ASSERT(layer->hasCompositedLayerMapping());
-
- FrameView* frameView = m_renderView->frameView();
- LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
-
- FixedPositionViewportConstraints constraints;
-
- GraphicsLayer* graphicsLayer = layer->compositedLayerMapping()->mainGraphicsLayer();
-
- constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
- constraints.setViewportRectAtLastLayout(viewportRect);
-
- RenderStyle* style = layer->renderer()->style();
- if (!style->left().isAuto())
- constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
-
- if (!style->right().isAuto())
- constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight);
-
- if (!style->top().isAuto())
- constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
-
- if (!style->bottom().isAuto())
- constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom);
-
- // If left and right are auto, use left.
- if (style->left().isAuto() && style->right().isAuto())
- constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
-
- // If top and bottom are auto, use top.
- if (style->top().isAuto() && style->bottom().isAuto())
- constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
-
- return constraints;
-}
-
-StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportConstraints(RenderLayer* layer) const
-{
- ASSERT(layer->hasCompositedLayerMapping());
-
- FrameView* frameView = m_renderView->frameView();
- LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
-
- StickyPositionViewportConstraints constraints;
-
- RenderBoxModelObject* renderer = toRenderBoxModelObject(layer->renderer());
-
- renderer->computeStickyPositionConstraints(constraints, viewportRect);
-
- GraphicsLayer* graphicsLayer = layer->compositedLayerMapping()->mainGraphicsLayer();
-
- constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
- constraints.setStickyOffsetAtLastLayout(renderer->stickyPositionOffset());
-
- return constraints;
-}
-
-ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const
-{
- if (Page* page = this->page())
- return page->scrollingCoordinator();
-
- return 0;
-}
-
-GraphicsLayerFactory* RenderLayerCompositor::graphicsLayerFactory() const
-{
- if (Page* page = this->page())
- return page->chrome().client().graphicsLayerFactory();
- return 0;
-}
-
-Page* RenderLayerCompositor::page() const
-{
- return m_renderView->frameView()->frame().page();
-}
-
-String RenderLayerCompositor::debugName(const GraphicsLayer* graphicsLayer)
-{
- String name;
- if (graphicsLayer == m_rootContentLayer.get()) {
- name = "Content Root Layer";
-#if USE(RUBBER_BANDING)
- } else if (graphicsLayer == m_layerForOverhangShadow.get()) {
- name = "Overhang Areas Shadow";
-#endif
- } else if (graphicsLayer == m_overflowControlsHostLayer.get()) {
- name = "Overflow Controls Host Layer";
- } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
- name = "Horizontal Scrollbar Layer";
- } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
- name = "Vertical Scrollbar Layer";
- } else if (graphicsLayer == m_layerForScrollCorner.get()) {
- name = "Scroll Corner Layer";
- } else if (graphicsLayer == m_containerLayer.get()) {
- name = "Frame Clipping Layer";
- } else if (graphicsLayer == m_scrollLayer.get()) {
- name = "Frame Scrolling Layer";
- } else {
- ASSERT_NOT_REACHED();
- }
-
- return name;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.h
deleted file mode 100644
index 162348c866c..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerCompositor.h
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (C) 2009 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 RenderLayerCompositor_h
-#define RenderLayerCompositor_h
-
-#include "core/page/ChromeClient.h"
-#include "core/rendering/RenderLayer.h"
-#include "platform/graphics/GraphicsLayerClient.h"
-#include "wtf/HashMap.h"
-
-namespace WebCore {
-
-class FixedPositionViewportConstraints;
-class GraphicsLayer;
-class RenderEmbeddedObject;
-class RenderLayerStackingNode;
-class RenderPart;
-class RenderVideo;
-class ScrollingCoordinator;
-class StickyPositionViewportConstraints;
-
-
-enum CompositingUpdateType {
- CompositingUpdateAfterStyleChange,
- CompositingUpdateAfterLayout,
- CompositingUpdateOnScroll,
- CompositingUpdateOnCompositedScroll,
- CompositingUpdateFinishAllDeferredWork
-};
-
-// RenderLayerCompositor manages the hierarchy of
-// composited RenderLayers. It determines which RenderLayers
-// become compositing, and creates and maintains a hierarchy of
-// GraphicsLayers based on the RenderLayer painting order.
-//
-// There is one RenderLayerCompositor per RenderView.
-
-class RenderLayerCompositor : public GraphicsLayerClient {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- explicit RenderLayerCompositor(RenderView*);
- ~RenderLayerCompositor();
-
- // Return true if this RenderView is in "compositing mode" (i.e. has one or more
- // composited RenderLayers)
- bool inCompositingMode() const { return m_compositing; }
- // 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; }
- bool layerSquashingEnabled() const;
-
- bool canRender3DTransforms() const;
-
- // Copy the accelerated compositing related flags from Settings
- void cacheAcceleratedCompositingFlags();
-
- // Called when the layer hierarchy needs to be updated (compositing layers have been
- // created, destroyed or re-parented).
- void setCompositingLayersNeedRebuild(bool needRebuild = true);
- bool compositingLayersNeedRebuild() const { return m_compositingLayersNeedRebuild; }
-
- // Called when something outside WebKit affects the visible rect (e.g. delegated scrolling). Might schedule a layer flush.
- void didChangeVisibleRect();
-
- // Updating properties required for determining if compositing is necessary.
- void updateCompositingRequirementsState();
- void setNeedsUpdateCompositingRequirementsState() { m_needsUpdateCompositingRequirementsState = true; }
-
- // Main entry point for a full update. As needed, this function will compute compositing requirements,
- // rebuild the composited layer tree, and/or update all the properties assocaited with each layer of the
- // composited layer tree.
- void updateCompositingLayers(CompositingUpdateType);
-
- // Update the compositing state of the given layer. Returns true if that state changed.
- bool updateLayerCompositingState(RenderLayer*);
-
- // Update the geometry for compositing children of compositingAncestor.
- void updateCompositingDescendantGeometry(RenderLayerStackingNode* compositingAncestor, RenderLayer*, bool compositedChildrenOnly);
-
- // Whether layer's compositedLayerMapping needs a GraphicsLayer to do clipping by an ancestor (non-stacking-context parent with overflow).
- bool clippedByAncestor(const RenderLayer*) const;
- // Whether layer's compositedLayerMapping needs a GraphicsLayer to clip z-order children of the given RenderLayer.
- bool clipsCompositingDescendants(const RenderLayer*) const;
-
- // Whether the given layer needs an extra 'contents' layer.
- bool needsContentsCompositingLayer(const RenderLayer*) const;
-
- bool supportsFixedRootBackgroundCompositing() const;
- bool needsFixedRootBackgroundLayer(const RenderLayer*) const;
- GraphicsLayer* fixedRootBackgroundLayer() const;
-
- // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
- // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only.
- IntRect calculateCompositedBounds(const RenderLayer*, const RenderLayer* ancestorLayer) const;
-
- // Repaint the appropriate layers when the given RenderLayer starts or stops being composited.
- void repaintOnCompositingChange(RenderLayer*);
-
- void repaintInCompositedAncestor(RenderLayer*, const LayoutRect&);
-
- // Notify us that a layer has been added or removed
- void layerWasAdded(RenderLayer* parent, RenderLayer* child);
- void layerWillBeRemoved(RenderLayer* parent, RenderLayer* child);
-
- // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context
- RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const;
-
- // Repaint parts of all composited layers that intersect the given absolute rectangle (or the entire layer if the pointer is null).
- void repaintCompositedLayers(const IntRect* = 0);
-
- RenderLayer* rootRenderLayer() const;
- GraphicsLayer* rootGraphicsLayer() const;
- GraphicsLayer* scrollLayer() const;
-
- enum RootLayerAttachment {
- RootLayerUnattached,
- RootLayerAttachedViaChromeClient,
- RootLayerAttachedViaEnclosingFrame
- };
-
- RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
- void updateRootLayerAttachment();
- void updateRootLayerPosition();
-
- void setIsInWindow(bool);
-
- void clearMappingForAllRenderLayers();
-
- // Use by RenderVideo to ask if it should try to use accelerated compositing.
- bool canAccelerateVideoRendering(RenderVideo*) const;
-
- // Walk the tree looking for layers with 3d transforms. Useful in case you need
- // to know if there is non-affine content, e.g. for drawing into an image.
- bool has3DContent() const;
-
- static RenderLayerCompositor* frameContentsCompositor(RenderPart*);
- // Return true if the layers changed.
- static bool parentFrameContentLayers(RenderPart*);
-
- // Update the geometry of the layers used for clipping and scrolling in frames.
- void frameViewDidChangeLocation(const IntPoint& contentsOffset);
- void frameViewDidChangeSize();
- void frameViewDidScroll();
- void frameViewDidLayout();
- void frameViewScrollbarsExistenceDidChange();
- void rootFixedBackgroundsChanged();
-
- bool scrollingLayerDidChange(RenderLayer*);
-
- String layerTreeAsText(LayerTreeFlags);
-
- virtual void didCommitChangesForLayer(const GraphicsLayer*) const OVERRIDE;
-
- GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
- GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
- GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
-
- void updateViewportConstraintStatus(RenderLayer*);
- void removeViewportConstrainedLayer(RenderLayer*);
-
- void addOutOfFlowPositionedLayer(RenderLayer*);
- void removeOutOfFlowPositionedLayer(RenderLayer*);
-
- void resetTrackedRepaintRects();
- void setTracksRepaints(bool);
-
- void setNeedsToRecomputeCompositingRequirements() { m_needsToRecomputeCompositingRequirements = true; }
-
- virtual String debugName(const GraphicsLayer*) OVERRIDE;
-
-private:
- class OverlapMap;
-
- // GraphicsLayerClient implementation
- virtual void notifyAnimationStarted(const GraphicsLayer*, double, double) OVERRIDE { }
- virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&) OVERRIDE;
-
- virtual bool isTrackingRepaints() const OVERRIDE;
-
- // Whether the given RL needs to paint into its own separate backing (and hence would need its own CompositedLayerMapping).
- bool needsOwnBacking(const RenderLayer*) const;
- // Whether the layer could ever be composited.
- bool canBeComposited(const RenderLayer*) const;
-
- // Returns all direct reasons that a layer should be composited.
- CompositingReasons directReasonsForCompositing(const RenderLayer*) const;
-
- void updateDirectCompositingReasons(RenderLayer*);
-
- // Returns indirect reasons that a layer should be composited because of something in its subtree.
- CompositingReasons subtreeReasonsForCompositing(RenderObject*, bool hasCompositedDescendants, bool has3DTransformedDescendants) const;
-
- // Make or destroy the CompositedLayerMapping for this layer; returns true if the compositedLayerMapping changed.
- bool allocateOrClearCompositedLayerMapping(RenderLayer*);
-
- void clearMappingForRenderLayerIncludingDescendants(RenderLayer*);
-
- // Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
- void recursiveRepaintLayer(RenderLayer*, const IntRect* = 0);
-
- void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
- void addToOverlapMapRecursive(OverlapMap&, RenderLayer*, RenderLayer* ancestorLayer = 0);
-
- struct SquashingState {
- SquashingState()
- : mostRecentMapping(0)
- , hasMostRecentMapping(false)
- , nextSquashedLayerIndex(0) { }
-
- void updateSquashingStateForNewMapping(CompositedLayerMappingPtr, bool hasNewCompositedLayerMapping, IntPoint newOffsetFromAbsolute);
-
- // The most recent composited backing that the layer should squash onto if needed.
- CompositedLayerMappingPtr mostRecentMapping;
- bool hasMostRecentMapping;
-
- // Offset in absolute coordinates of the compositedLayerMapping's owning layer.
- IntPoint offsetFromAbsolute;
-
- // Counter that tracks what index the next RenderLayer would be if it gets squashed to the current squashing layer.
- size_t nextSquashedLayerIndex;
- };
-
- // Forces an update for all frames of frame tree recursively. Used only when the mainFrame compositor is ready to
- // finish all deferred work.
- static void finishCompositingUpdateForFrameTree(Frame*);
-
- // Returns true if any layer's compositing changed
- void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer*, OverlapMap*, struct CompositingRecursionData&, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants);
-
- // Defines which RenderLayers will paint into which composited backings, by allocating and destroying CompositedLayerMappings as needed.
- void assignLayersToBackings(RenderLayer*, bool& layersChanged);
- void assignLayersToBackingsInternal(RenderLayer*, SquashingState&, 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, int depth);
-
- // Recurses down the tree, updating layer geometry only.
- void updateLayerTreeGeometry(RenderLayer*);
-
- // Hook compositing layers together
- void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
- void removeCompositedChildren(RenderLayer*);
-
- bool layerHas3DContent(const RenderLayer*) const;
- bool isRunningAcceleratedTransformAnimation(RenderObject*) const;
-
- bool hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const;
-
- void ensureRootLayer();
- void destroyRootLayer();
-
- void attachRootLayer(RootLayerAttachment);
- void detachRootLayer();
-
- bool isMainFrame() const;
-
- void updateOverflowControlsLayers();
-
- void notifyIFramesOfCompositingChange();
-
- Page* page() const;
-
- GraphicsLayerFactory* graphicsLayerFactory() const;
- ScrollingCoordinator* scrollingCoordinator() const;
-
- // Whether a running transition or animation enforces the need for a compositing layer.
- bool requiresCompositingForAnimation(RenderObject*) const;
- // Whether a (not necessarily running) transition enforces the need for a compositing layer.
- bool requiresCompositingForTransition(RenderObject*) const;
- bool requiresCompositingForTransform(RenderObject*) const;
- bool requiresCompositingForVideo(RenderObject*) const;
- bool requiresCompositingForCanvas(RenderObject*) const;
- bool requiresCompositingForPlugin(RenderObject*) const;
- bool requiresCompositingForFrame(RenderObject*) const;
- bool requiresCompositingForBackfaceVisibilityHidden(RenderObject*) const;
- bool requiresCompositingForFilters(RenderObject*) const;
- bool requiresCompositingForOverflowScrollingParent(const RenderLayer*) const;
- bool requiresCompositingForOutOfFlowClipping(const RenderLayer*) const;
- bool requiresCompositingForScrollableFrame() const;
- bool requiresCompositingForPosition(RenderObject*, const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason* = 0) const;
- bool requiresCompositingForOverflowScrolling(const RenderLayer*) const;
-
- void addViewportConstrainedLayer(RenderLayer*);
-
- FixedPositionViewportConstraints computeFixedViewportConstraints(RenderLayer*) const;
- StickyPositionViewportConstraints computeStickyViewportConstraints(RenderLayer*) const;
-
- bool requiresHorizontalScrollbarLayer() const;
- bool requiresVerticalScrollbarLayer() const;
- bool requiresScrollCornerLayer() const;
-#if USE(RUBBER_BANDING)
- bool requiresOverhangLayers() const;
-#endif
-
-private:
- RenderView* m_renderView;
- OwnPtr<GraphicsLayer> m_rootContentLayer;
-
- bool m_hasAcceleratedCompositing;
- ChromeClient::CompositingTriggerFlags m_compositingTriggers;
-
- bool m_showRepaintCounter;
-
- // FIXME: This should absolutely not be mutable.
- mutable bool m_needsToRecomputeCompositingRequirements;
- bool m_needsToUpdateLayerTreeGeometry;
-
- bool m_compositing;
- bool m_compositingLayersNeedRebuild;
- bool m_forceCompositingMode;
- bool m_inPostLayoutUpdate; // true when it's OK to trust layout information (e.g. layer sizes and positions)
- bool m_needsUpdateCompositingRequirementsState;
-
- bool m_isTrackingRepaints; // Used for testing.
-
- RootLayerAttachment m_rootLayerAttachment;
-
- // Enclosing container layer, which clips for iframe content
- OwnPtr<GraphicsLayer> m_containerLayer;
- OwnPtr<GraphicsLayer> m_scrollLayer;
-
- HashSet<RenderLayer*> m_viewportConstrainedLayers;
- HashSet<RenderLayer*> m_viewportConstrainedLayersNeedingUpdate;
-
- // This is used in updateCompositingRequirementsState to avoid full tree
- // walks while determining if layers have unclipped descendants.
- HashSet<RenderLayer*> m_outOfFlowPositionedLayers;
-
- // Enclosing layer for overflow controls and the clipping layer
- OwnPtr<GraphicsLayer> m_overflowControlsHostLayer;
-
- // Layers for overflow controls
- OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
- OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
- OwnPtr<GraphicsLayer> m_layerForScrollCorner;
-#if USE(RUBBER_BANDING)
- OwnPtr<GraphicsLayer> m_layerForOverhangShadow;
-#endif
-};
-
-
-} // namespace WebCore
-
-#endif // RenderLayerCompositor_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.cpp
index 600ced9e77a..1d0ff416d46 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.cpp
@@ -39,8 +39,6 @@
#include "core/svg/SVGFilterElement.h"
#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
#include "core/svg/graphics/filters/SVGFilter.h"
-#include "platform/graphics/filters/custom/CustomFilterOperation.h"
-#include "platform/graphics/filters/custom/CustomFilterProgram.h"
namespace WebCore {
@@ -95,7 +93,6 @@ RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer)
RenderLayerFilterInfo::~RenderLayerFilterInfo()
{
- removeCustomFilterClients();
removeReferenceFilterClients();
}
@@ -107,8 +104,12 @@ void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> rendere
void RenderLayerFilterInfo::notifyFinished(Resource*)
{
RenderObject* renderer = m_layer->renderer();
- toElement(renderer->node())->scheduleLayerUpdate();
- renderer->repaint();
+ // FIXME: This caller of scheduleSVGFilterLayerUpdateHack() is not correct. It's using the layer update
+ // system to trigger a RenderLayer to go through the filter updating logic, but that might not
+ // even happen if this element is style sharing and RenderObject::setStyle() returns early.
+ // Filters need to find a better way to hook into the system.
+ toElement(renderer->node())->scheduleSVGFilterLayerUpdateHack();
+ renderer->paintInvalidationForWholeRenderer();
}
void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations)
@@ -130,7 +131,7 @@ void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations&
// Reference is internal; add layer as a client so we can trigger
// filter repaint on SVG attribute change.
Element* filter = m_layer->renderer()->node()->document().getElementById(referenceFilterOperation->fragment());
- if (!filter || !filter->hasTagName(SVGNames::filterTag))
+ if (!isSVGFilterElement(filter))
continue;
if (filter->renderer())
toRenderSVGResourceContainer(filter->renderer())->addClientRenderLayer(m_layer);
@@ -156,39 +157,5 @@ void RenderLayerFilterInfo::removeReferenceFilterClients()
m_internalSVGReferences.clear();
}
-void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
-{
- RenderObject* renderer = m_layer->renderer();
- toElement(renderer->node())->scheduleLayerUpdate();
- 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->type() != FilterOperation::CUSTOM)
- continue;
- RefPtr<CustomFilterProgram> program = toCustomFilterOperation(filterOperation)->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();
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.h
index f982008fc55..4c84861c4b2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerFilterInfo.h
@@ -34,7 +34,6 @@
#include "core/fetch/DocumentResource.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/filters/FilterOperation.h"
-#include "platform/graphics/filters/custom/CustomFilterProgramClient.h"
#include "wtf/HashMap.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
@@ -48,7 +47,7 @@ class RenderLayerFilterInfo;
typedef HashMap<const RenderLayer*, RenderLayerFilterInfo*> RenderLayerFilterInfoMap;
-class RenderLayerFilterInfo : public CustomFilterProgramClient, public DocumentResourceClient {
+class RenderLayerFilterInfo FINAL : public DocumentResourceClient {
public:
static RenderLayerFilterInfo* filterInfoForRenderLayer(const RenderLayer*);
static RenderLayerFilterInfo* createFilterInfoForRenderLayerIfNeeded(RenderLayer*);
@@ -61,30 +60,21 @@ public:
FilterEffectRenderer* renderer() const { return m_renderer.get(); }
void setRenderer(PassRefPtr<FilterEffectRenderer>);
- // Implementation of the CustomFilterProgramClient interface.
- virtual void notifyCustomFilterProgramLoaded(CustomFilterProgram*);
-
- void updateCustomFilterClients(const FilterOperations&);
- void removeCustomFilterClients();
-
void updateReferenceFilterClients(const FilterOperations&);
- virtual void notifyFinished(Resource*);
+ virtual void notifyFinished(Resource*) OVERRIDE;
void removeReferenceFilterClients();
private:
RenderLayerFilterInfo(RenderLayer*);
- ~RenderLayerFilterInfo();
+ virtual ~RenderLayerFilterInfo();
RenderLayer* m_layer;
RefPtr<FilterEffectRenderer> m_renderer;
LayoutRect m_dirtySourceRect;
- typedef Vector<RefPtr<CustomFilterProgram> > CustomFilterProgramList;
- CustomFilterProgramList m_cachedCustomFilterPrograms;
-
static RenderLayerFilterInfoMap* s_filterMap;
- Vector<RefPtr<Element> > m_internalSVGReferences;
+ WillBePersistentHeapVector<RefPtrWillBeMember<Element> > m_internalSVGReferences;
Vector<ResourcePtr<DocumentResource> > m_externalSVGReferences;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.cpp
index 801c0af5199..cb617a2e8a4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.cpp
@@ -25,7 +25,7 @@
#include "config.h"
#include "core/rendering/RenderLayerModelObject.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
@@ -53,10 +53,10 @@ void RenderLayerModelObject::destroyLayer()
m_layer = nullptr;
}
-void RenderLayerModelObject::createLayer()
+void RenderLayerModelObject::createLayer(LayerType type)
{
ASSERT(!m_layer);
- m_layer = adoptPtr(new RenderLayer(this));
+ m_layer = adoptPtr(new RenderLayer(this, type));
setHasLayer(true);
m_layer->insertOnlyThisLayer();
}
@@ -75,7 +75,7 @@ void RenderLayerModelObject::willBeDestroyed()
{
if (isPositioned()) {
// Don't use this->view() because the document's renderView has been set to 0 during destruction.
- if (Frame* frame = this->frame()) {
+ if (LocalFrame* frame = this->frame()) {
if (FrameView* frameView = frame->view()) {
if (style()->hasViewportConstrainedPosition())
frameView->removeViewportConstrainedObject(this);
@@ -88,43 +88,29 @@ void RenderLayerModelObject::willBeDestroyed()
destroyLayer();
}
-void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
s_wasFloating = isFloating();
// If our z-index changes value or our visibility changes,
// we need to dirty our stacking context's z-order list.
RenderStyle* oldStyle = style();
- if (oldStyle && newStyle) {
- if (parent()) {
- // Do a repaint with the old style first, e.g., for example if we go from
- // having an outline to not having an outline.
- if (diff == StyleDifferenceRepaintLayer) {
- layer()->repainter().repaintIncludingDescendants();
- if (!(oldStyle->clip() == newStyle->clip()))
- layer()->clipper().clearClipRectsIncludingDescendants();
- } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < oldStyle->outlineSize())
- repaint();
- }
-
- if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
- // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
- // end up being destroyed.
+ if (oldStyle) {
+ // Do a repaint with the old style first through RenderLayerRepainter.
+ // RenderObject::styleWillChange takes care of repainting objects without RenderLayers.
+ if (parent() && diff.needsRepaintLayer()) {
+ layer()->repainter().repaintIncludingNonCompositingDescendants();
+ if (oldStyle->hasClip() != newStyle.hasClip()
+ || oldStyle->clip() != newStyle.clip())
+ layer()->clipper().clearClipRectsIncludingDescendants();
+ } else if (diff.needsFullLayout()) {
if (hasLayer()) {
- if (oldStyle->position() != newStyle->position()
- || oldStyle->zIndex() != newStyle->zIndex()
- || oldStyle->hasAutoZIndex() != newStyle->hasAutoZIndex()
- || !(oldStyle->clip() == newStyle->clip())
- || oldStyle->hasClip() != newStyle->hasClip()
- || oldStyle->opacity() != newStyle->opacity()
- || oldStyle->transform() != newStyle->transform()
- || oldStyle->filter() != newStyle->filter()
- )
- layer()->repainter().repaintIncludingDescendants();
- } else if (newStyle->hasTransform() || newStyle->opacity() < 1 || newStyle->hasFilter()) {
+ if (!layer()->hasCompositedLayerMapping() && oldStyle->position() != newStyle.position())
+ layer()->repainter().repaintIncludingNonCompositingDescendants();
+ } 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();
+ paintInvalidationForWholeRenderer();
}
}
}
@@ -135,22 +121,27 @@ void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderS
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
bool hadTransform = hasTransform();
- bool hadLayer = hasLayer();
- bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer();
RenderObject::styleDidChange(diff, oldStyle);
updateFromStyle();
- if (requiresLayer()) {
+ LayerType type = layerTypeRequired();
+ if (type != NoLayer) {
if (!layer() && layerCreationAllowedForSubtree()) {
if (s_wasFloating && isFloating())
setChildNeedsLayout();
- createLayer();
+ createLayer(type);
if (parent() && !needsLayout() && containingBlock()) {
- layer()->repainter().setRepaintStatus(NeedsFullRepaint);
- // There is only one layer to update, it is not worth using |cachedOffset| since
- // we are not sure the value will be used.
- layer()->updateLayerPositions(0);
+ // FIXME: This invalidation is overly broad. We should update to
+ // do the correct invalidation at RenderStyle::diff time. crbug.com/349061
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ layer()->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
+ else
+ layer()->repainter().setRepaintStatus(NeedsFullRepaint);
+ // Hit in animations/interpolation/perspective-interpolation.html
+ // FIXME: I suspect we can remove this assert disabler now.
+ DisableCompositingQueryAsserts disabler;
+ layer()->updateLayerPositionRecursive();
}
}
} else if (layer() && layer()->parent()) {
@@ -160,13 +151,14 @@ void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderSt
if (s_wasFloating && isFloating())
setChildNeedsLayout();
if (hadTransform)
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
if (layer()) {
+ // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer
+ // from the style.
+ layer()->setLayerType(type);
layer()->styleChanged(diff, oldStyle);
- if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting)
- setChildNeedsLayout();
}
if (FrameView *frameView = view()->frameView()) {
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.h
index 4eb42633a7f..d3153e6217e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerModelObject.h
@@ -23,7 +23,7 @@
#ifndef RenderLayerModelObject_h
#define RenderLayerModelObject_h
-#include "core/rendering/CompositedLayerMappingPtr.h"
+#include "core/rendering/compositing/CompositedLayerMappingPtr.h"
#include "core/rendering/RenderObject.h"
namespace WebCore {
@@ -32,6 +32,15 @@ class RenderLayer;
class CompositedLayerMapping;
class ScrollableArea;
+enum LayerType {
+ NoLayer,
+ NormalLayer,
+ // A forced or overflow clip layer is required for bookkeeping purposes,
+ // but does not force a layer to be self painting.
+ OverflowClipLayer,
+ ForcedLayer
+};
+
class RenderLayerModelObject : public RenderObject {
public:
explicit RenderLayerModelObject(ContainerNode*);
@@ -44,11 +53,11 @@ public:
RenderLayer* layer() const { return m_layer.get(); }
ScrollableArea* scrollableArea() const;
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
virtual void updateFromStyle() { }
- virtual bool requiresLayer() const = 0;
+ virtual LayerType layerTypeRequired() const = 0;
// Returns true if the background is painted opaque in the given rect.
// The query rect is given in local coordinate system.
@@ -62,7 +71,7 @@ public:
CompositedLayerMapping* groupedMapping() const;
protected:
- void createLayer();
+ void createLayer(LayerType);
virtual void willBeDestroyed() OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.cpp
index 38801bdbdc4..f6e2d9e5de3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.cpp
@@ -55,20 +55,20 @@
namespace WebCore {
-RenderLayerReflectionInfo::RenderLayerReflectionInfo(RenderBox* renderer)
- : m_renderer(renderer)
+RenderLayerReflectionInfo::RenderLayerReflectionInfo(RenderBox& renderer)
+ : m_box(renderer)
, m_isPaintingInsideReflection(false)
{
- UseCounter::count(m_renderer->document(), UseCounter::Reflection);
+ UseCounter::count(m_box.document(), UseCounter::Reflection);
- m_reflection = RenderReplica::createAnonymous(&(m_renderer->document()));
- m_reflection->setParent(m_renderer); // We create a 1-way connection.
+ m_reflection = RenderReplica::createAnonymous(&(m_box.document()));
+ m_reflection->setParent(&m_box); // We create a 1-way connection.
}
RenderLayerReflectionInfo::~RenderLayerReflectionInfo()
{
if (!m_reflection->documentBeingDestroyed())
- m_reflection->removeLayers(renderer()->layer());
+ m_reflection->removeLayers(m_box.layer());
m_reflection->setParent(0);
m_reflection->destroy();
@@ -84,16 +84,16 @@ RenderLayer* RenderLayerReflectionInfo::reflectionLayer() const
void RenderLayerReflectionInfo::updateAfterStyleChange(const RenderStyle* oldStyle)
{
RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(renderer()->style());
+ newStyle->inheritFrom(m_box.style());
// Map in our transform.
TransformOperations transform;
- switch (renderer()->style()->boxReflect()->direction()) {
+ switch (m_box.style()->boxReflect()->direction()) {
case ReflectionBelow:
transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed),
Length(100., Percent), TransformOperation::Translate));
transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed),
- renderer()->style()->boxReflect()->offset(), TransformOperation::Translate));
+ m_box.style()->boxReflect()->offset(), TransformOperation::Translate));
transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::Scale));
break;
@@ -102,14 +102,14 @@ void RenderLayerReflectionInfo::updateAfterStyleChange(const RenderStyle* oldSty
transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed),
Length(100., Percent), TransformOperation::Translate));
transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed),
- renderer()->style()->boxReflect()->offset(), TransformOperation::Translate));
+ m_box.style()->boxReflect()->offset(), TransformOperation::Translate));
break;
case ReflectionRight:
transform.operations().append(TranslateTransformOperation::create(Length(100., Percent),
Length(0, Fixed), TransformOperation::Translate));
transform.operations().append(TranslateTransformOperation::create(
- renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::Translate));
+ m_box.style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::Translate));
transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::Scale));
break;
@@ -118,13 +118,13 @@ void RenderLayerReflectionInfo::updateAfterStyleChange(const RenderStyle* oldSty
transform.operations().append(TranslateTransformOperation::create(Length(100., Percent),
Length(0, Fixed), TransformOperation::Translate));
transform.operations().append(TranslateTransformOperation::create(
- renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::Translate));
+ m_box.style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::Translate));
break;
}
newStyle->setTransform(transform);
// Map in our mask.
- newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
+ newStyle->setMaskBoxImage(m_box.style()->boxReflect()->mask());
m_reflection->setStyle(newStyle.release());
}
@@ -142,7 +142,7 @@ void RenderLayerReflectionInfo::paint(GraphicsContext* context, const LayerPaint
String RenderLayerReflectionInfo::debugName() const
{
- return renderer()->debugName() + " (reflection)";
+ return m_box.debugName() + " (reflection)";
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.h
index 90ec7898acf..83009eb0b91 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerReflectionInfo.h
@@ -57,7 +57,7 @@ class RenderReplica;
class RenderLayerReflectionInfo {
WTF_MAKE_NONCOPYABLE(RenderLayerReflectionInfo);
public:
- explicit RenderLayerReflectionInfo(RenderBox*);
+ explicit RenderLayerReflectionInfo(RenderBox&);
~RenderLayerReflectionInfo();
RenderReplica* reflection() const { return m_reflection; }
@@ -72,9 +72,7 @@ public:
String debugName() const;
private:
- RenderBox* renderer() const { return m_renderer; }
-
- RenderBox* m_renderer;
+ RenderBox& m_box;
RenderReplica* m_reflection;
// A state bit tracking if we are painting inside a replica.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.cpp
index 77da5c125d9..d502c3cf52c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.cpp
@@ -44,44 +44,49 @@
#include "config.h"
#include "core/rendering/RenderLayerRepainter.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/FilterEffectRenderer.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
namespace WebCore {
-RenderLayerRepainter::RenderLayerRepainter(RenderLayerModelObject* renderer)
+RenderLayerRepainter::RenderLayerRepainter(RenderLayerModelObject& renderer)
: m_renderer(renderer)
, m_repaintStatus(NeedsNormalRepaint)
{
}
-void RenderLayerRepainter::repaintAfterLayout(RenderGeometryMap* geometryMap, bool shouldCheckForRepaint)
+void RenderLayerRepainter::repaintAfterLayout(bool shouldCheckForRepaint)
{
- if (m_renderer->layer()->hasVisibleContent()) {
- RenderView* view = m_renderer->view();
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ return;
+
+ // FIXME: really, we're in the repaint phase here, and the following queries are legal.
+ // Until those states are fully fledged, I'll just disable the ASSERTS.
+ DisableCompositingQueryAsserts disabler;
+ if (m_renderer.layer()->hasVisibleContent()) {
+ RenderView* view = m_renderer.view();
ASSERT(view);
// FIXME: LayoutState does not work with RenderLayers as there is not a 1-to-1
// mapping between them and the RenderObjects. It would be neat to enable
// LayoutState outside the layout() phase and use it here.
- ASSERT(!view->layoutStateEnabled());
+ ASSERT(!view->layoutStateCachedOffsetsEnabled());
- RenderLayerModelObject* repaintContainer = m_renderer->containerForRepaint();
+ const RenderLayerModelObject* repaintContainer = m_renderer.containerForPaintInvalidation();
LayoutRect oldRepaintRect = m_repaintRect;
- LayoutRect oldOutlineBox = m_outlineBox;
- computeRepaintRects(repaintContainer, geometryMap);
+ LayoutPoint oldOffset = m_offset;
+ computeRepaintRects();
+ shouldCheckForRepaint &= shouldRepaintLayer();
- // FIXME: Should ASSERT that value calculated for m_outlineBox using the cached offset is the same
- // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
if (shouldCheckForRepaint) {
if (view && !view->document().printing()) {
if (m_repaintStatus & NeedsFullRepaint) {
- m_renderer->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldRepaintRect));
+ m_renderer.invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldRepaintRect), InvalidationLayer);
if (m_repaintRect != oldRepaintRect)
- m_renderer->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_repaintRect));
- } else if (shouldRepaintAfterLayout()) {
- m_renderer->repaintAfterLayoutIfNeeded(repaintContainer, m_renderer->selfNeedsLayout(), oldRepaintRect, oldOutlineBox, &m_repaintRect, &m_outlineBox);
+ m_renderer.invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_repaintRect), InvalidationLayer);
+ } else {
+ m_renderer.invalidatePaintAfterLayoutIfNeeded(repaintContainer, m_renderer.selfNeedsLayout(), oldRepaintRect, oldOffset, &m_repaintRect, &m_offset);
}
}
}
@@ -95,57 +100,83 @@ void RenderLayerRepainter::repaintAfterLayout(RenderGeometryMap* geometryMap, bo
void RenderLayerRepainter::clearRepaintRects()
{
- ASSERT(!m_renderer->layer()->hasVisibleContent());
+ ASSERT(!m_renderer.layer()->hasVisibleContent());
m_repaintRect = IntRect();
- m_outlineBox = IntRect();
}
-void RenderLayerRepainter::computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
+void RenderLayerRepainter::computeRepaintRects()
{
- m_repaintRect = m_renderer->clippedOverflowRectForRepaint(repaintContainer);
- m_outlineBox = m_renderer->outlineBoundsForRepaint(repaintContainer, geometryMap);
+ const RenderLayerModelObject* repaintContainer = m_renderer.containerForPaintInvalidation();
+ LayoutRect repaintRect = m_renderer.boundsRectForPaintInvalidation(repaintContainer);
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ // FIXME: We want RenderLayerRepainter to go away when
+ // repaint-after-layout is on by default so we need to figure out how to
+ // handle this update.
+ m_renderer.setPreviousPaintInvalidationRect(repaintRect);
+ } else {
+ m_repaintRect = repaintRect;
+ m_offset = RenderLayer::positionFromPaintInvalidationContainer(&m_renderer, repaintContainer);
+ }
}
-void RenderLayerRepainter::computeRepaintRectsIncludingDescendants()
+void RenderLayerRepainter::computeRepaintRectsIncludingNonCompositingDescendants()
{
// FIXME: computeRepaintRects() has to walk up the parent chain for every layer to compute the rects.
// We should make this more efficient.
// FIXME: it's wrong to call this when layout is not up-to-date, which we do.
- computeRepaintRects(m_renderer->containerForRepaint());
+ computeRepaintRects();
- for (RenderLayer* layer = m_renderer->layer()->firstChild(); layer; layer = layer->nextSibling())
- layer->repainter().computeRepaintRectsIncludingDescendants();
+ for (RenderLayer* layer = m_renderer.layer()->firstChild(); layer; layer = layer->nextSibling()) {
+ if (layer->compositingState() != PaintsIntoOwnBacking && layer->compositingState() != PaintsIntoGroupedBacking)
+ layer->repainter().computeRepaintRectsIncludingNonCompositingDescendants();
+ }
}
-inline bool RenderLayerRepainter::shouldRepaintAfterLayout() const
+inline bool RenderLayerRepainter::shouldRepaintLayer() const
{
- if (m_repaintStatus == NeedsNormalRepaint)
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ return false;
+
+ if (m_repaintStatus != NeedsFullRepaintForPositionedMovementLayout)
return true;
// Composited layers that were moved during a positioned movement only
// layout, don't need to be repainted. They just need to be recomposited.
- ASSERT(m_repaintStatus == NeedsFullRepaintForPositionedMovementLayout);
- return m_renderer->compositingState() != PaintsIntoOwnBacking;
+ return m_renderer.compositingState() != PaintsIntoOwnBacking;
}
// Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
-void RenderLayerRepainter::repaintIncludingNonCompositingDescendants(RenderLayerModelObject* repaintContainer)
+void RenderLayerRepainter::repaintIncludingNonCompositingDescendants()
{
- m_renderer->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_renderer->clippedOverflowRectForRepaint(repaintContainer)));
+ repaintIncludingNonCompositingDescendantsInternal(m_renderer.containerForPaintInvalidation());
+}
- for (RenderLayer* curr = m_renderer->layer()->firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->hasCompositedLayerMapping())
- curr->repainter().repaintIncludingNonCompositingDescendants(repaintContainer);
+void RenderLayerRepainter::repaintIncludingNonCompositingDescendantsInternal(const RenderLayerModelObject* repaintContainer)
+{
+ m_renderer.invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_renderer.boundsRectForPaintInvalidation(repaintContainer)), InvalidationLayer);
+
+ // FIXME: Repaints can be issued during style recalc at present, via RenderLayerModelObject::styleWillChange. This happens in scenarios when
+ // repaint is needed but not layout.
+ DisableCompositingQueryAsserts disabler;
+
+ for (RenderLayer* curr = m_renderer.layer()->firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->compositingState() != PaintsIntoOwnBacking && curr->compositingState() != PaintsIntoGroupedBacking)
+ curr->repainter().repaintIncludingNonCompositingDescendantsInternal(repaintContainer);
}
}
LayoutRect RenderLayerRepainter::repaintRectIncludingNonCompositingDescendants() const
{
- LayoutRect repaintRect = m_repaintRect;
- for (RenderLayer* child = m_renderer->layer()->firstChild(); child; child = child->nextSibling()) {
+ LayoutRect repaintRect;
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ repaintRect = m_renderer.previousPaintInvalidationRect();
+ else
+ repaintRect = m_repaintRect;
+
+ for (RenderLayer* child = m_renderer.layer()->firstChild(); child; child = child->nextSibling()) {
// Don't include repaint rects for composited child layers; they will paint themselves and have a different origin.
- if (child->hasCompositedLayerMapping())
+ if (child->compositingState() == PaintsIntoOwnBacking || child->compositingState() == PaintsIntoGroupedBacking)
continue;
repaintRect.unite(child->repainter().repaintRectIncludingNonCompositingDescendants());
@@ -153,80 +184,55 @@ LayoutRect RenderLayerRepainter::repaintRectIncludingNonCompositingDescendants()
return repaintRect;
}
-void RenderLayerRepainter::setBackingNeedsRepaint()
-{
- ASSERT(m_renderer->compositingState() != NotComposited);
-
- if (m_renderer->compositingState() == PaintsIntoGroupedBacking) {
- // FIXME: should probably setNeedsDisplayInRect for this layer's bounds only.
- m_renderer->groupedMapping()->squashingLayer()->setNeedsDisplay();
- } else {
- m_renderer->compositedLayerMapping()->setContentsNeedDisplay();
- }
-}
-
void RenderLayerRepainter::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(m_renderer->compositingState() != NotComposited);
- if (m_renderer->compositingState() == NotComposited) {
+ ASSERT(m_renderer.compositingState() != NotComposited);
+ if (m_renderer.compositingState() == NotComposited) {
// If we're trying to repaint the placeholder document layer, propagate the
// repaint to the native view system.
LayoutRect absRect(r);
LayoutPoint delta;
- m_renderer->layer()->convertToLayerCoords(m_renderer->layer()->root(), delta);
+ m_renderer.layer()->convertToLayerCoords(m_renderer.layer()->root(), delta);
absRect.moveBy(delta);
- RenderView* view = m_renderer->view();
+ if (absRect.isEmpty())
+ return;
+
+ RenderView* view = m_renderer.view();
if (view)
view->repaintViewRectangle(absRect);
+ return;
+ }
+ IntRect repaintRect = pixelSnappedIntRect(r);
+ // FIXME: generalize accessors to backing GraphicsLayers so that this code is squashing-agnostic.
+ if (m_renderer.groupedMapping()) {
+ if (GraphicsLayer* squashingLayer = m_renderer.groupedMapping()->squashingLayer())
+ squashingLayer->setNeedsDisplayInRect(repaintRect);
} else {
- if (m_renderer->compositingState() == PaintsIntoGroupedBacking) {
- // FIXME: LayoutRect rounding to IntRect is probably not a good idea.
- IntRect offsetRect = pixelSnappedIntRect(r);
- if (m_renderer->hasTransform())
- offsetRect = m_renderer->layer()->transform()->mapRect(pixelSnappedIntRect(r));
-
- offsetRect.move(-m_renderer->layer()->offsetFromSquashingLayerOrigin());
- m_renderer->groupedMapping()->squashingLayer()->setNeedsDisplayInRect(offsetRect);
- } else {
- m_renderer->compositedLayerMapping()->setContentsNeedDisplayInRect(pixelSnappedIntRect(r));
- }
+ m_renderer.compositedLayerMapping()->setContentsNeedDisplayInRect(repaintRect);
}
}
-void RenderLayerRepainter::repaintIncludingDescendants()
-{
- m_renderer->repaint();
- for (RenderLayer* curr = m_renderer->layer()->firstChild(); curr; curr = curr->nextSibling())
- curr->repainter().repaintIncludingDescendants();
-}
-
void RenderLayerRepainter::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect)
{
if (rect.isEmpty())
return;
-
LayoutRect rectForRepaint = rect;
- m_renderer->style()->filterOutsets().expandRect(rectForRepaint);
+ m_renderer.style()->filterOutsets().expandRect(rectForRepaint);
- RenderLayerFilterInfo* filterInfo = m_renderer->layer()->filterInfo();
+ RenderLayerFilterInfo* filterInfo = m_renderer.layer()->filterInfo();
ASSERT(filterInfo);
filterInfo->expandDirtySourceRect(rectForRepaint);
- 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(m_renderer->layer()->calculateLayerBounds(m_renderer->layer()));
- }
-
RenderLayer* parentLayer = enclosingFilterRepaintLayer();
ASSERT(parentLayer);
FloatQuad repaintQuad(rectForRepaint);
- LayoutRect parentLayerRect = m_renderer->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
+ LayoutRect parentLayerRect = m_renderer.localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
+
+ if (parentLayerRect.isEmpty())
+ return;
if (parentLayer->hasCompositedLayerMapping()) {
parentLayer->repainter().setBackingNeedsRepaintInRect(parentLayerRect);
@@ -249,8 +255,8 @@ void RenderLayerRepainter::setFilterBackendNeedsRepaintingInRect(const LayoutRec
RenderLayer* RenderLayerRepainter::enclosingFilterRepaintLayer() const
{
- for (const RenderLayer* curr = m_renderer->layer(); curr; curr = curr->parent()) {
- if ((curr != m_renderer->layer() && curr->requiresFullLayerImageForFilters()) || curr->compositingState() == PaintsIntoOwnBacking || curr->isRootLayer())
+ for (const RenderLayer* curr = m_renderer.layer(); curr; curr = curr->parent()) {
+ if ((curr != m_renderer.layer() && curr->requiresFullLayerImageForFilters()) || curr->compositingState() == PaintsIntoOwnBacking || curr->isRootLayer())
return const_cast<RenderLayer*>(curr);
}
return 0;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.h
index ffc08ee8947..b55d89d0ffd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerRepainter.h
@@ -53,51 +53,50 @@ namespace WebCore {
enum RepaintStatus {
NeedsNormalRepaint = 0,
NeedsFullRepaint = 1 << 0,
- NeedsFullRepaintForPositionedMovementLayout = 1 << 1
+ NeedsFullRepaintForPositionedMovementLayout = NeedsFullRepaint | 1 << 1
};
-class RenderGeometryMap;
class RenderLayer;
class RenderLayerModelObject;
class RenderLayerRepainter {
WTF_MAKE_NONCOPYABLE(RenderLayerRepainter);
public:
- RenderLayerRepainter(RenderLayerModelObject*);
+ RenderLayerRepainter(RenderLayerModelObject&);
- // Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint.
+ // Return a cached repaint rect, computed relative to the layer renderer's containerForPaintInvalidation.
LayoutRect repaintRect() const { return m_repaintRect; }
LayoutRect repaintRectIncludingNonCompositingDescendants() const;
- void repaintAfterLayout(RenderGeometryMap*, bool shouldCheckForRepaint);
- void repaintIncludingNonCompositingDescendants(RenderLayerModelObject* repaintContainer);
- void repaintIncludingDescendants();
+ void repaintAfterLayout(bool shouldCheckForRepaint);
+ void repaintIncludingNonCompositingDescendants();
void setRepaintStatus(RepaintStatus status) { m_repaintStatus = status; }
- void computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* = 0);
- void computeRepaintRectsIncludingDescendants();
+ void computeRepaintRects();
+ void computeRepaintRectsIncludingNonCompositingDescendants();
// Indicate that the layer contents need to be repainted. Only has an effect
// if layer compositing is being used,
- void setBackingNeedsRepaint();
void setBackingNeedsRepaintInRect(const LayoutRect&); // r is in the coordinate space of the layer's render object
void setFilterBackendNeedsRepaintingInRect(const LayoutRect&);
private:
- bool shouldRepaintAfterLayout() const;
+ void repaintIncludingNonCompositingDescendantsInternal(const RenderLayerModelObject* repaintContainer);
+
+ bool shouldRepaintLayer() const;
void clearRepaintRects();
RenderLayer* enclosingFilterRepaintLayer() const;
- RenderLayerModelObject* m_renderer;
+ RenderLayerModelObject& m_renderer;
unsigned m_repaintStatus; // RepaintStatus
LayoutRect m_repaintRect; // Cached repaint rects. Used by layout.
- LayoutRect m_outlineBox;
+ LayoutPoint m_offset;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.cpp
index 0486111467d..b9512464833 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.cpp
@@ -47,20 +47,21 @@
#include "core/css/PseudoStyleRequest.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/FrameSelection.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorTraceEvents.h"
#include "core/page/EventHandler.h"
#include "core/page/FocusController.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/RenderGeometryMap.h"
-#include "core/rendering/RenderLayerCompositor.h"
#include "core/rendering/RenderScrollbar.h"
#include "core/rendering/RenderScrollbarPart.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "platform/PlatformGestureEvent.h"
#include "platform/PlatformMouseEvent.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
@@ -73,21 +74,18 @@ namespace WebCore {
const int ResizerControlExpandRatioForTouch = 2;
-RenderLayerScrollableArea::RenderLayerScrollableArea(RenderBox* box)
- : m_box(box)
+RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer& layer)
+ : m_layer(layer)
, m_inResizeMode(false)
+ , m_scrollsOverflow(false)
, m_scrollDimensionsDirty(true)
, m_inOverflowRelayout(false)
- , m_needsCompositedScrolling(false)
- , m_willUseCompositedScrollingHasBeenRecorded(false)
- , m_isScrollableAreaHasBeenRecorded(false)
- , m_forceNeedsCompositedScrolling(DoNotForceCompositedScrolling)
, m_scrollCorner(0)
, m_resizer(0)
{
ScrollableArea::setConstrainsScrollingToContentEdge(false);
- Node* node = m_box->node();
+ Node* node = box().node();
if (node && node->isElementNode()) {
// We save and restore only the scrollOffset as the other scroll values are recalculated.
Element* element = toElement(node);
@@ -102,31 +100,31 @@ RenderLayerScrollableArea::RenderLayerScrollableArea(RenderBox* box)
RenderLayerScrollableArea::~RenderLayerScrollableArea()
{
- if (inResizeMode() && !m_box->documentBeingDestroyed()) {
- if (Frame* frame = m_box->frame())
+ if (inResizeMode() && !box().documentBeingDestroyed()) {
+ if (LocalFrame* frame = box().frame())
frame->eventHandler().resizeScrollableAreaDestroyed();
}
- if (Frame* frame = m_box->frame()) {
+ if (LocalFrame* frame = box().frame()) {
if (FrameView* frameView = frame->view()) {
frameView->removeScrollableArea(this);
}
}
- if (m_box->frame() && m_box->frame()->page()) {
- if (ScrollingCoordinator* scrollingCoordinator = m_box->frame()->page()->scrollingCoordinator())
+ if (box().frame() && box().frame()->page()) {
+ if (ScrollingCoordinator* scrollingCoordinator = box().frame()->page()->scrollingCoordinator())
scrollingCoordinator->willDestroyScrollableArea(this);
}
- if (!m_box->documentBeingDestroyed()) {
- Node* node = m_box->node();
+ if (!box().documentBeingDestroyed()) {
+ Node* node = box().node();
if (node && node->isElementNode())
toElement(node)->setSavedLayerScrollOffset(m_scrollOffset);
}
- if (Frame* frame = m_box->frame()) {
+ if (LocalFrame* frame = box().frame()) {
if (FrameView* frameView = frame->view())
- frameView->removeResizerArea(m_box);
+ frameView->removeResizerArea(box());
}
destroyScrollbar(HorizontalScrollbar);
@@ -138,38 +136,40 @@ RenderLayerScrollableArea::~RenderLayerScrollableArea()
m_resizer->destroy();
}
-ScrollableArea* RenderLayerScrollableArea::enclosingScrollableArea() const
-{
- if (RenderBox* enclosingScrollableBox = m_box->enclosingScrollableBox())
- return enclosingScrollableBox->layer()->scrollableArea();
-
- // FIXME: We should return the frame view here (or possibly an ancestor frame view,
- // if the frame view isn't scrollable.
- return 0;
-}
-
GraphicsLayer* RenderLayerScrollableArea::layerForScrolling() const
{
- return m_box->hasCompositedLayerMapping() ? m_box->compositedLayerMapping()->scrollingContentsLayer() : 0;
+ return box().hasCompositedLayerMapping() ? box().compositedLayerMapping()->scrollingContentsLayer() : 0;
}
GraphicsLayer* RenderLayerScrollableArea::layerForHorizontalScrollbar() const
{
- return m_box->hasCompositedLayerMapping() ? m_box->compositedLayerMapping()->layerForHorizontalScrollbar() : 0;
+ // See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
+ return box().hasCompositedLayerMapping() ? box().compositedLayerMapping()->layerForHorizontalScrollbar() : 0;
}
GraphicsLayer* RenderLayerScrollableArea::layerForVerticalScrollbar() const
{
- return m_box->hasCompositedLayerMapping() ? m_box->compositedLayerMapping()->layerForVerticalScrollbar() : 0;
+ // See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
+ return box().hasCompositedLayerMapping() ? box().compositedLayerMapping()->layerForVerticalScrollbar() : 0;
}
GraphicsLayer* RenderLayerScrollableArea::layerForScrollCorner() const
{
- return m_box->hasCompositedLayerMapping() ? m_box->compositedLayerMapping()->layerForScrollCorner() : 0;
+ // See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
+ return box().hasCompositedLayerMapping() ? box().compositedLayerMapping()->layerForScrollCorner() : 0;
}
void RenderLayerScrollableArea::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
{
+ // See crbug.com/343132.
+ DisableCompositingQueryAsserts disabler;
+
if (scrollbar == m_vBar.get()) {
if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
layer->setNeedsDisplayInRect(rect);
@@ -184,14 +184,34 @@ void RenderLayerScrollableArea::invalidateScrollbarRect(Scrollbar* scrollbar, co
IntRect scrollRect = rect;
// If we are not yet inserted into the tree, there is no need to repaint.
- if (!m_box->parent())
+ if (!box().parent())
return;
if (scrollbar == m_vBar.get())
- scrollRect.move(verticalScrollbarStart(0, m_box->width()), m_box->borderTop());
+ scrollRect.move(verticalScrollbarStart(0, box().width()), box().borderTop());
else
- scrollRect.move(horizontalScrollbarStart(0), m_box->height() - m_box->borderBottom() - scrollbar->height());
- m_box->repaintRectangle(scrollRect);
+ scrollRect.move(horizontalScrollbarStart(0), box().height() - box().borderBottom() - scrollbar->height());
+
+ if (scrollRect.isEmpty())
+ return;
+
+ LayoutRect repaintRect = scrollRect;
+ box().flipForWritingMode(repaintRect);
+
+ IntRect intRect = pixelSnappedIntRect(repaintRect);
+
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && box().frameView()->isInPerformLayout()) {
+ if (scrollbar == m_vBar.get()) {
+ m_verticalBarDamage = intRect;
+ m_hasVerticalBarDamage = true;
+ } else {
+ m_horizontalBarDamage = intRect;
+ m_hasHorizontalBarDamage = true;
+ }
+
+ } else {
+ box().invalidatePaintRectangle(intRect);
+ }
}
void RenderLayerScrollableArea::invalidateScrollCornerRect(const IntRect& rect)
@@ -202,14 +222,14 @@ void RenderLayerScrollableArea::invalidateScrollCornerRect(const IntRect& rect)
}
if (m_scrollCorner)
- m_scrollCorner->repaintRectangle(rect);
+ m_scrollCorner->invalidatePaintRectangle(rect);
if (m_resizer)
- m_resizer->repaintRectangle(rect);
+ m_resizer->invalidatePaintRectangle(rect);
}
bool RenderLayerScrollableArea::isActive() const
{
- Page* page = m_box->frame()->page();
+ Page* page = box().frame()->page();
return page && page->focusController().isActive();
}
@@ -258,53 +278,53 @@ IntRect RenderLayerScrollableArea::scrollCornerRect() const
// (b) Both scrollbars are present.
bool hasHorizontalBar = horizontalScrollbar();
bool hasVerticalBar = verticalScrollbar();
- bool hasResizer = m_box->style()->resize() != RESIZE_NONE;
+ bool hasResizer = box().style()->resize() != RESIZE_NONE;
if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
- return cornerRect(m_box->style(), horizontalScrollbar(), verticalScrollbar(), m_box->pixelSnappedBorderBoxRect());
+ return cornerRect(box().style(), horizontalScrollbar(), verticalScrollbar(), box().pixelSnappedBorderBoxRect());
return IntRect();
}
IntRect RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
{
- RenderView* view = m_box->view();
+ RenderView* view = box().view();
if (!view)
return scrollbarRect;
IntRect rect = scrollbarRect;
rect.move(scrollbarOffset(scrollbar));
- return view->frameView()->convertFromRenderer(m_box, rect);
+ return view->frameView()->convertFromRenderer(box(), rect);
}
IntRect RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
{
- RenderView* view = m_box->view();
+ RenderView* view = box().view();
if (!view)
return parentRect;
- IntRect rect = view->frameView()->convertToRenderer(m_box, parentRect);
+ IntRect rect = view->frameView()->convertToRenderer(box(), parentRect);
rect.move(-scrollbarOffset(scrollbar));
return rect;
}
IntPoint RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
{
- RenderView* view = m_box->view();
+ RenderView* view = box().view();
if (!view)
return scrollbarPoint;
IntPoint point = scrollbarPoint;
point.move(scrollbarOffset(scrollbar));
- return view->frameView()->convertFromRenderer(m_box, point);
+ return view->frameView()->convertFromRenderer(box(), point);
}
IntPoint RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
{
- RenderView* view = m_box->view();
+ RenderView* view = box().view();
if (!view)
return parentPoint;
- IntPoint point = view->frameView()->convertToRenderer(m_box, parentPoint);
+ IntPoint point = view->frameView()->convertToRenderer(box(), parentPoint);
point.move(-scrollbarOffset(scrollbar));
return point;
@@ -318,7 +338,7 @@ int RenderLayerScrollableArea::scrollSize(ScrollbarOrientation orientation) cons
void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset)
{
- if (!m_box->isMarquee()) {
+ if (!box().isMarquee()) {
// Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
if (m_scrollDimensionsDirty)
computeScrollDimensions();
@@ -329,62 +349,77 @@ void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset)
setScrollOffset(toIntSize(newScrollOffset));
- Frame* frame = m_box->frame();
- InspectorInstrumentation::willScrollLayer(m_box);
+ LocalFrame* frame = box().frame();
+ ASSERT(frame);
- RenderView* view = m_box->view();
+ RefPtr<FrameView> frameView = box().frameView();
- // We should have a RenderView if we're trying to scroll.
- ASSERT(view);
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ScrollLayer", "data", InspectorScrollLayerEvent::data(&box()));
+ // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
+ InspectorInstrumentation::willScrollLayer(&box());
// Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
// We don't update compositing layers, because we need to do a deep update from the compositing ancestor.
- bool inLayout = view ? view->frameView()->isInLayout() : false;
- if (!inLayout) {
+ if (!frameView->isInPerformLayout()) {
// If we're in the middle of layout, we'll just update layers once layout has finished.
layer()->updateLayerPositionsAfterOverflowScroll();
- if (view) {
- // Update regions, scrolling may change the clip of a particular region.
- view->frameView()->updateAnnotatedRegions();
- view->updateWidgetPositions();
- }
-
+ // Update regions, scrolling may change the clip of a particular region.
+ frameView->updateAnnotatedRegions();
+ // FIXME: We shouldn't call updateWidgetPositions() here since it might tear down the render tree,
+ // for now we just crash to avoid allowing an attacker to use after free.
+ frameView->updateWidgetPositions();
+ RELEASE_ASSERT(frameView->renderView());
updateCompositingLayersAfterScroll();
}
- RenderLayerModelObject* repaintContainer = m_box->containerForRepaint();
- if (frame) {
- // The caret rect needs to be invalidated after scrolling
- frame->selection().setCaretRectNeedsUpdate();
+ const RenderLayerModelObject* repaintContainer = box().containerForPaintInvalidation();
+ // The caret rect needs to be invalidated after scrolling
+ frame->selection().setCaretRectNeedsUpdate();
- FloatQuad quadForFakeMouseMoveEvent = FloatQuad(layer()->repainter().repaintRect());
- if (repaintContainer)
- quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
- frame->eventHandler().dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
- }
+ FloatQuad quadForFakeMouseMoveEvent;
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ quadForFakeMouseMoveEvent = FloatQuad(layer()->renderer()->previousPaintInvalidationRect());
+ else
+ quadForFakeMouseMoveEvent = FloatQuad(layer()->repainter().repaintRect());
+
+ quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
+ frame->eventHandler().dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
bool requiresRepaint = true;
- if (m_box->view()->compositor()->inCompositingMode()) {
+ if (box().view()->compositor()->inCompositingMode()) {
+ // Hits in virtual/gpu/fast/canvas/canvas-scroll-path-into-view.html.
+ DisableCompositingQueryAsserts disabler;
bool onlyScrolledCompositedLayers = scrollsOverflow()
&& !layer()->hasVisibleNonLayerContent()
&& !layer()->hasNonCompositedChild()
&& !layer()->hasBlockSelectionGapBounds()
- && !m_box->isMarquee();
+ && !box().isMarquee();
if (usesCompositedScrolling() || onlyScrolledCompositedLayers)
requiresRepaint = false;
}
// Just schedule a full repaint of our object.
- if (view && requiresRepaint)
- m_box->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(layer()->repainter().repaintRect()));
+ if (requiresRepaint) {
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ if (box().frameView()->isInPerformLayout())
+ box().setShouldDoFullPaintInvalidationAfterLayout(true);
+ else
+ box().invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(layer()->renderer()->previousPaintInvalidationRect()), InvalidationScroll);
+ } else {
+ box().invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(layer()->repainter().repaintRect()), InvalidationScroll);
+ }
+ }
// Schedule the scroll DOM event.
- if (m_box->node())
- m_box->node()->document().enqueueScrollEventForNode(m_box->node());
+ if (box().node())
+ box().node()->document().enqueueScrollEventForNode(box().node());
- InspectorInstrumentation::didScrollLayer(m_box);
+ if (AXObjectCache* cache = box().document().existingAXObjectCache())
+ cache->handleScrollPositionChanged(&box());
+
+ InspectorInstrumentation::didScrollLayer(&box());
}
IntPoint RenderLayerScrollableArea::scrollPosition() const
@@ -399,10 +434,10 @@ IntPoint RenderLayerScrollableArea::minimumScrollPosition() const
IntPoint RenderLayerScrollableArea::maximumScrollPosition() const
{
- if (!m_box->hasOverflowClip())
+ if (!box().hasOverflowClip())
return -scrollOrigin();
- return -scrollOrigin() + enclosingIntRect(m_overflowRect).size() - enclosingIntRect(m_box->clientBoxRect()).size();
+ return -scrollOrigin() + enclosingIntRect(m_overflowRect).size() - enclosingIntRect(box().clientBoxRect()).size();
}
IntRect RenderLayerScrollableArea::visibleContentRect(IncludeScrollbarsInRect scrollbarInclusion) const
@@ -440,12 +475,12 @@ IntSize RenderLayerScrollableArea::overhangAmount() const
IntPoint RenderLayerScrollableArea::lastKnownMousePosition() const
{
- return m_box->frame() ? m_box->frame()->eventHandler().lastKnownMousePosition() : IntPoint();
+ return box().frame() ? box().frame()->eventHandler().lastKnownMousePosition() : IntPoint();
}
bool RenderLayerScrollableArea::shouldSuspendScrollAnimations() const
{
- RenderView* view = m_box->view();
+ RenderView* view = box().view();
if (!view)
return true;
return view->frameView()->shouldSuspendScrollAnimations();
@@ -453,7 +488,7 @@ bool RenderLayerScrollableArea::shouldSuspendScrollAnimations() const
bool RenderLayerScrollableArea::scrollbarsCanBeActive() const
{
- RenderView* view = m_box->view();
+ RenderView* view = box().view();
if (!view)
return false;
return view->frameView()->scrollbarsCanBeActive();
@@ -461,62 +496,67 @@ bool RenderLayerScrollableArea::scrollbarsCanBeActive() const
IntRect RenderLayerScrollableArea::scrollableAreaBoundingBox() const
{
- return m_box->absoluteBoundingBoxRect();
+ return box().absoluteBoundingBoxRect();
}
bool RenderLayerScrollableArea::userInputScrollable(ScrollbarOrientation orientation) const
{
- if (m_box->isIntristicallyScrollable(orientation))
+ if (box().isIntristicallyScrollable(orientation))
return true;
EOverflow overflowStyle = (orientation == HorizontalScrollbar) ?
- m_box->style()->overflowX() : m_box->style()->overflowY();
+ box().style()->overflowX() : box().style()->overflowY();
return (overflowStyle == OSCROLL || overflowStyle == OAUTO || overflowStyle == OOVERLAY);
}
bool RenderLayerScrollableArea::shouldPlaceVerticalScrollbarOnLeft() const
{
- return m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft();
+ return box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft();
}
int RenderLayerScrollableArea::pageStep(ScrollbarOrientation orientation) const
{
int length = (orientation == HorizontalScrollbar) ?
- m_box->pixelSnappedClientWidth() : m_box->pixelSnappedClientHeight();
+ box().pixelSnappedClientWidth() : box().pixelSnappedClientHeight();
int minPageStep = static_cast<float>(length) * ScrollableArea::minFractionToStepWhenPaging();
int pageStep = max(minPageStep, length - ScrollableArea::maxOverlapBetweenPages());
return max(pageStep, 1);
}
+RenderBox& RenderLayerScrollableArea::box() const
+{
+ return *m_layer.renderBox();
+}
+
RenderLayer* RenderLayerScrollableArea::layer() const
{
- return m_box->layer();
+ return &m_layer;
}
-int RenderLayerScrollableArea::scrollWidth() const
+LayoutUnit RenderLayerScrollableArea::scrollWidth() const
{
if (m_scrollDimensionsDirty)
const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
- return snapSizeToPixel(m_overflowRect.width(), m_box->clientLeft() + m_box->x());
+ return m_overflowRect.width();
}
-int RenderLayerScrollableArea::scrollHeight() const
+LayoutUnit RenderLayerScrollableArea::scrollHeight() const
{
if (m_scrollDimensionsDirty)
const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
- return snapSizeToPixel(m_overflowRect.height(), m_box->clientTop() + m_box->y());
+ return m_overflowRect.height();
}
void RenderLayerScrollableArea::computeScrollDimensions()
{
m_scrollDimensionsDirty = false;
- m_overflowRect = m_box->layoutOverflowRect();
- m_box->flipForWritingMode(m_overflowRect);
+ m_overflowRect = box().layoutOverflowRect();
+ box().flipForWritingMode(m_overflowRect);
- int scrollableLeftOverflow = m_overflowRect.x() - m_box->borderLeft() - (m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? m_box->verticalScrollbarWidth() : 0);
- int scrollableTopOverflow = m_overflowRect.y() - m_box->borderTop();
+ int scrollableLeftOverflow = m_overflowRect.x() - box().borderLeft() - (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? box().verticalScrollbarWidth() : 0);
+ int scrollableTopOverflow = m_overflowRect.y() - box().borderTop();
setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));
}
@@ -530,7 +570,7 @@ void RenderLayerScrollableArea::scrollToOffset(const IntSize& scrollOffset, Scro
void RenderLayerScrollableArea::updateAfterLayout()
{
// List box parts handle the scrollbars by themselves so we have nothing to do.
- if (m_box->style()->appearance() == ListboxPart)
+ if (box().style()->appearance() == ListboxPart)
return;
m_scrollDimensionsDirty = true;
@@ -538,7 +578,7 @@ void RenderLayerScrollableArea::updateAfterLayout()
computeScrollDimensions();
- if (!m_box->isMarquee()) {
+ if (!box().isMarquee()) {
// 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).
IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset());
@@ -552,87 +592,97 @@ void RenderLayerScrollableArea::updateAfterLayout()
bool hasHorizontalOverflow = this->hasHorizontalOverflow();
bool hasVerticalOverflow = this->hasVerticalOverflow();
- // overflow:scroll should just enable/disable.
- if (m_box->style()->overflowX() == OSCROLL)
- horizontalScrollbar()->setEnabled(hasHorizontalOverflow);
- if (m_box->style()->overflowY() == OSCROLL)
- verticalScrollbar()->setEnabled(hasVerticalOverflow);
+ {
+ // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-after-style-change.html.
+ DisableCompositingQueryAsserts disabler;
+
+ // overflow:scroll should just enable/disable.
+ if (box().style()->overflowX() == OSCROLL)
+ horizontalScrollbar()->setEnabled(hasHorizontalOverflow);
+ if (box().style()->overflowY() == OSCROLL)
+ verticalScrollbar()->setEnabled(hasVerticalOverflow);
+ }
// overflow:auto may need to lay out again if scrollbars got added/removed.
- bool autoHorizontalScrollBarChanged = m_box->hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
- bool autoVerticalScrollBarChanged = m_box->hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
+ bool autoHorizontalScrollBarChanged = box().hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
+ bool autoVerticalScrollBarChanged = box().hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
- if (m_box->hasAutoHorizontalScrollbar())
+ if (box().hasAutoHorizontalScrollbar())
setHasHorizontalScrollbar(hasHorizontalOverflow);
- if (m_box->hasAutoVerticalScrollbar())
+ if (box().hasAutoVerticalScrollbar())
setHasVerticalScrollbar(hasVerticalOverflow);
+ if (hasVerticalOverflow || hasHorizontalOverflow)
+ updateScrollCornerStyle();
+
layer()->updateSelfPaintingLayer();
// Force an update since we know the scrollbars have changed things.
- if (m_box->document().hasAnnotatedRegions())
- m_box->document().setAnnotatedRegionsDirty(true);
+ if (box().document().hasAnnotatedRegions())
+ box().document().setAnnotatedRegionsDirty(true);
- m_box->repaint();
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ box().paintInvalidationForWholeRenderer();
- if (m_box->style()->overflowX() == OAUTO || m_box->style()->overflowY() == OAUTO) {
+ if (box().style()->overflowX() == OAUTO || box().style()->overflowY() == OAUTO) {
if (!m_inOverflowRelayout) {
// Our proprietary overflow: overlay value doesn't trigger a layout.
m_inOverflowRelayout = true;
- SubtreeLayoutScope layoutScope(m_box);
- layoutScope.setNeedsLayout(m_box);
- if (m_box->isRenderBlock()) {
- RenderBlock* block = toRenderBlock(m_box);
- block->scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
- block->layoutBlock(true);
+ SubtreeLayoutScope layoutScope(box());
+ layoutScope.setNeedsLayout(&box());
+ if (box().isRenderBlock()) {
+ RenderBlock& block = toRenderBlock(box());
+ block.scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
+ block.layoutBlock(true);
} else {
- m_box->layout();
+ box().layout();
}
m_inOverflowRelayout = false;
}
}
}
- // Set up the range (and page step/line step).
- if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
- int clientWidth = m_box->pixelSnappedClientWidth();
- horizontalScrollbar->setProportion(clientWidth, overflowRect().width());
- }
- if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
- int clientHeight = m_box->pixelSnappedClientHeight();
- verticalScrollbar->setProportion(clientHeight, overflowRect().height());
+ {
+ // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-after-style-change.html.
+ DisableCompositingQueryAsserts disabler;
+
+ // Set up the range (and page step/line step).
+ if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
+ int clientWidth = box().pixelSnappedClientWidth();
+ horizontalScrollbar->setProportion(clientWidth, overflowRect().width());
+ }
+ if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
+ int clientHeight = box().pixelSnappedClientHeight();
+ verticalScrollbar->setProportion(clientHeight, overflowRect().height());
+ }
}
updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
-
- // Composited scrolling may need to be enabled or disabled if the amount of overflow changed.
- if (m_box->view() && m_box->view()->compositor()->updateLayerCompositingState(m_box->layer()))
- m_box->view()->compositor()->setCompositingLayersNeedRebuild();
}
bool RenderLayerScrollableArea::hasHorizontalOverflow() const
{
ASSERT(!m_scrollDimensionsDirty);
- return scrollWidth() > m_box->pixelSnappedClientWidth();
+ return scrollWidth() > box().clientWidth();
}
bool RenderLayerScrollableArea::hasVerticalOverflow() const
{
ASSERT(!m_scrollDimensionsDirty);
- return scrollHeight() > m_box->pixelSnappedClientHeight();
+ return scrollHeight() > box().clientHeight();
}
bool RenderLayerScrollableArea::hasScrollableHorizontalOverflow() const
{
- return hasHorizontalOverflow() && m_box->scrollsOverflowX();
+ return hasHorizontalOverflow() && box().scrollsOverflowX();
}
bool RenderLayerScrollableArea::hasScrollableVerticalOverflow() const
{
- return hasVerticalOverflow() && m_box->scrollsOverflowY();
+ return hasVerticalOverflow() && box().scrollsOverflowY();
}
static bool overflowRequiresScrollbar(EOverflow overflow)
@@ -648,14 +698,18 @@ static bool overflowDefinesAutomaticScrollbar(EOverflow overflow)
void RenderLayerScrollableArea::updateAfterStyleChange(const RenderStyle* oldStyle)
{
// List box parts handle the scrollbars by themselves so we have nothing to do.
- if (m_box->style()->appearance() == ListboxPart)
+ if (box().style()->appearance() == ListboxPart)
+ return;
+
+ // RenderView shouldn't provide scrollbars on its own.
+ if (box().isRenderView())
return;
if (!m_scrollDimensionsDirty)
updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
- EOverflow overflowX = m_box->style()->overflowX();
- EOverflow overflowY = m_box->style()->overflowY();
+ EOverflow overflowX = box().style()->overflowX();
+ EOverflow overflowY = box().style()->overflowY();
// To avoid doing a relayout in updateScrollbarsAfterLayout, we try to keep any automatic scrollbar that was already present.
bool needsHorizontalScrollbar = (hasHorizontalScrollbar() && overflowDefinesAutomaticScrollbar(overflowX)) || overflowRequiresScrollbar(overflowX);
@@ -686,10 +740,35 @@ void RenderLayerScrollableArea::updateAfterStyleChange(const RenderStyle* oldSty
updateResizerStyle();
}
+void RenderLayerScrollableArea::updateAfterCompositingChange()
+{
+ layer()->updateScrollingStateAfterCompositingChange();
+}
+
+void RenderLayerScrollableArea::updateAfterOverflowRecalc()
+{
+ computeScrollDimensions();
+ if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
+ int clientWidth = box().pixelSnappedClientWidth();
+ horizontalScrollbar->setProportion(clientWidth, overflowRect().width());
+ }
+ if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
+ int clientHeight = box().pixelSnappedClientHeight();
+ verticalScrollbar->setProportion(clientHeight, overflowRect().height());
+ }
+
+ bool hasHorizontalOverflow = this->hasHorizontalOverflow();
+ bool hasVerticalOverflow = this->hasVerticalOverflow();
+ bool autoHorizontalScrollBarChanged = box().hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
+ bool autoVerticalScrollBarChanged = box().hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
+ if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged)
+ box().setNeedsLayoutAndFullPaintInvalidation();
+}
+
IntSize RenderLayerScrollableArea::clampScrollOffset(const IntSize& scrollOffset) const
{
- int maxX = scrollWidth() - m_box->pixelSnappedClientWidth();
- int maxY = scrollHeight() - m_box->pixelSnappedClientHeight();
+ int maxX = scrollWidth() - box().pixelSnappedClientWidth();
+ int maxY = scrollHeight() - box().pixelSnappedClientHeight();
int x = std::max(std::min(scrollOffset.width(), maxX), 0);
int y = std::max(std::min(scrollOffset.height(), maxY), 0);
@@ -704,8 +783,8 @@ IntRect RenderLayerScrollableArea::rectForHorizontalScrollbar(const IntRect& bor
const IntRect& scrollCorner = scrollCornerRect();
return IntRect(horizontalScrollbarStart(borderBoxRect.x()),
- borderBoxRect.maxY() - m_box->borderBottom() - m_hBar->height(),
- borderBoxRect.width() - (m_box->borderLeft() + m_box->borderRight()) - scrollCorner.width(),
+ borderBoxRect.maxY() - box().borderBottom() - m_hBar->height(),
+ borderBoxRect.width() - (box().borderLeft() + box().borderRight()) - scrollCorner.width(),
m_hBar->height());
}
@@ -717,54 +796,54 @@ IntRect RenderLayerScrollableArea::rectForVerticalScrollbar(const IntRect& borde
const IntRect& scrollCorner = scrollCornerRect();
return IntRect(verticalScrollbarStart(borderBoxRect.x(), borderBoxRect.maxX()),
- borderBoxRect.y() + m_box->borderTop(),
+ borderBoxRect.y() + box().borderTop(),
m_vBar->width(),
- borderBoxRect.height() - (m_box->borderTop() + m_box->borderBottom()) - scrollCorner.height());
+ borderBoxRect.height() - (box().borderTop() + box().borderBottom()) - scrollCorner.height());
}
LayoutUnit RenderLayerScrollableArea::verticalScrollbarStart(int minX, int maxX) const
{
- if (m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
- return minX + m_box->borderLeft();
- return maxX - m_box->borderRight() - m_vBar->width();
+ if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ return minX + box().borderLeft();
+ return maxX - box().borderRight() - m_vBar->width();
}
LayoutUnit RenderLayerScrollableArea::horizontalScrollbarStart(int minX) const
{
- int x = minX + m_box->borderLeft();
- if (m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
- x += m_vBar ? m_vBar->width() : resizerCornerRect(m_box->pixelSnappedBorderBoxRect(), ResizerForPointer).width();
+ int x = minX + box().borderLeft();
+ if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ x += m_vBar ? m_vBar->width() : resizerCornerRect(box().pixelSnappedBorderBoxRect(), ResizerForPointer).width();
return x;
}
IntSize RenderLayerScrollableArea::scrollbarOffset(const Scrollbar* scrollbar) const
{
if (scrollbar == m_vBar.get())
- return IntSize(verticalScrollbarStart(0, m_box->width()), m_box->borderTop());
+ return IntSize(verticalScrollbarStart(0, box().width()), box().borderTop());
if (scrollbar == m_hBar.get())
- return IntSize(horizontalScrollbarStart(0), m_box->height() - m_box->borderBottom() - scrollbar->height());
+ return IntSize(horizontalScrollbarStart(0), box().height() - box().borderBottom() - scrollbar->height());
ASSERT_NOT_REACHED();
return IntSize();
}
-static inline RenderObject* rendererForScrollbar(RenderObject* renderer)
+static inline RenderObject* rendererForScrollbar(RenderObject& renderer)
{
- if (Node* node = renderer->node()) {
+ if (Node* node = renderer.node()) {
if (ShadowRoot* shadowRoot = node->containingShadowRoot()) {
if (shadowRoot->type() == ShadowRoot::UserAgentShadowRoot)
return shadowRoot->host()->renderer();
}
}
- return renderer;
+ return &renderer;
}
PassRefPtr<Scrollbar> RenderLayerScrollableArea::createScrollbar(ScrollbarOrientation orientation)
{
RefPtr<Scrollbar> widget;
- RenderObject* actualRenderer = rendererForScrollbar(m_box);
+ RenderObject* actualRenderer = rendererForScrollbar(box());
bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
if (hasCustomScrollbarStyle) {
widget = RenderScrollbar::createCustomScrollbar(this, orientation, actualRenderer->node());
@@ -775,7 +854,7 @@ PassRefPtr<Scrollbar> RenderLayerScrollableArea::createScrollbar(ScrollbarOrient
else
didAddScrollbar(widget.get(), VerticalScrollbar);
}
- m_box->document().view()->addChild(widget.get());
+ box().document().view()->addChild(widget.get());
return widget.release();
}
@@ -790,7 +869,7 @@ void RenderLayerScrollableArea::destroyScrollbar(ScrollbarOrientation orientatio
scrollbar->removeFromParent();
scrollbar->disconnectFromScrollableArea();
- scrollbar = 0;
+ scrollbar = nullptr;
}
void RenderLayerScrollableArea::setHasHorizontalScrollbar(bool hasScrollbar)
@@ -798,10 +877,14 @@ void RenderLayerScrollableArea::setHasHorizontalScrollbar(bool hasScrollbar)
if (hasScrollbar == hasHorizontalScrollbar())
return;
- if (hasScrollbar)
+ if (hasScrollbar) {
+ // This doesn't hit in any tests, but since the equivalent code in setHasVerticalScrollbar
+ // does, presumably this code does as well.
+ DisableCompositingQueryAsserts disabler;
m_hBar = createScrollbar(HorizontalScrollbar);
- else
+ } else {
destroyScrollbar(HorizontalScrollbar);
+ }
// Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
if (m_hBar)
@@ -810,8 +893,8 @@ void RenderLayerScrollableArea::setHasHorizontalScrollbar(bool hasScrollbar)
m_vBar->styleChanged();
// Force an update since we know the scrollbars have changed things.
- if (m_box->document().hasAnnotatedRegions())
- m_box->document().setAnnotatedRegionsDirty(true);
+ if (box().document().hasAnnotatedRegions())
+ box().document().setAnnotatedRegionsDirty(true);
}
void RenderLayerScrollableArea::setHasVerticalScrollbar(bool hasScrollbar)
@@ -819,10 +902,13 @@ void RenderLayerScrollableArea::setHasVerticalScrollbar(bool hasScrollbar)
if (hasScrollbar == hasVerticalScrollbar())
return;
- if (hasScrollbar)
+ if (hasScrollbar) {
+ // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-after-style-change.html
+ DisableCompositingQueryAsserts disabler;
m_vBar = createScrollbar(VerticalScrollbar);
- else
+ } else {
destroyScrollbar(VerticalScrollbar);
+ }
// Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
if (m_hBar)
@@ -831,8 +917,8 @@ void RenderLayerScrollableArea::setHasVerticalScrollbar(bool hasScrollbar)
m_vBar->styleChanged();
// Force an update since we know the scrollbars have changed things.
- if (m_box->document().hasAnnotatedRegions())
- m_box->document().setAnnotatedRegionsDirty(true);
+ if (box().document().hasAnnotatedRegions())
+ box().document().setAnnotatedRegionsDirty(true);
}
int RenderLayerScrollableArea::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
@@ -849,23 +935,12 @@ int RenderLayerScrollableArea::horizontalScrollbarHeight(OverlayScrollbarSizeRel
return m_hBar->height();
}
-void RenderLayerScrollableArea::positionOverflowControls()
-{
- RenderGeometryMap geometryMap(UseTransforms);
- RenderView* view = m_box->view();
- if (m_box->layer() != view->layer() && m_box->layer()->parent())
- geometryMap.pushMappingsToAncestor(m_box->layer()->parent(), 0);
-
- LayoutPoint offsetFromRoot = LayoutPoint(geometryMap.absolutePoint(FloatPoint()));
- positionOverflowControls(toIntSize(roundedIntPoint(offsetFromRoot)));
-}
-
void RenderLayerScrollableArea::positionOverflowControls(const IntSize& offsetFromRoot)
{
- if (!hasScrollbar() && !m_box->canResize())
+ if (!hasScrollbar() && !box().canResize())
return;
- const IntRect borderBox = m_box->pixelSnappedBorderBoxRect();
+ const IntRect borderBox = box().pixelSnappedBorderBoxRect();
if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
IntRect vBarRect = rectForVerticalScrollbar(borderBox);
vBarRect.move(offsetFromRoot);
@@ -888,26 +963,23 @@ void RenderLayerScrollableArea::positionOverflowControls(const IntSize& offsetFr
// FIXME, this should eventually be removed, once we are certain that composited
// controls get correctly positioned on a compositor update. For now, conservatively
// leaving this unchanged.
- if (m_box->hasCompositedLayerMapping())
- m_box->compositedLayerMapping()->positionOverflowControlsLayers(offsetFromRoot);
-}
-
-bool RenderLayerScrollableArea::scrollsOverflow() const
-{
- if (FrameView* frameView = m_box->view()->frameView())
- return frameView->containsScrollableArea(this);
-
- return false;
+ if (box().hasCompositedLayerMapping())
+ box().compositedLayerMapping()->positionOverflowControlsLayers(offsetFromRoot);
}
void RenderLayerScrollableArea::updateScrollCornerStyle()
{
- RenderObject* actualRenderer = rendererForScrollbar(m_box);
- RefPtr<RenderStyle> corner = m_box->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
+ if (!m_scrollCorner && !hasScrollbar())
+ return;
+ if (!m_scrollCorner && hasOverlayScrollbars())
+ return;
+
+ RenderObject* actualRenderer = rendererForScrollbar(box());
+ RefPtr<RenderStyle> corner = box().hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), actualRenderer->style()) : PassRefPtr<RenderStyle>(nullptr);
if (corner) {
if (!m_scrollCorner) {
- m_scrollCorner = RenderScrollbarPart::createAnonymous(&m_box->document());
- m_scrollCorner->setParent(m_box);
+ m_scrollCorner = RenderScrollbarPart::createAnonymous(&box().document());
+ m_scrollCorner->setParent(&box());
}
m_scrollCorner->setStyle(corner.release());
} else if (m_scrollCorner) {
@@ -919,7 +991,7 @@ void RenderLayerScrollableArea::updateScrollCornerStyle()
void RenderLayerScrollableArea::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
{
// Don't do anything if we have no overflow.
- if (!m_box->hasOverflowClip())
+ if (!box().hasOverflowClip())
return;
IntPoint adjustedPaintOffset = paintOffset;
@@ -947,7 +1019,7 @@ void RenderLayerScrollableArea::paintOverflowControls(GraphicsContext* context,
if (!overflowControlsIntersectRect(localDamgeRect))
return;
- RenderView* renderView = m_box->view();
+ RenderView* renderView = box().view();
RenderLayer* paintingRoot = layer()->enclosingCompositingLayer();
if (!paintingRoot)
@@ -1003,22 +1075,22 @@ void RenderLayerScrollableArea::paintScrollCorner(GraphicsContext* context, cons
bool RenderLayerScrollableArea::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
{
- if (!hasScrollbar() && !m_box->canResize())
+ if (!hasScrollbar() && !box().canResize())
return false;
IntRect resizeControlRect;
- if (m_box->style()->resize() != RESIZE_NONE) {
- resizeControlRect = resizerCornerRect(m_box->pixelSnappedBorderBoxRect(), ResizerForPointer);
+ if (box().style()->resize() != RESIZE_NONE) {
+ resizeControlRect = resizerCornerRect(box().pixelSnappedBorderBoxRect(), ResizerForPointer);
if (resizeControlRect.contains(localPoint))
return true;
}
int resizeControlSize = max(resizeControlRect.height(), 0);
if (m_vBar && m_vBar->shouldParticipateInHitTesting()) {
- LayoutRect vBarRect(verticalScrollbarStart(0, m_box->width()),
- m_box->borderTop(),
+ LayoutRect vBarRect(verticalScrollbarStart(0, box().width()),
+ box().borderTop(),
m_vBar->width(),
- m_box->height() - (m_box->borderTop() + m_box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+ box().height() - (box().borderTop() + box().borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
if (vBarRect.contains(localPoint)) {
result.setScrollbar(m_vBar.get());
return true;
@@ -1028,8 +1100,8 @@ bool RenderLayerScrollableArea::hitTestOverflowControls(HitTestResult& result, c
resizeControlSize = max(resizeControlRect.width(), 0);
if (m_hBar && m_hBar->shouldParticipateInHitTesting()) {
LayoutRect hBarRect(horizontalScrollbarStart(0),
- m_box->height() - m_box->borderBottom() - m_hBar->height(),
- m_box->width() - (m_box->borderLeft() + m_box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
+ box().height() - box().borderBottom() - m_hBar->height(),
+ box().width() - (box().borderLeft() + box().borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
m_hBar->height());
if (hBarRect.contains(localPoint)) {
result.setScrollbar(m_hBar.get());
@@ -1044,9 +1116,9 @@ bool RenderLayerScrollableArea::hitTestOverflowControls(HitTestResult& result, c
IntRect RenderLayerScrollableArea::resizerCornerRect(const IntRect& bounds, ResizerHitTestType resizerHitTestType) const
{
- if (m_box->style()->resize() == RESIZE_NONE)
+ if (box().style()->resize() == RESIZE_NONE)
return IntRect();
- IntRect corner = cornerRect(m_box->style(), horizontalScrollbar(), verticalScrollbar(), bounds);
+ IntRect corner = cornerRect(box().style(), horizontalScrollbar(), verticalScrollbar(), bounds);
if (resizerHitTestType == ResizerForTouch) {
// We make the resizer virtually larger for touch hit testing. With the
@@ -1065,13 +1137,13 @@ IntRect RenderLayerScrollableArea::scrollCornerAndResizerRect() const
{
IntRect scrollCornerAndResizer = scrollCornerRect();
if (scrollCornerAndResizer.isEmpty())
- scrollCornerAndResizer = resizerCornerRect(m_box->pixelSnappedBorderBoxRect(), ResizerForPointer);
+ scrollCornerAndResizer = resizerCornerRect(box().pixelSnappedBorderBoxRect(), ResizerForPointer);
return scrollCornerAndResizer;
}
bool RenderLayerScrollableArea::overflowControlsIntersectRect(const IntRect& localRect) const
{
- const IntRect borderBox = m_box->pixelSnappedBorderBoxRect();
+ const IntRect borderBox = box().pixelSnappedBorderBoxRect();
if (rectForHorizontalScrollbar(borderBox).intersects(localRect))
return true;
@@ -1090,10 +1162,10 @@ bool RenderLayerScrollableArea::overflowControlsIntersectRect(const IntRect& loc
void RenderLayerScrollableArea::paintResizer(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
{
- if (m_box->style()->resize() == RESIZE_NONE)
+ if (box().style()->resize() == RESIZE_NONE)
return;
- IntRect absRect = resizerCornerRect(m_box->pixelSnappedBorderBoxRect(), ResizerForPointer);
+ IntRect absRect = resizerCornerRect(box().pixelSnappedBorderBoxRect(), ResizerForPointer);
absRect.moveBy(paintOffset);
if (!absRect.intersects(damageRect))
return;
@@ -1126,17 +1198,17 @@ void RenderLayerScrollableArea::paintResizer(GraphicsContext* context, const Int
bool RenderLayerScrollableArea::isPointInResizeControl(const IntPoint& absolutePoint, ResizerHitTestType resizerHitTestType) const
{
- if (!m_box->canResize())
+ if (!box().canResize())
return false;
- IntPoint localPoint = roundedIntPoint(m_box->absoluteToLocal(absolutePoint, UseTransforms));
- IntRect localBounds(0, 0, m_box->pixelSnappedWidth(), m_box->pixelSnappedHeight());
+ IntPoint localPoint = roundedIntPoint(box().absoluteToLocal(absolutePoint, UseTransforms));
+ IntRect localBounds(0, 0, box().pixelSnappedWidth(), box().pixelSnappedHeight());
return resizerCornerRect(localBounds, resizerHitTestType).contains(localPoint);
}
bool RenderLayerScrollableArea::hitTestResizerInFragments(const LayerFragments& layerFragments, const HitTestLocation& hitTestLocation) const
{
- if (!m_box->canResize())
+ if (!box().canResize())
return false;
if (layerFragments.isEmpty())
@@ -1153,26 +1225,29 @@ bool RenderLayerScrollableArea::hitTestResizerInFragments(const LayerFragments&
void RenderLayerScrollableArea::updateResizerAreaSet()
{
- Frame* frame = m_box->frame();
+ LocalFrame* frame = box().frame();
if (!frame)
return;
FrameView* frameView = frame->view();
if (!frameView)
return;
- if (m_box->canResize())
- frameView->addResizerArea(m_box);
+ if (box().canResize())
+ frameView->addResizerArea(box());
else
- frameView->removeResizerArea(m_box);
+ frameView->removeResizerArea(box());
}
void RenderLayerScrollableArea::updateResizerStyle()
{
- RenderObject* actualRenderer = rendererForScrollbar(m_box);
- RefPtr<RenderStyle> resizer = m_box->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(RESIZER), actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
+ if (!m_resizer && !box().canResize())
+ return;
+
+ RenderObject* actualRenderer = rendererForScrollbar(box());
+ RefPtr<RenderStyle> resizer = box().hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(RESIZER), actualRenderer->style()) : PassRefPtr<RenderStyle>(nullptr);
if (resizer) {
if (!m_resizer) {
- m_resizer = RenderScrollbarPart::createAnonymous(&m_box->document());
- m_resizer->setParent(m_box);
+ m_resizer = RenderScrollbarPart::createAnonymous(&box().document());
+ m_resizer->setParent(&box());
}
m_resizer->setStyle(resizer.release());
} else if (m_resizer) {
@@ -1183,7 +1258,7 @@ void RenderLayerScrollableArea::updateResizerStyle()
void RenderLayerScrollableArea::drawPlatformResizerImage(GraphicsContext* context, IntRect resizerCornerRect)
{
- float deviceScaleFactor = WebCore::deviceScaleFactor(m_box->frame());
+ float deviceScaleFactor = WebCore::deviceScaleFactor(box().frame());
RefPtr<Image> resizeCornerImage;
IntSize cornerResizerSize;
@@ -1198,10 +1273,10 @@ void RenderLayerScrollableArea::drawPlatformResizerImage(GraphicsContext* contex
cornerResizerSize = resizeCornerImage->size();
}
- if (m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+ if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
context->save();
context->translate(resizerCornerRect.x() + cornerResizerSize.width(), resizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height());
- context->scale(FloatSize(-1.0, 1.0));
+ context->scale(-1.0, 1.0);
context->drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerResizerSize));
context->restore();
return;
@@ -1215,21 +1290,21 @@ IntSize RenderLayerScrollableArea::offsetFromResizeCorner(const IntPoint& absolu
// Currently the resize corner is either the bottom right corner or the bottom left corner.
// FIXME: This assumes the location is 0, 0. Is this guaranteed to always be the case?
IntSize elementSize = layer()->size();
- if (m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
elementSize.setWidth(0);
IntPoint resizerPoint = IntPoint(elementSize);
- IntPoint localPoint = roundedIntPoint(m_box->absoluteToLocal(absolutePoint, UseTransforms));
+ IntPoint localPoint = roundedIntPoint(box().absoluteToLocal(absolutePoint, UseTransforms));
return localPoint - resizerPoint;
}
void RenderLayerScrollableArea::resize(const PlatformEvent& evt, const LayoutSize& oldOffset)
{
// FIXME: This should be possible on generated content but is not right now.
- if (!inResizeMode() || !m_box->canResize() || !m_box->node())
+ if (!inResizeMode() || !box().canResize() || !box().node())
return;
- ASSERT(m_box->node()->isElementNode());
- Element* element = toElement(m_box->node());
+ ASSERT(box().node()->isElementNode());
+ Element* element = toElement(box().node());
Document& document = element->document();
@@ -1253,34 +1328,34 @@ void RenderLayerScrollableArea::resize(const PlatformEvent& evt, const LayoutSiz
ASSERT_NOT_REACHED();
}
- float zoomFactor = m_box->style()->effectiveZoom();
+ float zoomFactor = box().style()->effectiveZoom();
LayoutSize newOffset = offsetFromResizeCorner(document.view()->windowToContents(pos));
newOffset.setWidth(newOffset.width() / zoomFactor);
newOffset.setHeight(newOffset.height() / zoomFactor);
- LayoutSize currentSize = LayoutSize(m_box->width() / zoomFactor, m_box->height() / zoomFactor);
+ LayoutSize currentSize = LayoutSize(box().width() / zoomFactor, box().height() / zoomFactor);
LayoutSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
element->setMinimumSizeForResizing(minimumSize);
LayoutSize adjustedOldOffset = LayoutSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
- if (m_box->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+ if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
newOffset.setWidth(-newOffset.width());
adjustedOldOffset.setWidth(-adjustedOldOffset.width());
}
LayoutSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
- bool isBoxSizingBorder = m_box->style()->boxSizing() == BORDER_BOX;
+ bool isBoxSizingBorder = box().style()->boxSizing() == BORDER_BOX;
- EResize resize = m_box->style()->resize();
+ EResize resize = box().style()->resize();
if (resize != RESIZE_VERTICAL && difference.width()) {
if (element->isFormControlElement()) {
// Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
- element->setInlineStyleProperty(CSSPropertyMarginLeft, m_box->marginLeft() / zoomFactor, CSSPrimitiveValue::CSS_PX);
- element->setInlineStyleProperty(CSSPropertyMarginRight, m_box->marginRight() / zoomFactor, CSSPrimitiveValue::CSS_PX);
+ element->setInlineStyleProperty(CSSPropertyMarginLeft, box().marginLeft() / zoomFactor, CSSPrimitiveValue::CSS_PX);
+ element->setInlineStyleProperty(CSSPropertyMarginRight, box().marginRight() / zoomFactor, CSSPrimitiveValue::CSS_PX);
}
- LayoutUnit baseWidth = m_box->width() - (isBoxSizingBorder ? LayoutUnit() : m_box->borderAndPaddingWidth());
+ LayoutUnit baseWidth = box().width() - (isBoxSizingBorder ? LayoutUnit() : box().borderAndPaddingWidth());
baseWidth = baseWidth / zoomFactor;
element->setInlineStyleProperty(CSSPropertyWidth, roundToInt(baseWidth + difference.width()), CSSPrimitiveValue::CSS_PX);
}
@@ -1288,10 +1363,10 @@ void RenderLayerScrollableArea::resize(const PlatformEvent& evt, const LayoutSiz
if (resize != RESIZE_HORIZONTAL && difference.height()) {
if (element->isFormControlElement()) {
// Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
- element->setInlineStyleProperty(CSSPropertyMarginTop, m_box->marginTop() / zoomFactor, CSSPrimitiveValue::CSS_PX);
- element->setInlineStyleProperty(CSSPropertyMarginBottom, m_box->marginBottom() / zoomFactor, CSSPrimitiveValue::CSS_PX);
+ element->setInlineStyleProperty(CSSPropertyMarginTop, box().marginTop() / zoomFactor, CSSPrimitiveValue::CSS_PX);
+ element->setInlineStyleProperty(CSSPropertyMarginBottom, box().marginBottom() / zoomFactor, CSSPrimitiveValue::CSS_PX);
}
- LayoutUnit baseHeight = m_box->height() - (isBoxSizingBorder ? LayoutUnit() : m_box->borderAndPaddingHeight());
+ LayoutUnit baseHeight = box().height() - (isBoxSizingBorder ? LayoutUnit() : box().borderAndPaddingHeight());
baseHeight = baseHeight / zoomFactor;
element->setInlineStyleProperty(CSSPropertyHeight, roundToInt(baseHeight + difference.height()), CSSPrimitiveValue::CSS_PX);
}
@@ -1303,8 +1378,8 @@ void RenderLayerScrollableArea::resize(const PlatformEvent& evt, const LayoutSiz
LayoutRect RenderLayerScrollableArea::exposeRect(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
{
- LayoutRect localExposeRect(m_box->absoluteToLocalQuad(FloatQuad(FloatRect(rect)), UseTransforms).boundingBox());
- LayoutRect layerBounds(0, 0, m_box->clientWidth(), m_box->clientHeight());
+ LayoutRect localExposeRect(box().absoluteToLocalQuad(FloatQuad(FloatRect(rect)), UseTransforms).boundingBox());
+ LayoutRect layerBounds(0, 0, box().clientWidth(), box().clientHeight());
LayoutRect r = ScrollAlignment::getRectToExpose(layerBounds, localExposeRect, alignX, alignY);
IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset() + toIntSize(roundedIntRect(r).location()));
@@ -1315,12 +1390,12 @@ LayoutRect RenderLayerScrollableArea::exposeRect(const LayoutRect& rect, const S
scrollToOffset(clampedScrollOffset);
IntSize scrollOffsetDifference = adjustedScrollOffset() - oldScrollOffset;
localExposeRect.move(-scrollOffsetDifference);
- return LayoutRect(m_box->localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox());
+ return LayoutRect(box().localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox());
}
void RenderLayerScrollableArea::updateScrollableAreaSet(bool hasOverflow)
{
- Frame* frame = m_box->frame();
+ LocalFrame* frame = box().frame();
if (!frame)
return;
@@ -1328,148 +1403,58 @@ void RenderLayerScrollableArea::updateScrollableAreaSet(bool hasOverflow)
if (!frameView)
return;
- bool isVisibleToHitTest = m_box->visibleToHitTesting();
- if (HTMLFrameOwnerElement* owner = frame->ownerElement())
+ // FIXME: Does this need to be fixed later for OOPI?
+ bool isVisibleToHitTest = box().visibleToHitTesting();
+ if (HTMLFrameOwnerElement* owner = frame->deprecatedLocalOwner())
isVisibleToHitTest &= owner->renderer() && owner->renderer()->visibleToHitTesting();
- bool requiresScrollableArea = hasOverflow && isVisibleToHitTest;
- bool updatedScrollableAreaSet = false;
- if (requiresScrollableArea) {
- if (frameView->addScrollableArea(this))
- updatedScrollableAreaSet = true;
- } else {
- if (frameView->removeScrollableArea(this))
- updatedScrollableAreaSet = true;
- }
-
- if (updatedScrollableAreaSet) {
- // Count the total number of RenderLayers that are scrollable areas for
- // any period. We only want to record this at most once per RenderLayer.
- if (requiresScrollableArea && !m_isScrollableAreaHasBeenRecorded) {
- blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", RenderLayer::IsScrollableAreaBucket, RenderLayer::CompositedScrollingHistogramMax);
- m_isScrollableAreaHasBeenRecorded = true;
- }
-
- // We always want composited scrolling if compositor driven accelerated
- // scrolling is enabled. Since we will not update needs composited scrolling
- // in this case, we must force our state to update.
- if (layer()->compositorDrivenAcceleratedScrollingEnabled())
- layer()->didUpdateNeedsCompositedScrolling();
- else if (requiresScrollableArea)
- m_box->view()->compositor()->setNeedsUpdateCompositingRequirementsState();
- else
- setNeedsCompositedScrolling(false);
- }
-}
-
-void RenderLayerScrollableArea::updateNeedsCompositedScrolling()
-{
- TRACE_EVENT0("comp-scroll", "RenderLayer::updateNeedsCompositedScrolling");
-
- layer()->stackingNode()->updateDescendantsAreContiguousInStackingOrder();
- layer()->updateDescendantDependentFlags();
-
- ASSERT(scrollsOverflow());
- const bool needsToBeStackingContainer = layer()->acceleratedCompositingForOverflowScrollEnabled()
- && layer()->stackingNode()->descendantsAreContiguousInStackingOrder()
- && !layer()->hasUnclippedDescendant();
+ bool didNeedCompositedScrolling = needsCompositedScrolling();
- const bool needsToBeStackingContainerDidChange = layer()->stackingNode()->setNeedsToBeStackingContainer(needsToBeStackingContainer);
+ bool didScrollOverflow = m_scrollsOverflow;
- const bool needsCompositedScrolling = needsToBeStackingContainer
- || layer()->compositorDrivenAcceleratedScrollingEnabled();
-
- // We gather a boolean value for use with Google UMA histograms to
- // quantify the actual effects of a set of patches attempting to
- // relax composited scrolling requirements, thereby increasing the
- // number of composited overflow divs.
- if (layer()->acceleratedCompositingForOverflowScrollEnabled())
- blink::Platform::current()->histogramEnumeration("Renderer.NeedsCompositedScrolling", needsCompositedScrolling, 2);
+ m_scrollsOverflow = hasOverflow && isVisibleToHitTest;
+ if (didScrollOverflow == scrollsOverflow())
+ return;
- const bool needsCompositedScrollingDidChange = setNeedsCompositedScrolling(needsCompositedScrolling);
+ if (m_scrollsOverflow)
+ frameView->addScrollableArea(this);
+ else
+ frameView->removeScrollableArea(this);
- if (needsToBeStackingContainerDidChange || needsCompositedScrollingDidChange) {
- // Note, the z-order lists may need to be rebuilt, but our code guarantees
- // that we have not affected stacking, so we will not dirty
- // m_descendantsAreContiguousInStackingOrder for either us or our stacking
- // context or container.
+ if (didNeedCompositedScrolling != needsCompositedScrolling())
layer()->didUpdateNeedsCompositedScrolling();
- }
-}
-
-bool RenderLayerScrollableArea::setNeedsCompositedScrolling(bool needsCompositedScrolling)
-{
- if (this->needsCompositedScrolling() == needsCompositedScrolling)
- return false;
-
- // Count the total number of RenderLayers which need composited scrolling at
- // some point. This should be recorded at most once per RenderLayer, so we
- // check m_willUseCompositedScrollingHasBeenRecorded.
- if (layer()->acceleratedCompositingForOverflowScrollEnabled() && !m_willUseCompositedScrollingHasBeenRecorded) {
- blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", RenderLayer::WillUseCompositedScrollingBucket, RenderLayer::CompositedScrollingHistogramMax);
- m_willUseCompositedScrollingHasBeenRecorded = true;
- }
-
- m_needsCompositedScrolling = needsCompositedScrolling;
-
- return true;
-}
-
-void RenderLayerScrollableArea::updateHasVisibleNonLayerContent()
-{
- layer()->updateHasVisibleNonLayerContent();
}
void RenderLayerScrollableArea::updateCompositingLayersAfterScroll()
{
- RenderLayerCompositor* compositor = m_box->view()->compositor();
+ RenderLayerCompositor* compositor = box().view()->compositor();
if (compositor->inCompositingMode()) {
- // FIXME: Our stacking container is guaranteed to contain all of our descendants that may need
- // repositioning, so we should be able to enqueue a partial update compositing layers from there.
- // this feature was overridden for now by deferred compositing updates.
- if (usesCompositedScrolling())
- compositor->updateCompositingLayers(CompositingUpdateOnCompositedScroll);
- else
- compositor->updateCompositingLayers(CompositingUpdateOnScroll);
+ if (usesCompositedScrolling()) {
+ DisableCompositingQueryAsserts disabler;
+ ASSERT(box().hasCompositedLayerMapping());
+ box().compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+ compositor->setNeedsCompositingUpdate(CompositingUpdateAfterGeometryChange);
+ } else {
+ layer()->setNeedsCompositingInputsUpdate();
+ compositor->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
+ }
}
}
bool RenderLayerScrollableArea::usesCompositedScrolling() const
{
// Scroll form controls on the main thread so they exhibit correct touch scroll event bubbling
- if (m_box && (m_box->isIntristicallyScrollable(VerticalScrollbar) || m_box->isIntristicallyScrollable(HorizontalScrollbar)))
+ if (box().isIntristicallyScrollable(VerticalScrollbar) || box().isIntristicallyScrollable(HorizontalScrollbar))
return false;
- return m_box->hasCompositedLayerMapping() && m_box->compositedLayerMapping()->scrollingLayer();
-}
-
-bool RenderLayerScrollableArea::adjustForForceCompositedScrollingMode(bool value) const
-{
- switch (m_forceNeedsCompositedScrolling) {
- case DoNotForceCompositedScrolling:
- return value;
- case CompositedScrollingAlwaysOn:
- return true;
- case CompositedScrollingAlwaysOff:
- return false;
- }
-
- ASSERT_NOT_REACHED();
- return value;
+ // See https://codereview.chromium.org/176633003/ for the tests that fail without this disabler.
+ DisableCompositingQueryAsserts disabler;
+ return box().hasCompositedLayerMapping() && box().compositedLayerMapping()->scrollingLayer();
}
bool RenderLayerScrollableArea::needsCompositedScrolling() const
{
- return adjustForForceCompositedScrollingMode(m_needsCompositedScrolling);
-}
-
-void RenderLayerScrollableArea::setForceNeedsCompositedScrolling(ForceNeedsCompositedScrollingMode mode)
-{
- if (m_forceNeedsCompositedScrolling == mode)
- return;
-
- m_forceNeedsCompositedScrolling = mode;
- layer()->didUpdateNeedsCompositedScrolling();
+ return scrollsOverflow() && box().view()->compositor()->acceleratedCompositingForOverflowScrollEnabled();
}
} // Namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.h
index 0444ca78b33..a41bbde5232 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerScrollableArea.h
@@ -53,12 +53,6 @@ enum ResizerHitTestType {
ResizerForTouch
};
-enum ForceNeedsCompositedScrollingMode {
- DoNotForceCompositedScrolling = 0,
- CompositedScrollingAlwaysOn = 1,
- CompositedScrollingAlwaysOff = 2
-};
-
class PlatformEvent;
class RenderBox;
class RenderLayer;
@@ -68,7 +62,9 @@ class RenderLayerScrollableArea FINAL : public ScrollableArea {
friend class Internals;
public:
- RenderLayerScrollableArea(RenderBox*);
+ // FIXME: We should pass in the RenderBox but this opens a window
+ // for crashers during RenderLayer setup (see crbug.com/368062).
+ RenderLayerScrollableArea(RenderLayer&);
virtual ~RenderLayerScrollableArea();
bool hasHorizontalScrollbar() const { return horizontalScrollbar(); }
@@ -76,7 +72,6 @@ public:
virtual Scrollbar* horizontalScrollbar() const OVERRIDE { return m_hBar.get(); }
virtual Scrollbar* verticalScrollbar() const OVERRIDE { return m_vBar.get(); }
- virtual ScrollableArea* enclosingScrollableArea() const OVERRIDE;
virtual GraphicsLayer* layerForScrolling() const OVERRIDE;
virtual GraphicsLayer* layerForHorizontalScrollbar() const OVERRIDE;
@@ -124,6 +119,9 @@ public:
void updateAfterLayout();
void updateAfterStyleChange(const RenderStyle*);
+ void updateAfterOverflowRecalc();
+
+ virtual void updateAfterCompositingChange() OVERRIDE;
bool hasScrollbar() const { return m_hBar || m_vBar; }
@@ -141,8 +139,8 @@ public:
return resizerCornerRect(bounds, ResizerForTouch);
}
- int scrollWidth() const;
- int scrollHeight() const;
+ LayoutUnit scrollWidth() const;
+ LayoutUnit scrollHeight() const;
int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
@@ -153,9 +151,6 @@ public:
void paintOverflowControls(GraphicsContext*, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls);
void paintScrollCorner(GraphicsContext*, const IntPoint&, const IntRect& damageRect);
- // If IntSize is not given, then we must incur additional overhead to instantiate a RenderGeometryMap
- // and compute the correct offset ourselves.
- void positionOverflowControls();
void positionOverflowControls(const IntSize& offsetFromRoot);
// isPointInResizeControl() is used for testing if a pointer/touch position is in the resize control
@@ -167,7 +162,10 @@ public:
LayoutRect exposeRect(const LayoutRect&, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
- bool scrollsOverflow() const;
+ // Returns true our scrollable area is in the FrameView's collection of scrollable areas. This can
+ // only happen if we're both scrollable, and we do in fact overflow. This means that overflow: hidden
+ // layers never get added to the FrameView's collection.
+ bool scrollsOverflow() const { return m_scrollsOverflow; }
// Rectangle encompassing the scroll corner and resizer rect.
IntRect scrollCornerAndResizerRect() const;
@@ -211,33 +209,22 @@ private:
void updateResizerStyle();
void drawPlatformResizerImage(GraphicsContext*, IntRect resizerCornerRect);
+ RenderBox& box() const;
RenderLayer* layer() const;
void updateScrollableAreaSet(bool hasOverflow);
void updateCompositingLayersAfterScroll();
- virtual void updateNeedsCompositedScrolling() OVERRIDE;
- bool setNeedsCompositedScrolling(bool);
-
- virtual void updateHasVisibleNonLayerContent() OVERRIDE;
- void setForceNeedsCompositedScrolling(ForceNeedsCompositedScrollingMode);
-
- RenderBox* m_box;
+ RenderLayer& m_layer;
// Keeps track of whether the layer is currently resizing, so events can cause resizing to start and stop.
unsigned m_inResizeMode : 1;
+ unsigned m_scrollsOverflow : 1;
unsigned m_scrollDimensionsDirty : 1;
unsigned m_inOverflowRelayout : 1;
- unsigned m_needsCompositedScrolling : 1;
- unsigned m_willUseCompositedScrollingHasBeenRecorded : 1;
-
- unsigned m_isScrollableAreaHasBeenRecorded : 1;
-
- ForceNeedsCompositedScrollingMode m_forceNeedsCompositedScrolling;
-
// The width/height of our scrolled area.
LayoutRect m_overflowRect;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.cpp
index 715dcecfe77..eaa6dfc09b4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.cpp
@@ -45,37 +45,33 @@
#include "core/rendering/RenderLayerStackingNode.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerCompositor.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "public/platform/Platform.h"
namespace WebCore {
// FIXME: This should not require RenderLayer. There is currently a cycle where
-// in order to determine if we shoulBeNormalFlowOnly() and isStackingContainer()
-// we have to ask the render layer about some of its state.
+// in order to determine if we shoulBeNormalFlowOnly() we have to ask the render
+// layer about some of its state.
RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer)
: m_layer(layer)
- , m_descendantsAreContiguousInStackingOrder(false)
- , m_descendantsAreContiguousInStackingOrderDirty(true)
, m_normalFlowListDirty(true)
- , m_needsToBeStackingContainer(false)
- , m_needsToBeStackingContainerHasBeenRecorded(false)
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
, m_layerListMutationAllowed(true)
, m_stackingParent(0)
#endif
{
m_isNormalFlowOnly = shouldBeNormalFlowOnly();
- // Non-stacking containers should have empty z-order lists. As this is already the case,
+ // Non-stacking contexts should have empty z-order lists. As this is already the case,
// there is no need to dirty / recompute these lists.
- m_zOrderListsDirty = isStackingContainer();
+ m_zOrderListsDirty = isStackingContext();
}
RenderLayerStackingNode::~RenderLayerStackingNode()
{
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
if (!renderer()->documentBeingDestroyed()) {
ASSERT(!isInStackingParentZOrderLists());
ASSERT(!isInStackingParentNormalFlowList());
@@ -86,11 +82,6 @@ RenderLayerStackingNode::~RenderLayerStackingNode()
#endif
}
-bool RenderLayerStackingNode::isStackingContext(const RenderStyle* style) const
-{
- return !style->hasAutoZIndex() || layer()->isRootLayer();
-}
-
// Helper for the sorting of layers by z-index.
static inline bool compareZIndex(RenderLayerStackingNode* first, RenderLayerStackingNode* second)
{
@@ -99,47 +90,16 @@ static inline bool compareZIndex(RenderLayerStackingNode* first, RenderLayerStac
RenderLayerCompositor* RenderLayerStackingNode::compositor() const
{
- if (!renderer()->view())
- return 0;
+ ASSERT(renderer()->view());
return renderer()->view()->compositor();
}
-void RenderLayerStackingNode::dirtyNormalFlowListCanBePromotedToStackingContainer()
-{
- m_descendantsAreContiguousInStackingOrderDirty = true;
-
- if (m_normalFlowListDirty || !normalFlowList())
- return;
-
- for (size_t index = 0; index < normalFlowList()->size(); ++index)
- normalFlowList()->at(index)->dirtyNormalFlowListCanBePromotedToStackingContainer();
-}
-
-void RenderLayerStackingNode::dirtySiblingStackingNodeCanBePromotedToStackingContainer()
-{
- RenderLayerStackingNode* stackingNode = ancestorStackingNode();
- if (!stackingNode)
- return;
-
- if (!stackingNode->zOrderListsDirty() && stackingNode->posZOrderList()) {
- for (size_t index = 0; index < stackingNode->posZOrderList()->size(); ++index)
- stackingNode->posZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
- }
-
- stackingNode->dirtyNormalFlowListCanBePromotedToStackingContainer();
-
- if (!stackingNode->zOrderListsDirty() && stackingNode->negZOrderList()) {
- for (size_t index = 0; index < stackingNode->negZOrderList()->size(); ++index)
- stackingNode->negZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true);
- }
-}
-
void RenderLayerStackingNode::dirtyZOrderLists()
{
ASSERT(m_layerListMutationAllowed);
- ASSERT(isStackingContainer());
+ ASSERT(isStackingContext());
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
updateStackingParentForZOrderLists(0);
#endif
@@ -149,35 +109,13 @@ void RenderLayerStackingNode::dirtyZOrderLists()
m_negZOrderList->clear();
m_zOrderListsDirty = true;
- m_descendantsAreContiguousInStackingOrderDirty = true;
-
- if (!renderer()->documentBeingDestroyed()) {
- compositor()->setNeedsUpdateCompositingRequirementsState();
- compositor()->setCompositingLayersNeedRebuild();
- if (layer()->acceleratedCompositingForOverflowScrollEnabled())
- compositor()->setNeedsToRecomputeCompositingRequirements();
- }
+ if (!renderer()->documentBeingDestroyed())
+ compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree);
}
-void RenderLayerStackingNode::dirtyStackingContainerZOrderLists()
+void RenderLayerStackingNode::dirtyStackingContextZOrderLists()
{
- // Any siblings in the ancestor stacking context could also be affected.
- // Changing z-index, for example, could cause us to stack in between a
- // sibling's descendants, meaning that we have to recompute
- // m_descendantsAreContiguousInStackingOrder for that sibling.
- dirtySiblingStackingNodeCanBePromotedToStackingContainer();
-
- RenderLayerStackingNode* stackingContainerNode = ancestorStackingContainerNode();
- if (stackingContainerNode)
- stackingContainerNode->dirtyZOrderLists();
-
- // Any change that could affect our stacking container's z-order list could
- // cause other RenderLayers in our stacking context to either opt in or out
- // of composited scrolling. It is important that we make our stacking
- // context aware of these z-order changes so the appropriate updating can
- // happen.
- RenderLayerStackingNode* stackingNode = ancestorStackingNode();
- if (stackingNode && stackingNode != stackingContainerNode)
+ if (RenderLayerStackingNode* stackingNode = ancestorStackingContextNode())
stackingNode->dirtyZOrderLists();
}
@@ -185,7 +123,7 @@ void RenderLayerStackingNode::dirtyNormalFlowList()
{
ASSERT(m_layerListMutationAllowed);
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
updateStackingParentForNormalFlowList(0);
#endif
@@ -193,57 +131,48 @@ void RenderLayerStackingNode::dirtyNormalFlowList()
m_normalFlowList->clear();
m_normalFlowListDirty = true;
- if (!renderer()->documentBeingDestroyed()) {
- compositor()->setCompositingLayersNeedRebuild();
- if (layer()->acceleratedCompositingForOverflowScrollEnabled())
- compositor()->setNeedsToRecomputeCompositingRequirements();
- }
+ if (!renderer()->documentBeingDestroyed())
+ compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree);
}
void RenderLayerStackingNode::rebuildZOrderLists()
{
ASSERT(m_layerListMutationAllowed);
- ASSERT(isDirtyStackingContainer());
- rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
-
-#if !ASSERT_DISABLED
- updateStackingParentForZOrderLists(this);
-#endif
-
- m_zOrderListsDirty = false;
-}
+ ASSERT(isDirtyStackingContext());
-void RenderLayerStackingNode::rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList,
- OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList, const RenderLayerStackingNode* nodeToForceAsStackingContainer,
- CollectLayersBehavior collectLayersBehavior)
-{
for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)
- child->stackingNode()->collectLayers(posZOrderList, negZOrderList, nodeToForceAsStackingContainer, collectLayersBehavior);
+ child->stackingNode()->collectLayers(m_posZOrderList, m_negZOrderList);
}
// Sort the two lists.
- if (posZOrderList)
- std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
+ if (m_posZOrderList)
+ std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
- if (negZOrderList)
- std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
+ if (m_negZOrderList)
+ std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
// Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes.
// The renderers of top layer elements are children of the view, sorted in top layer stacking order.
if (layer()->isRootLayer()) {
- RenderObject* view = renderer()->view();
+ RenderView* view = renderer()->view();
for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) {
Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0;
if (childElement && childElement->isInTopLayer()) {
RenderLayer* layer = toRenderLayerModelObject(child)->layer();
// Create the buffer if it doesn't exist yet.
- if (!posZOrderList)
- posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>);
- posZOrderList->append(layer->stackingNode());
+ if (!m_posZOrderList)
+ m_posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>);
+ m_posZOrderList->append(layer->stackingNode());
}
}
}
+
+#if ASSERT_ENABLED
+ updateStackingParentForZOrderLists(this);
+#endif
+
+ m_zOrderListsDirty = false;
}
void RenderLayerStackingNode::updateNormalFlowList()
@@ -254,7 +183,6 @@ void RenderLayerStackingNode::updateNormalFlowList()
ASSERT(m_layerListMutationAllowed);
for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
- // Ignore non-overflow layers and reflections.
if (child->stackingNode()->isNormalFlowOnly() && (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)) {
if (!m_normalFlowList)
m_normalFlowList = adoptPtr(new Vector<RenderLayerStackingNode*>);
@@ -262,71 +190,36 @@ void RenderLayerStackingNode::updateNormalFlowList()
}
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
updateStackingParentForNormalFlowList(this);
#endif
m_normalFlowListDirty = false;
}
-void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer,
- const RenderLayerStackingNode* nodeToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior)
+void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer)
{
if (layer()->isInTopLayer())
return;
layer()->updateDescendantDependentFlags();
- bool isStacking = false;
- bool isNormalFlow = false;
-
- switch (collectLayersBehavior) {
- case ForceLayerToStackingContainer:
- ASSERT(nodeToForceAsStackingContainer);
- if (this == nodeToForceAsStackingContainer) {
- isStacking = true;
- isNormalFlow = false;
- } else {
- isStacking = isStackingContext();
- isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
- }
- break;
- case OverflowScrollCanBeStackingContainers:
- ASSERT(!nodeToForceAsStackingContainer);
- isStacking = isStackingContainer();
- isNormalFlow = isNormalFlowOnly();
- break;
- case OnlyStackingContextsCanBeStackingContainers:
- isStacking = isStackingContext();
- isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling();
- break;
- }
-
- // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
- if (!isNormalFlow && !layer()->isOutOfFlowRenderFlowThread()) {
- // Determine which buffer the child should be in.
+ if (!isNormalFlowOnly()) {
OwnPtr<Vector<RenderLayerStackingNode*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
-
- // Create the buffer if it doesn't exist yet.
if (!buffer)
buffer = adoptPtr(new Vector<RenderLayerStackingNode*>);
-
- // Append ourselves at the end of the appropriate buffer.
buffer->append(this);
}
- // Recur into our children to collect more layers, but only if we don't establish
- // a stacking context/container.
- if (!isStacking) {
+ if (!isStackingContext()) {
for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) {
- // Ignore reflections.
if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)
- child->stackingNode()->collectLayers(posBuffer, negBuffer, nodeToForceAsStackingContainer, collectLayersBehavior);
+ child->stackingNode()->collectLayers(posBuffer, negBuffer);
}
}
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool RenderLayerStackingNode::isInStackingParentZOrderLists() const
{
if (!m_stackingParent || m_stackingParent->zOrderListsDirty())
@@ -386,50 +279,26 @@ void RenderLayerStackingNode::updateLayerListsIfNeeded()
void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle)
{
- bool wasStackingContext = oldStyle ? isStackingContext(oldStyle) : false;
- EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE;
+ bool wasStackingContext = oldStyle ? !oldStyle->hasAutoZIndex() : false;
int oldZIndex = oldStyle ? oldStyle->zIndex() : 0;
- // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could
- // likely be folded along with the rest.
bool isStackingContext = this->isStackingContext();
- if (isStackingContext == wasStackingContext && oldVisibility == renderer()->style()->visibility() && oldZIndex == zIndex())
+ if (isStackingContext == wasStackingContext && oldZIndex == zIndex())
return;
- dirtyStackingContainerZOrderLists();
+ dirtyStackingContextZOrderLists();
- if (isStackingContainer())
+ if (isStackingContext)
dirtyZOrderLists();
else
clearZOrderLists();
-
- compositor()->setNeedsUpdateCompositingRequirementsState();
}
+// FIXME: Rename shouldBeNormalFlowOnly to something more accurate now that CSS
+// 2.1 defines the term "normal flow".
bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const
{
- return shouldBeNormalFlowOnlyIgnoringCompositedScrolling() && !layer()->needsCompositedScrolling();
-}
-
-bool RenderLayerStackingNode::shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const
-{
- const bool couldBeNormalFlow = renderer()->hasOverflowClip()
- || renderer()->hasReflection()
- || renderer()->hasMask()
- || renderer()->isCanvas()
- || renderer()->isVideo()
- || renderer()->isEmbeddedObject()
- || renderer()->isRenderIFrame()
- || (renderer()->style()->specifiesColumns() && !layer()->isRootLayer());
- const bool preventsElementFromBeingNormalFlow = renderer()->isPositioned()
- || renderer()->hasTransform()
- || renderer()->hasClipPath()
- || renderer()->hasFilter()
- || renderer()->hasBlendMode()
- || layer()->isTransparent()
- || renderer()->style()->hasFlowFrom();
-
- return couldBeNormalFlow && !preventsElementFromBeingNormalFlow;
+ return !isStackingContext() && !renderer()->isPositioned();
}
void RenderLayerStackingNode::updateIsNormalFlowOnly()
@@ -441,215 +310,16 @@ void RenderLayerStackingNode::updateIsNormalFlowOnly()
m_isNormalFlowOnly = isNormalFlowOnly;
if (RenderLayer* p = layer()->parent())
p->stackingNode()->dirtyNormalFlowList();
- dirtyStackingContainerZOrderLists();
-}
-
-bool RenderLayerStackingNode::needsToBeStackingContainer() const
-{
- return layer()->scrollableArea() && layer()->scrollableArea()->adjustForForceCompositedScrollingMode(m_needsToBeStackingContainer);
-}
-
-// Determine whether the current layer can be promoted to a stacking container.
-// We do this by computing what positive and negative z-order lists would look
-// like before and after promotion, and ensuring that proper stacking order is
-// preserved between the two sets of lists.
-void RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder()
-{
- TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder");
-
- const RenderLayer* currentLayer = layer();
- if (isStackingContext() || !m_descendantsAreContiguousInStackingOrderDirty || !currentLayer->acceleratedCompositingForOverflowScrollEnabled())
- return;
-
- if (!currentLayer->scrollsOverflow())
- return;
-
- RenderLayerStackingNode* stackingNode = ancestorStackingNode();
- if (!stackingNode)
- return;
-
- OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
- OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
- OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
- OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>);
-
- collectBeforePromotionZOrderList(stackingNode, posZOrderListBeforePromote, negZOrderListBeforePromote);
- collectAfterPromotionZOrderList(stackingNode, posZOrderListAfterPromote, negZOrderListAfterPromote);
-
- size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderListAfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePromote->size());
-
- m_descendantsAreContiguousInStackingOrderDirty = false;
- m_descendantsAreContiguousInStackingOrder = false;
-
- const RenderLayerStackingNode* nodeAfterPromote = 0;
- for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) {
- const RenderLayerStackingNode* nodeBeforePromote = i < negZOrderListBeforePromote->size()
- ? negZOrderListBeforePromote->at(i)
- : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->size());
- nodeAfterPromote = i < negZOrderListAfterPromote->size()
- ? negZOrderListAfterPromote->at(i)
- : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size());
-
- if (nodeBeforePromote != nodeAfterPromote && (nodeAfterPromote != this || renderer()->hasBackground()))
- return;
- }
-
- nodeAfterPromote = 0;
- for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) {
- const RenderLayerStackingNode* nodeBeforePromote = i < posZOrderListBeforePromote->size()
- ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1)
- : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1);
- nodeAfterPromote = i < posZOrderListAfterPromote->size()
- ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1)
- : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1);
-
- if (nodeBeforePromote != nodeAfterPromote && nodeAfterPromote != this)
- return;
- }
-
- m_descendantsAreContiguousInStackingOrder = true;
-}
-
-void RenderLayerStackingNode::collectBeforePromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
- OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
-{
- ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, OnlyStackingContextsCanBeStackingContainers);
-
- const RenderLayer* currentLayer = layer();
- const RenderLayer* positionedAncestor = currentLayer->parent();
- while (positionedAncestor && !positionedAncestor->isPositionedContainer() && !positionedAncestor->stackingNode()->isStackingContext())
- positionedAncestor = positionedAncestor->parent();
- if (positionedAncestor && (!positionedAncestor->isPositionedContainer() || positionedAncestor->stackingNode()->isStackingContext()))
- positionedAncestor = 0;
-
- if (!posZOrderList)
- posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>());
- else if (posZOrderList->find(this) != kNotFound)
- return;
-
- // The current node will appear in the z-order lists after promotion, so
- // for a meaningful comparison, we must insert it in the z-order lists
- // before promotion if it does not appear there already.
- if (!positionedAncestor) {
- posZOrderList->prepend(this);
- return;
- }
-
- for (size_t index = 0; index < posZOrderList->size(); index++) {
- if (posZOrderList->at(index)->layer() == positionedAncestor) {
- posZOrderList->insert(index + 1, this);
- return;
- }
- }
-}
-
-void RenderLayerStackingNode::collectAfterPromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode,
- OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList)
-{
- ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, ForceLayerToStackingContainer);
+ dirtyStackingContextZOrderLists();
}
-// Compute what positive and negative z-order lists would look like before and
-// after promotion, so we can later ensure that proper stacking order is
-// preserved between the two sets of lists.
-//
-// A few examples:
-// c = currentLayer
-// - = negative z-order child of currentLayer
-// + = positive z-order child of currentLayer
-// a = positioned ancestor of currentLayer
-// x = any other RenderLayer in the list
-//
-// (a) xxxxx-----++a+++x
-// (b) xxx-----c++++++xx
-//
-// Normally the current layer would be painted in the normal flow list if it
-// doesn't already appear in the positive z-order list. However, in the case
-// that the layer has a positioned ancestor, it will paint directly after the
-// positioned ancestor. In example (a), the current layer would be painted in
-// the middle of its own positive z-order children, so promoting would cause a
-// change in paint order (since a promoted layer will paint all of its positive
-// z-order children strictly after it paints itself).
-//
-// In example (b), it is ok to promote the current layer only if it does not
-// have a background. If it has a background, the background gets painted before
-// the layer's negative z-order children, so again, a promotion would cause a
-// change in paint order (causing the background to get painted after the
-// negative z-order children instead of before).
-//
-void RenderLayerStackingNode::computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >& list)
+RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContextNode() const
{
- OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderList;
- OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderList;
-
- RenderLayerStackingNode* stackingNode = ancestorStackingNode();
- if (!stackingNode)
- return;
-
- switch (type) {
- case BeforePromote:
- collectBeforePromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
- break;
- case AfterPromote:
- collectAfterPromotionZOrderList(stackingNode, posZOrderList, negZOrderList);
- break;
- }
-
- if (negZOrderList) {
- for (size_t index = 0; index < negZOrderList->size(); ++index)
- list.append(negZOrderList->at(index)->renderer()->node());
- }
-
- if (posZOrderList) {
- for (size_t index = 0; index < posZOrderList->size(); ++index)
- list.append(posZOrderList->at(index)->renderer()->node());
+ for (RenderLayer* ancestor = layer()->parent(); ancestor; ancestor = ancestor->parent()) {
+ RenderLayerStackingNode* stackingNode = ancestor->stackingNode();
+ if (stackingNode->isStackingContext())
+ return stackingNode;
}
-}
-
-bool RenderLayerStackingNode::descendantsAreContiguousInStackingOrder() const
-{
- if (isStackingContext() || !ancestorStackingContainerNode())
- return true;
-
- ASSERT(!m_descendantsAreContiguousInStackingOrderDirty);
- return m_descendantsAreContiguousInStackingOrder;
-}
-
-bool RenderLayerStackingNode::setNeedsToBeStackingContainer(bool needsToBeStackingContainer)
-{
- if (this->needsToBeStackingContainer() == needsToBeStackingContainer)
- return false;
-
- // Count the total number of RenderLayers which need to be stacking
- // containers some point. This should be recorded at most once per
- // RenderLayer, so we check m_needsToBeStackingContainerHasBeenRecorded.
- if (layer()->acceleratedCompositingForOverflowScrollEnabled() && !m_needsToBeStackingContainerHasBeenRecorded) {
- blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", RenderLayer::NeedsToBeStackingContainerBucket, RenderLayer::CompositedScrollingHistogramMax);
- m_needsToBeStackingContainerHasBeenRecorded = true;
- }
-
- m_needsToBeStackingContainer = needsToBeStackingContainer;
-
- return true;
-}
-
-RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContainerNode() const
-{
- RenderLayer* ancestor = layer()->parent();
- while (ancestor && !ancestor->stackingNode()->isStackingContainer())
- ancestor = ancestor->parent();
- if (ancestor)
- return ancestor->stackingNode();
- return 0;
-}
-
-RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingNode() const
-{
- RenderLayer* ancestor = layer()->parent();
- while (ancestor && !ancestor->stackingNode()->isStackingContext())
- ancestor = ancestor->parent();
- if (ancestor)
- return ancestor->stackingNode();
return 0;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.h
index 12d7490fd8f..abe6b68c218 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNode.h
@@ -65,20 +65,7 @@ public:
int zIndex() const { return renderer()->style()->zIndex(); }
// A stacking context is a layer that has a non-auto z-index.
- bool isStackingContext() const { return isStackingContext(renderer()->style()); }
-
- // A stacking container can have z-order lists. All stacking contexts are
- // stacking containers, but the converse is not true. Layers that use
- // composited scrolling are stacking containers, but they may not
- // necessarily be stacking contexts.
- bool isStackingContainer() const { return isStackingContext() || needsToBeStackingContainer(); }
-
- bool setNeedsToBeStackingContainer(bool);
-
- // Returns true if z ordering would not change if this layer were a stacking container.
- bool descendantsAreContiguousInStackingOrder() const;
- void setDescendantsAreContiguousInStackingOrderDirty(bool flag) { m_descendantsAreContiguousInStackingOrderDirty = flag; }
- void updateDescendantsAreContiguousInStackingOrder();
+ bool isStackingContext() const { return !renderer()->style()->hasAutoZIndex(); }
// Update our normal and z-index lists.
void updateLayerListsIfNeeded();
@@ -87,31 +74,28 @@ public:
void dirtyZOrderLists();
void updateZOrderLists();
void clearZOrderLists();
- void dirtyStackingContainerZOrderLists();
+ void dirtyStackingContextZOrderLists();
bool hasPositiveZOrderList() const { return posZOrderList() && posZOrderList()->size(); }
bool hasNegativeZOrderList() const { return negZOrderList() && negZOrderList()->size(); }
+ // FIXME: should check for dirtiness here?
bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
void updateIsNormalFlowOnly();
bool normalFlowListDirty() const { return m_normalFlowListDirty; }
void dirtyNormalFlowList();
- enum PaintOrderListType {BeforePromote, AfterPromote};
- void computePaintOrderList(PaintOrderListType, Vector<RefPtr<Node> >&);
-
void updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle);
- RenderLayerStackingNode* ancestorStackingContainerNode() const;
- RenderLayerStackingNode* ancestorStackingNode() const;
+ RenderLayerStackingNode* ancestorStackingContextNode() const;
- // Gets the enclosing stacking container for this node, possibly the node
- // itself, if it is a stacking container.
- RenderLayerStackingNode* enclosingStackingContainerNode() { return isStackingContainer() ? this : ancestorStackingContainerNode(); }
+ // Gets the enclosing stacking context for this node, possibly the node
+ // itself, if it is a stacking context.
+ RenderLayerStackingNode* enclosingStackingContextNode() { return isStackingContext() ? this : ancestorStackingContextNode(); }
RenderLayer* layer() const { return m_layer; }
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; }
#endif
@@ -124,7 +108,7 @@ private:
Vector<RenderLayerStackingNode*>* posZOrderList() const
{
ASSERT(!m_zOrderListsDirty);
- ASSERT(isStackingContainer() || !m_posZOrderList);
+ ASSERT(isStackingContext() || !m_posZOrderList);
return m_posZOrderList.get();
}
@@ -137,33 +121,14 @@ private:
Vector<RenderLayerStackingNode*>* negZOrderList() const
{
ASSERT(!m_zOrderListsDirty);
- ASSERT(isStackingContainer() || !m_negZOrderList);
+ ASSERT(isStackingContext() || !m_negZOrderList);
return m_negZOrderList.get();
}
- enum CollectLayersBehavior {
- ForceLayerToStackingContainer,
- OverflowScrollCanBeStackingContainers,
- OnlyStackingContextsCanBeStackingContainers
- };
-
- bool isStackingContext(const RenderStyle*) const;
-
void rebuildZOrderLists();
+ void collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList);
- // layerToForceAsStackingContainer allows us to build pre-promotion and
- // post-promotion layer lists, by allowing us to treat a layer as if it is a
- // stacking context, without adding a new member to RenderLayer or modifying
- // the style (which could cause extra allocations).
- void rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >&, OwnPtr<Vector<RenderLayerStackingNode*> >&,
- const RenderLayerStackingNode* nodeToForceAsStackingContainer = 0,
- CollectLayersBehavior = OverflowScrollCanBeStackingContainers);
-
- void collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >&,
- OwnPtr<Vector<RenderLayerStackingNode*> >&, const RenderLayerStackingNode* nodeToForceAsStackingContainer = 0,
- CollectLayersBehavior = OverflowScrollCanBeStackingContainers);
-
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool isInStackingParentZOrderLists() const;
bool isInStackingParentNormalFlowList() const;
void updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent);
@@ -172,21 +137,10 @@ private:
#endif
bool shouldBeNormalFlowOnly() const;
- bool shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const;
void updateNormalFlowList();
- void dirtyNormalFlowListCanBePromotedToStackingContainer();
-
- void dirtySiblingStackingNodeCanBePromotedToStackingContainer();
-
- void collectBeforePromotionZOrderList(RenderLayerStackingNode*,
- OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList);
- void collectAfterPromotionZOrderList(RenderLayerStackingNode*,
- OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList);
- bool isDirtyStackingContainer() const { return m_zOrderListsDirty && isStackingContainer(); }
-
- bool needsToBeStackingContainer() const;
+ bool isDirtyStackingContext() const { return m_zOrderListsDirty && isStackingContext(); }
RenderLayerCompositor* compositor() const;
// FIXME: Investigate changing this to Renderbox.
@@ -194,31 +148,21 @@ private:
RenderLayer* m_layer;
- // For stacking contexts, m_posZOrderList holds a sorted list of all the
- // descendant nodes within the stacking context that have z-indices of 0 or greater
- // (auto will count as 0). m_negZOrderList holds descendants within our stacking context with negative
- // z-indices.
+ // m_posZOrderList holds a sorted list of all the descendant nodes within
+ // that have z-indices of 0 or greater (auto will count as 0).
+ // m_negZOrderList holds descendants within our stacking context with
+ // negative z-indices.
OwnPtr<Vector<RenderLayerStackingNode*> > m_posZOrderList;
OwnPtr<Vector<RenderLayerStackingNode*> > m_negZOrderList;
- // This list contains child nodes that cannot create stacking contexts. For now it is just
- // overflow layers, but that may change in the future.
+ // This list contains child nodes that cannot create stacking contexts.
OwnPtr<Vector<RenderLayerStackingNode*> > m_normalFlowList;
- // If this is true, then no non-descendant appears between any of our
- // descendants in stacking order. This is one of the requirements of being
- // able to safely become a stacking context.
- unsigned m_descendantsAreContiguousInStackingOrder : 1;
- unsigned m_descendantsAreContiguousInStackingOrderDirty : 1;
-
unsigned m_zOrderListsDirty : 1;
unsigned m_normalFlowListDirty: 1;
unsigned m_isNormalFlowOnly : 1;
- unsigned m_needsToBeStackingContainer : 1;
- unsigned m_needsToBeStackingContainerHasBeenRecorded : 1;
-
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
unsigned m_layerListMutationAllowed : 1;
RenderLayerStackingNode* m_stackingParent;
#endif
@@ -226,9 +170,9 @@ private:
inline void RenderLayerStackingNode::clearZOrderLists()
{
- ASSERT(!isStackingContainer());
+ ASSERT(!isStackingContext());
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
updateStackingParentForZOrderLists(0);
#endif
@@ -241,7 +185,7 @@ inline void RenderLayerStackingNode::updateZOrderLists()
if (!m_zOrderListsDirty)
return;
- if (!isStackingContainer()) {
+ if (!isStackingContext()) {
clearZOrderLists();
m_zOrderListsDirty = false;
return;
@@ -250,7 +194,7 @@ inline void RenderLayerStackingNode::updateZOrderLists()
rebuildZOrderLists();
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
class LayerListMutationDetector {
public:
explicit LayerListMutationDetector(RenderLayerStackingNode* stackingNode)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNodeIterator.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNodeIterator.h
index 7682ea33d58..b230371fe1a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNodeIterator.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLayerStackingNodeIterator.h
@@ -42,7 +42,6 @@ enum ChildrenIteration {
AllChildren = NegativeZOrderChildren | NormalFlowChildren | PositiveZOrderChildren
};
-class RenderLayer;
class RenderLayerStackingNode;
// This iterator walks the RenderLayerStackingNode lists in the following order:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.cpp
index 085224721fe..9e0f01a30bc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.cpp
@@ -170,27 +170,25 @@ bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, Layo
return true;
}
-bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, const LayoutRect& rect, const LayoutPoint& offset, LayoutUnit outlineSize) const
+bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, const LayoutRect& rect, const LayoutPoint& offset) const
{
// We can check the first box and last box and avoid painting/hit testing if we don't
// intersect. This is a quick short-circuit that we can take to avoid walking any lines.
// FIXME: This check is flawed in the following extremely obscure way:
// if some line in the middle has a huge overflow, it might actually extend below the last line.
- RootInlineBox* firstRootBox = firstLineBox()->root();
- RootInlineBox* lastRootBox = lastLineBox()->root();
- LayoutUnit firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
- LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom());
- LayoutUnit logicalTop = firstLineTop - outlineSize;
- LayoutUnit logicalBottom = outlineSize + lastLineBottom;
-
- return rangeIntersectsRect(renderer, logicalTop, logicalBottom, rect, offset);
+ RootInlineBox& firstRootBox = firstLineBox()->root();
+ RootInlineBox& lastRootBox = lastLineBox()->root();
+ LayoutUnit firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox.lineTop());
+ LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom());
+
+ return rangeIntersectsRect(renderer, firstLineTop, lastLineBottom, rect, offset);
}
bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer, InlineFlowBox* box, const PaintInfo& paintInfo, const LayoutPoint& offset) const
{
- RootInlineBox* root = box->root();
- LayoutUnit logicalTop = min<LayoutUnit>(box->logicalTopVisualOverflow(root->lineTop()), root->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase);
- LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(root->lineBottom()) + renderer->maximalOutlineSize(paintInfo.phase);
+ RootInlineBox& root = box->root();
+ LayoutUnit logicalTop = min<LayoutUnit>(box->logicalTopVisualOverflow(root.lineTop()), root.selectionTop());
+ LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(root.lineBottom());
return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.rect, offset);
}
@@ -209,8 +207,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
if (!firstLineBox())
return;
- LayoutUnit outlineSize = renderer->maximalOutlineSize(paintInfo.phase);
- if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset, outlineSize))
+ if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset))
return;
PaintInfo info(paintInfo);
@@ -222,8 +219,8 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
// based off positions of our first line box or our last line box.
for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
if (lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) {
- RootInlineBox* root = curr->root();
- curr->paint(info, paintOffset, root->lineTop(), root->lineBottom());
+ RootInlineBox& root = curr->root();
+ curr->paint(info, paintOffset, root.lineTop(), root.lineBottom());
}
}
@@ -260,9 +257,9 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq
// them further. Note that boxes can easily overlap, so we can't make any assumptions
// based off positions of our first line box or our last line box.
for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) {
- RootInlineBox* root = curr->root();
- if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root->lineTop()), curr->logicalBottomVisualOverflow(root->lineBottom()), rect, accumulatedOffset)) {
- bool inside = curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, root->lineTop(), root->lineBottom());
+ RootInlineBox& root = curr->root();
+ if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root.lineTop()), curr->logicalBottomVisualOverflow(root.lineBottom()), rect, accumulatedOffset)) {
+ bool inside = curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, root.lineTop(), root.lineBottom());
if (inside) {
renderer->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
return true;
@@ -304,15 +301,15 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend
if (curr->isReplaced()) {
InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper();
if (wrapper)
- box = wrapper->root();
+ box = &wrapper->root();
} else if (curr->isText()) {
InlineTextBox* textBox = toRenderText(curr)->lastTextBox();
if (textBox)
- box = textBox->root();
+ box = &textBox->root();
} else if (curr->isRenderInline()) {
InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling();
if (lastSiblingBox)
- box = lastSiblingBox->root();
+ box = &lastSiblingBox->root();
}
if (box)
@@ -331,7 +328,7 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend
}
return;
}
- box = firstBox->root();
+ box = &firstBox->root();
}
// If we found a line box, then dirty it.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.h b/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.h
index b57a4a03806..611b4d42ba8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderLineBoxList.h
@@ -67,7 +67,7 @@ public:
bool hitTest(RenderBoxModelObject*, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) const;
private:
- bool anyLineIntersectsRect(RenderBoxModelObject*, const LayoutRect&, const LayoutPoint&, LayoutUnit outlineSize = 0) const;
+ bool anyLineIntersectsRect(RenderBoxModelObject*, const LayoutRect&, const LayoutPoint&) const;
bool lineIntersectsDirtyRect(RenderBoxModelObject*, InlineFlowBox*, const PaintInfo&, const LayoutPoint&) const;
bool rangeIntersectsRect(RenderBoxModelObject*, LayoutUnit logicalTop, LayoutUnit logicalBottom, const LayoutRect&, const LayoutPoint&) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.cpp
index bc4617f29ff..82c22b91945 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.cpp
@@ -30,25 +30,23 @@
#include "config.h"
#include "core/rendering/RenderListBox.h"
-#include <math.h>
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Document.h"
#include "core/dom/NodeRenderStyle.h"
#include "core/editing/FrameSelection.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLOptGroupElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/page/EventHandler.h"
#include "core/page/FocusController.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
#include "core/page/Page.h"
#include "core/page/SpatialNavigation.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderScrollbar.h"
#include "core/rendering/RenderText.h"
@@ -57,6 +55,8 @@
#include "platform/fonts/FontCache.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/scroll/Scrollbar.h"
+#include "platform/text/BidiTextRun.h"
+#include <math.h>
using namespace std;
@@ -86,10 +86,11 @@ RenderListBox::RenderListBox(Element* element)
, m_inAutoscroll(false)
, m_optionsWidth(0)
, m_indexOffset(0)
+ , m_listItemCount(0)
{
ASSERT(element);
ASSERT(element->isHTMLElement());
- ASSERT(element->hasTagName(HTMLNames::selectTag));
+ ASSERT(isHTMLSelectElement(element));
if (FrameView* frameView = frame()->view())
frameView->addScrollableArea(this);
@@ -103,6 +104,13 @@ RenderListBox::~RenderListBox()
frameView->removeScrollableArea(this);
}
+// FIXME: Instead of this hack we should add a ShadowRoot to <select> with no insertion point
+// to prevent children from rendering.
+bool RenderListBox::isChildAllowed(RenderObject* object, RenderStyle*) const
+{
+ return object->isAnonymous() && !object->isRenderFullScreen();
+}
+
inline HTMLSelectElement* RenderListBox::selectElement() const
{
return toHTMLSelectElement(node());
@@ -111,30 +119,46 @@ inline HTMLSelectElement* RenderListBox::selectElement() const
void RenderListBox::updateFromElement()
{
FontCachePurgePreventer fontCachePurgePreventer;
-
if (m_optionsChanged) {
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
- int size = numItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
+ int size = static_cast<int>(listItems.size());
float width = 0;
+ m_listItemCount = 0;
for (int i = 0; i < size; ++i) {
- HTMLElement* element = listItems[i];
+ const HTMLElement& element = *listItems[i];
+
String text;
Font itemFont = style()->font();
- if (element->hasTagName(optionTag)) {
- text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+ if (isHTMLOptionElement(element)) {
+ const HTMLOptionElement& optionElement = toHTMLOptionElement(element);
+ if (optionElement.isDisplayNone())
+ continue;
+ text = optionElement.textIndentedToRespectGroupLabel();
+ ++m_listItemCount;
} else if (isHTMLOptGroupElement(element)) {
- text = toHTMLOptGroupElement(element)->groupLabelText();
+ if (toHTMLOptGroupElement(element).isDisplayNone())
+ continue;
+ text = toHTMLOptGroupElement(element).groupLabelText();
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
- itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+ itemFont = Font(d);
itemFont.update(document().styleEngine()->fontSelector());
+ ++m_listItemCount;
+ } else if (isHTMLHRElement(element)) {
+ // HTMLSelect adds it to its list, so we will also add it to match the count.
+ ++m_listItemCount;
+ continue;
}
if (!text.isEmpty()) {
applyTextTransform(style(), text, ' ');
- // FIXME: Why is this always LTR? Can't text direction affect the width?
+
+ bool hasStrongDirectionality;
+ TextDirection direction = determineDirectionality(text, hasStrongDirectionality);
TextRun textRun = constructTextRun(this, itemFont, text, style(), TextRun::AllowTrailingExpansion);
+ if (hasStrongDirectionality)
+ textRun.setDirection(direction);
textRun.disableRoundingHacks();
float textWidth = itemFont.width(textRun);
width = max(width, textWidth);
@@ -145,13 +169,13 @@ void RenderListBox::updateFromElement()
setHasVerticalScrollbar(true);
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
void RenderListBox::selectionChanged()
{
- repaint();
+ paintInvalidationForWholeRenderer();
if (!m_inAutoscroll) {
if (m_optionsChanged || needsLayout())
m_scrollToRevealSelectionAfterLayout = true;
@@ -165,7 +189,6 @@ void RenderListBox::selectionChanged()
void RenderListBox::layout()
{
- LayoutRectRecorder recorder(*this);
RenderBlockFlow::layout();
if (m_vBar) {
@@ -179,27 +202,32 @@ void RenderListBox::layout()
}
if (m_scrollToRevealSelectionAfterLayout) {
- LayoutStateDisabler layoutStateDisabler(view());
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
scrollToRevealSelection();
}
}
+void RenderListBox::invalidateTreeAfterLayout(const RenderLayerModelObject& invalidationContainer)
+{
+ repaintScrollbarIfNeeded();
+ RenderBox::invalidateTreeAfterLayout(invalidationContainer);
+}
+
void RenderListBox::scrollToRevealSelection()
{
HTMLSelectElement* select = selectElement();
m_scrollToRevealSelectionAfterLayout = false;
- int firstIndex = select->activeSelectionStartListIndex();
- if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex()))
- scrollToRevealElementAtListIndex(firstIndex);
+ int firstIndex = listIndexToRenderListBoxIndex(select->activeSelectionStartListIndex());
+ int lastIndex = listIndexToRenderListBoxIndex(select->activeSelectionEndListIndex());
+ if (firstIndex >= 0 && !listIndexIsVisible(lastIndex))
+ scrollToRevealElementAtListIndexInternal(firstIndex);
}
void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
- maxLogicalWidth = m_optionsWidth + 2 * optionsSpacingHorizontal;
- if (m_vBar)
- maxLogicalWidth += verticalScrollbarWidth();
+ maxLogicalWidth = m_optionsWidth + 2 * optionsSpacingHorizontal + verticalScrollbarWidth();
if (!style()->width().isPercent())
minLogicalWidth = maxLogicalWidth;
}
@@ -210,20 +238,21 @@ void RenderListBox::computePreferredLogicalWidths()
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
+ RenderStyle* styleToUse = style();
- if (style()->width().isFixed() && style()->width().value() > 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+ if (styleToUse->width().isFixed() && styleToUse->width().value() > 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->width().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+ if (styleToUse->minWidth().isFixed() && styleToUse->minWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
}
- if (style()->maxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+ if (styleToUse->maxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
}
LayoutUnit toAdd = borderAndPaddingWidth();
@@ -250,7 +279,7 @@ int RenderListBox::numVisibleItems() const
int RenderListBox::numItems() const
{
- return selectElement()->listItems().size();
+ return m_listItemCount;
}
LayoutUnit RenderListBox::listHeight() const
@@ -260,7 +289,12 @@ LayoutUnit RenderListBox::listHeight() const
void RenderListBox::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
- LayoutUnit height = itemHeight() * size() - rowSpacing + borderAndPaddingHeight();
+ LayoutUnit height = itemHeight() * size() - rowSpacing;
+ // FIXME: The item height should have been added before updateLogicalHeight was called to avoid this hack.
+ updateIntrinsicContentLogicalHeight(height);
+
+ height += borderAndPaddingHeight();
+
RenderBox::computeLogicalHeight(height, logicalTop, computedValues);
}
@@ -269,7 +303,7 @@ int RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, L
return RenderBox::baselinePosition(baselineType, firstLine, lineDirection, linePositionMode) - baselineAdjustment;
}
-LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& additionalOffset, int index)
+LayoutRect RenderListBox::itemBoundingBoxRectInternal(const LayoutPoint& additionalOffset, int index) const
{
// For RTL, items start after the left-side vertical scrollbar.
int scrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? verticalScrollbarWidth() : 0;
@@ -294,7 +328,7 @@ void RenderListBox::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOf
}
// Paint the children.
- RenderBlock::paintObject(paintInfo, paintOffset);
+ RenderBlockFlow::paintObject(paintInfo, paintOffset);
switch (paintInfo.phase) {
// Depending on whether we have overlay scrollbars they
@@ -324,24 +358,24 @@ void RenderListBox::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOf
void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
{
if (!isSpatialNavigationEnabled(frame()))
- return RenderBlock::addFocusRingRects(rects, additionalOffset, paintContainer);
+ return RenderBlockFlow::addFocusRingRects(rects, additionalOffset, paintContainer);
HTMLSelectElement* select = selectElement();
// Focus the last selected item.
int selectedItem = select->activeSelectionEndListIndex();
if (selectedItem >= 0) {
- rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, selectedItem)));
+ rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additionalOffset, selectedItem)));
return;
}
// No selected items, find the first non-disabled item.
int size = numItems();
- const Vector<HTMLElement*>& listItems = select->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = select->listItems();
for (int i = 0; i < size; ++i) {
- HTMLElement* element = listItems[i];
- if (element->hasTagName(optionTag) && !element->isDisabledFormControl()) {
- rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, i)));
+ HTMLElement* element = listItems[renderListBoxIndexToListIndex(i)];
+ if (isHTMLOptionElement(*element) && !element->isDisabledFormControl()) {
+ rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additionalOffset, i)));
return;
}
}
@@ -353,7 +387,7 @@ int RenderListBox::scrollbarLeft() const
if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
scrollbarLeft = borderLeft();
else
- scrollbarLeft = width() - borderRight() - verticalScrollbarWidth();
+ scrollbarLeft = width() - borderRight() - (m_vBar ? m_vBar->width() : 0);
return scrollbarLeft;
}
@@ -362,7 +396,7 @@ void RenderListBox::paintScrollbar(PaintInfo& paintInfo, const LayoutPoint& pain
if (m_vBar) {
IntRect scrollRect = pixelSnappedIntRect(paintOffset.x() + scrollbarLeft(),
paintOffset.y() + borderTop(),
- verticalScrollbarWidth(),
+ m_vBar->width(),
height() - (borderTop() + borderBottom()));
m_vBar->setFrameRect(scrollRect);
m_vBar->paint(paintInfo.context, paintInfo.rect);
@@ -395,8 +429,8 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
HTMLSelectElement* select = selectElement();
- const Vector<HTMLElement*>& listItems = select->listItems();
- HTMLElement* element = listItems[listIndex];
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = select->listItems();
+ HTMLElement* element = listItems[renderListBoxIndexToListIndex(listIndex)];
RenderStyle* itemStyle = element->renderStyle();
if (!itemStyle)
@@ -406,15 +440,15 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
return;
String itemText;
- bool isOptionElement = element->hasTagName(optionTag);
+ bool isOptionElement = isHTMLOptionElement(*element);
if (isOptionElement)
- itemText = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
- else if (isHTMLOptGroupElement(element))
- itemText = toHTMLOptGroupElement(element)->groupLabelText();
+ itemText = toHTMLOptionElement(*element).textIndentedToRespectGroupLabel();
+ else if (isHTMLOptGroupElement(*element))
+ itemText = toHTMLOptGroupElement(*element).groupLabelText();
applyTextTransform(style(), itemText, ' ');
Color textColor = element->renderStyle() ? resolveColor(element->renderStyle(), CSSPropertyColor) : resolveColor(CSSPropertyColor);
- if (isOptionElement && toHTMLOptionElement(element)->selected()) {
+ if (isOptionElement && ((toHTMLOptionElement(*element).selected() && select->suggestedIndex() < 0) || listIndex == select->suggestedIndex())) {
if (frame()->selection().isFocusedAndActive() && document().focusedElement() == node())
textColor = RenderTheme::theme().activeListBoxSelectionForegroundColor();
// Honor the foreground color for disabled items
@@ -426,13 +460,13 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->direction(), isOverride(itemStyle->unicodeBidi()), true, TextRun::NoRounding);
Font itemFont = style()->font();
- LayoutRect r = itemBoundingBoxRect(paintOffset, listIndex);
+ LayoutRect r = itemBoundingBoxRectInternal(paintOffset, listIndex);
r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r));
- if (isHTMLOptGroupElement(element)) {
+ if (isHTMLOptGroupElement(*element)) {
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
- itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+ itemFont = Font(d);
itemFont.update(document().styleEngine()->fontSelector());
}
@@ -444,11 +478,11 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex)
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
- HTMLElement* element = listItems[listIndex];
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
+ HTMLElement* element = listItems[renderListBoxIndexToListIndex(listIndex)];
Color backColor;
- if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected()) {
+ if (isHTMLOptionElement(*element) && ((toHTMLOptionElement(*element).selected() && selectElement()->suggestedIndex() < 0) || listIndex == selectElement()->suggestedIndex())) {
if (frame()->selection().isFocusedAndActive() && document().focusedElement() == node())
backColor = RenderTheme::theme().activeListBoxSelectionBackgroundColor();
else
@@ -459,7 +493,7 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint&
// Draw the background for this list box item
if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) {
- LayoutRect itemRect = itemBoundingBoxRect(paintOffset, listIndex);
+ LayoutRect itemRect = itemBoundingBoxRectInternal(paintOffset, listIndex);
itemRect.intersect(controlClipRect(paintOffset));
paintInfo.context->fillRect(pixelSnappedIntRect(itemRect), backColor);
}
@@ -482,7 +516,7 @@ bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const Layout
return false;
}
-int RenderListBox::listIndexAtOffset(const LayoutSize& offset)
+int RenderListBox::listIndexAtOffset(const LayoutSize& offset) const
{
if (!numItems())
return -1;
@@ -498,7 +532,7 @@ int RenderListBox::listIndexAtOffset(const LayoutSize& offset)
return -1;
int newOffset = (offset.height() - borderTop() - paddingTop()) / itemHeight() + m_indexOffset;
- return newOffset < numItems() ? newOffset : -1;
+ return newOffset < numItems() ? renderListBoxIndexToListIndex(newOffset) : -1;
}
void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
@@ -527,8 +561,7 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
return;
if (yDelta > 0)
- //offsetY = view()->viewHeight();
- absOffset.move(0, listHeight());
+ absOffset.move(0, listHeight().toFloat());
else if (yDelta < 0)
yDelta--;
@@ -556,10 +589,10 @@ int RenderListBox::scrollToward(const IntPoint& destination)
int rows = numVisibleItems();
int offset = m_indexOffset;
- if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1))
+ if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealElementAtListIndexInternal(offset - 1))
return offset - 1;
- if (positionOffset.height() > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows))
+ if (positionOffset.height() > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndexInternal(offset + rows))
return offset + rows - 1;
return listIndexAtOffset(positionOffset);
@@ -578,9 +611,9 @@ void RenderListBox::autoscroll(const IntPoint&)
m_inAutoscroll = true;
if (!select->multiple())
- select->setActiveSelectionAnchorIndex(endIndex);
+ select->setActiveSelectionAnchorIndex(renderListBoxIndexToListIndex(endIndex));
- select->setActiveSelectionEndIndex(endIndex);
+ select->setActiveSelectionEndIndex(renderListBoxIndexToListIndex(endIndex));
select->updateListBoxSelection(!select->multiple());
m_inAutoscroll = false;
}
@@ -594,7 +627,7 @@ void RenderListBox::stopAutoscroll()
selectElement()->listBoxOnChange();
}
-bool RenderListBox::scrollToRevealElementAtListIndex(int index)
+bool RenderListBox::scrollToRevealElementAtListIndexInternal(int index)
{
if (index < 0 || index >= numItems() || listIndexIsVisible(index))
return false;
@@ -610,7 +643,7 @@ bool RenderListBox::scrollToRevealElementAtListIndex(int index)
return true;
}
-bool RenderListBox::listIndexIsVisible(int index)
+bool RenderListBox::listIndexIsVisible(int index) const
{
return index >= m_indexOffset && index < m_indexOffset + numVisibleItems();
}
@@ -620,13 +653,6 @@ bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granular
return ScrollableArea::scroll(direction, granularity, multiplier);
}
-void RenderListBox::valueChanged(unsigned listIndex)
-{
- HTMLSelectElement* element = selectElement();
- element->setSelectedIndex(element->listToOptionIndex(listIndex));
- element->dispatchFormControlChangeEvent();
-}
-
int RenderListBox::scrollSize(ScrollbarOrientation orientation) const
{
return orientation == VerticalScrollbar ? (numItems() - numVisibleItems()) : 0;
@@ -648,7 +674,12 @@ void RenderListBox::scrollTo(int newOffset)
return;
m_indexOffset = newOffset;
- repaint();
+
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInPerformLayout())
+ setShouldDoFullPaintInvalidationAfterLayout(true);
+ else
+ paintInvalidationForWholeRenderer();
+
node()->document().enqueueScrollEventForNode(node());
}
@@ -664,32 +695,32 @@ int RenderListBox::verticalScrollbarWidth() const
// FIXME: We ignore padding in the vertical direction as far as these values are concerned, since that's
// how the control currently paints.
-int RenderListBox::scrollWidth() const
+LayoutUnit RenderListBox::scrollWidth() const
{
// There is no horizontal scrolling allowed.
- return pixelSnappedClientWidth();
+ return clientWidth();
}
-int RenderListBox::scrollHeight() const
+LayoutUnit RenderListBox::scrollHeight() const
{
- return max(pixelSnappedClientHeight(), roundToInt(listHeight()));
+ return max(clientHeight(), listHeight());
}
-int RenderListBox::scrollLeft() const
+LayoutUnit RenderListBox::scrollLeft() const
{
return 0;
}
-void RenderListBox::setScrollLeft(int)
+void RenderListBox::setScrollLeft(LayoutUnit)
{
}
-int RenderListBox::scrollTop() const
+LayoutUnit RenderListBox::scrollTop() const
{
return m_indexOffset * itemHeight();
}
-void RenderListBox::setScrollTop(int newTop)
+void RenderListBox::setScrollTop(LayoutUnit newTop)
{
// Determine an index and scroll to it.
int index = newTop / itemHeight();
@@ -701,15 +732,15 @@ void RenderListBox::setScrollTop(int newTop)
bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- if (!RenderBlock::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
+ if (!RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
return false;
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
int size = numItems();
LayoutPoint adjustedLocation = accumulatedOffset + location();
for (int i = 0; i < size; ++i) {
- if (itemBoundingBoxRect(adjustedLocation, i).contains(locationInContainer.point())) {
- if (Element* node = listItems[i]) {
+ if (itemBoundingBoxRectInternal(adjustedLocation, i).contains(locationInContainer.point())) {
+ if (Element* node = listItems[renderListBoxIndexToListIndex(i)]) {
result.setInnerNode(node);
if (!result.innerNonSharedNode())
result.setInnerNonSharedNode(node);
@@ -745,7 +776,22 @@ void RenderListBox::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect&
scrollRect.move(borderLeft(), borderTop());
else
scrollRect.move(width() - borderRight() - scrollbar->width(), borderTop());
- repaintRectangle(scrollRect);
+
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInPerformLayout()) {
+ m_verticalBarDamage = scrollRect;
+ m_hasVerticalBarDamage = true;
+ } else {
+ invalidatePaintRectangle(scrollRect);
+ }
+}
+
+void RenderListBox::repaintScrollbarIfNeeded()
+{
+ if (!hasVerticalBarDamage())
+ return;
+ invalidatePaintRectangle(verticalBarDamage());
+
+ resetScrollbarDamage();
}
IntRect RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
@@ -759,7 +805,7 @@ IntRect RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scr
int scrollbarTop = borderTop();
rect.move(scrollbarLeft(), scrollbarTop);
- return view->frameView()->convertFromRenderer(this, rect);
+ return view->frameView()->convertFromRenderer(*this, rect);
}
IntRect RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
@@ -768,7 +814,7 @@ IntRect RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scr
if (!view)
return parentRect;
- IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
+ IntRect rect = view->frameView()->convertToRenderer(*this, parentRect);
int scrollbarTop = borderTop();
rect.move(-scrollbarLeft(), -scrollbarTop);
@@ -786,7 +832,7 @@ IntPoint RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* sc
int scrollbarTop = borderTop();
point.move(scrollbarLeft(), scrollbarTop);
- return view->frameView()->convertFromRenderer(this, point);
+ return view->frameView()->convertFromRenderer(*this, point);
}
IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
@@ -795,7 +841,7 @@ IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* sc
if (!view)
return parentPoint;
- IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
+ IntPoint point = view->frameView()->convertToRenderer(*this, parentPoint);
int scrollbarTop = borderTop();
point.move(-scrollbarLeft(), -scrollbarTop);
@@ -848,7 +894,7 @@ IntPoint RenderListBox::minimumScrollPosition() const
IntPoint RenderListBox::maximumScrollPosition() const
{
- return IntPoint(0, numItems() - numVisibleItems());
+ return IntPoint(0, std::max(numItems() - numVisibleItems(), 0));
}
bool RenderListBox::userInputScrollable(ScrollbarOrientation orientation) const
@@ -876,12 +922,6 @@ float RenderListBox::pixelStep(ScrollbarOrientation) const
return 1.0f / itemHeight();
}
-ScrollableArea* RenderListBox::enclosingScrollableArea() const
-{
- // FIXME: Return a RenderLayer that's scrollable.
- return 0;
-}
-
IntRect RenderListBox::scrollableAreaBoundingBox() const
{
return absoluteBoundingBoxRect();
@@ -910,7 +950,7 @@ void RenderListBox::destroyScrollbar()
ScrollableArea::willRemoveScrollbar(m_vBar.get(), VerticalScrollbar);
m_vBar->removeFromParent();
m_vBar->disconnectFromScrollableArea();
- m_vBar = 0;
+ m_vBar = nullptr;
}
void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar)
@@ -931,4 +971,59 @@ void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar)
document().setAnnotatedRegionsDirty(true);
}
+int RenderListBox::renderListBoxIndexToListIndex(int index) const
+{
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
+ const int size = static_cast<int>(listItems.size());
+
+ if (size == numItems())
+ return index;
+
+ int listBoxIndex = 0;
+ int listIndex = 0;
+ for (; listIndex < size; ++listIndex) {
+ const HTMLElement& element = *listItems[listIndex];
+ if (isHTMLOptionElement(element) && toHTMLOptionElement(element).isDisplayNone())
+ continue;
+ if (isHTMLOptGroupElement(element) && toHTMLOptGroupElement(element).isDisplayNone())
+ continue;
+ if (index == listBoxIndex)
+ break;
+ ++listBoxIndex;
+ }
+ return listIndex;
+}
+
+int RenderListBox::listIndexToRenderListBoxIndex(int index) const
+{
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
+ const int size = static_cast<int>(listItems.size());
+
+ if (size == numItems())
+ return index;
+
+ int listBoxIndex = 0;
+ for (int listIndex = 0; listIndex < size; ++listIndex) {
+ const HTMLElement& element = *listItems[listIndex];
+ if (isHTMLOptionElement(element) && toHTMLOptionElement(element).isDisplayNone())
+ continue;
+ if (isHTMLOptGroupElement(element) && toHTMLOptGroupElement(element).isDisplayNone())
+ continue;
+ if (index == listIndex)
+ break;
+ ++listBoxIndex;
+ }
+ return listBoxIndex;
+}
+
+LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& point, int index) const
+{
+ return itemBoundingBoxRectInternal(point, listIndexToRenderListBoxIndex(index));
+}
+
+bool RenderListBox::scrollToRevealElementAtListIndex(int index)
+{
+ return scrollToRevealElementAtListIndexInternal(listIndexToRenderListBoxIndex(index));
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.h b/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.h
index c86b50869bc..9a99eab5f17 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderListBox.h
@@ -47,57 +47,58 @@ public:
void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
- int listIndexAtOffset(const LayoutSize&);
- LayoutRect itemBoundingBoxRect(const LayoutPoint&, int index);
+ int listIndexAtOffset(const LayoutSize&) const;
+ LayoutRect itemBoundingBoxRect(const LayoutPoint&, int index) const;
bool scrollToRevealElementAtListIndex(int index);
- bool listIndexIsVisible(int index);
int scrollToward(const IntPoint&); // Returns the new index or -1 if no scroll occurred
int size() const;
+ void repaintScrollbarIfNeeded();
+
private:
HTMLSelectElement* selectElement() const;
- virtual const char* renderName() const { return "RenderListBox"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderListBox"; }
- virtual bool isListBox() const { return true; }
+ virtual bool isListBox() const OVERRIDE { return true; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
- virtual void updateFromElement();
- virtual bool hasControlClip() const { return true; }
- virtual void paintObject(PaintInfo&, const LayoutPoint&);
- virtual LayoutRect controlClipRect(const LayoutPoint&) const;
+ virtual void updateFromElement() OVERRIDE;
+ virtual bool hasControlClip() const OVERRIDE { return true; }
+ virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual LayoutRect controlClipRect(const LayoutPoint&) const OVERRIDE;
- virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
+ virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE;
virtual bool scroll(ScrollDirection, ScrollGranularity, float) OVERRIDE;
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE;
- virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+ virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE FINAL;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
- virtual bool canBeProgramaticallyScrolled() const { return true; }
- virtual void autoscroll(const IntPoint&);
- virtual void stopAutoscroll();
+ virtual bool canBeProgramaticallyScrolled() const OVERRIDE { return true; }
+ virtual void autoscroll(const IntPoint&) OVERRIDE;
+ virtual void stopAutoscroll() OVERRIDE;
- virtual bool shouldPanScroll() const { return true; }
- virtual void panScroll(const IntPoint&);
+ virtual void panScroll(const IntPoint&) OVERRIDE;
- virtual int verticalScrollbarWidth() const;
- virtual int scrollLeft() const;
- virtual int scrollTop() const;
- virtual int scrollWidth() const;
- virtual int scrollHeight() const;
- virtual void setScrollLeft(int);
- virtual void setScrollTop(int);
+ virtual int verticalScrollbarWidth() const OVERRIDE;
+ virtual LayoutUnit scrollLeft() const OVERRIDE;
+ virtual LayoutUnit scrollTop() const OVERRIDE;
+ virtual LayoutUnit scrollWidth() const OVERRIDE;
+ virtual LayoutUnit scrollHeight() const OVERRIDE;
+ virtual void setScrollLeft(LayoutUnit) OVERRIDE;
+ virtual void setScrollTop(LayoutUnit) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
@@ -125,14 +126,14 @@ private:
virtual IntPoint maximumScrollPosition() const OVERRIDE;
virtual bool userInputScrollable(ScrollbarOrientation) const OVERRIDE;
virtual bool shouldPlaceVerticalScrollbarOnLeft() const OVERRIDE;
- virtual int lineStep(ScrollbarOrientation) const;
- virtual int pageStep(ScrollbarOrientation) const;
- virtual float pixelStep(ScrollbarOrientation) const;
-
-
- virtual ScrollableArea* enclosingScrollableArea() const OVERRIDE;
+ virtual int lineStep(ScrollbarOrientation) const OVERRIDE;
+ virtual int pageStep(ScrollbarOrientation) const OVERRIDE;
+ virtual float pixelStep(ScrollbarOrientation) const OVERRIDE;
virtual IntRect scrollableAreaBoundingBox() const OVERRIDE;
+ LayoutRect itemBoundingBoxRectInternal(const LayoutPoint&, int index) const;
+ bool scrollToRevealElementAtListIndexInternal(int index);
+
// NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
void scrollTo(int newOffset);
@@ -141,8 +142,8 @@ private:
void destroyScrollbar();
LayoutUnit itemHeight() const;
- void valueChanged(unsigned listIndex);
int numVisibleItems() const;
+ bool listIndexIsVisible(int index) const;
int numItems() const;
LayoutUnit listHeight() const;
int scrollbarLeft() const;
@@ -151,11 +152,15 @@ private:
void paintItemBackground(PaintInfo&, const LayoutPoint&, int listIndex);
void scrollToRevealSelection();
+ int renderListBoxIndexToListIndex(int index) const;
+ int listIndexToRenderListBoxIndex(int index) const;
+
bool m_optionsChanged;
bool m_scrollToRevealSelectionAfterLayout;
bool m_inAutoscroll;
int m_optionsWidth;
int m_indexOffset;
+ int m_listItemCount;
RefPtr<Scrollbar> m_vBar;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.cpp
index b3b57a571ba..54d3d2d7e4b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.cpp
@@ -24,10 +24,10 @@
#include "config.h"
#include "core/rendering/RenderListItem.h"
-#include "HTMLNames.h"
-#include "core/dom/ElementTraversal.h"
+#include "core/HTMLNames.h"
+#include "core/dom/NodeRenderingTraversal.h"
#include "core/html/HTMLOListElement.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/RenderListMarker.h"
#include "core/rendering/RenderView.h"
#include "wtf/StdLibExtras.h"
@@ -51,15 +51,11 @@ RenderListItem::RenderListItem(Element* element)
void RenderListItem::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- RenderBlock::styleDidChange(diff, oldStyle);
+ RenderBlockFlow::styleDidChange(diff, oldStyle);
if (style()->listStyleType() != NoneListStyle
|| (style()->listStyleImage() && !style()->listStyleImage()->errorOccurred())) {
RefPtr<RenderStyle> newStyle = RenderStyle::create();
- // Markers update their own margin style. By copying the existing style we can
- // avoid an unnecessary layout in setStyle below.
- if (m_marker)
- newStyle->copyNonInheritedFrom(m_marker->style());
// The marker always inherits from the list item, regardless of where it might end
// up (e.g., in some deeply nested line box). See CSS3 spec.
newStyle->inheritFrom(style());
@@ -95,9 +91,9 @@ void RenderListItem::willBeRemovedFromTree()
updateListMarkerNumbers();
}
-static bool isList(const Node* node)
+static bool isList(const Node& node)
{
- return (node->hasTagName(ulTag) || node->hasTagName(olTag));
+ return isHTMLUListElement(node) || isHTMLOListElement(node);
}
// Returns the enclosing list with respect to the DOM order.
@@ -106,8 +102,8 @@ static Node* enclosingList(const RenderListItem* listItem)
Node* listItemNode = listItem->node();
Node* firstNode = 0;
// We use parentNode because the enclosing list could be a ShadowRoot that's not Element.
- for (Node* parent = listItemNode->parentNode(); parent; parent = parent->parentNode()) {
- if (isList(parent))
+ for (Node* parent = NodeRenderingTraversal::parent(listItemNode); parent; parent = NodeRenderingTraversal::parent(parent)) {
+ if (isList(*parent))
return parent;
if (!firstNode)
firstNode = parent;
@@ -127,12 +123,13 @@ static RenderListItem* nextListItem(const Node* listNode, const RenderListItem*
const Node* current = item ? item->node() : listNode;
ASSERT(current);
- current = ElementTraversal::nextIncludingPseudo(*current, listNode);
+ ASSERT(!current->document().childNeedsDistributionRecalc());
+ current = NodeRenderingTraversal::next(current, listNode);
while (current) {
- if (isList(current)) {
+ if (isList(*current)) {
// We've found a nested, independent list: nothing to do here.
- current = ElementTraversal::nextIncludingPseudoSkippingChildren(*current, listNode);
+ current = NodeRenderingTraversal::next(current, listNode);
continue;
}
@@ -141,7 +138,7 @@ static RenderListItem* nextListItem(const Node* listNode, const RenderListItem*
return toRenderListItem(renderer);
// FIXME: Can this be optimized to skip the children of the elements without a renderer?
- current = ElementTraversal::nextIncludingPseudo(*current, listNode);
+ current = NodeRenderingTraversal::next(current, listNode);
}
return 0;
@@ -152,7 +149,8 @@ static RenderListItem* previousListItem(const Node* listNode, const RenderListIt
{
Node* current = item->node();
ASSERT(current);
- for (current = ElementTraversal::previousIncludingPseudo(*current, listNode); current; current = ElementTraversal::previousIncludingPseudo(*current, listNode)) {
+ ASSERT(!current->document().childNeedsDistributionRecalc());
+ for (current = NodeRenderingTraversal::previous(current, listNode); current && current != listNode; current = NodeRenderingTraversal::previous(current, listNode)) {
RenderObject* renderer = current->renderer();
if (!renderer || (renderer && !renderer->isListItem()))
continue;
@@ -165,7 +163,7 @@ static RenderListItem* previousListItem(const Node* listNode, const RenderListIt
// be a list item itself. We need to examine it, so we do this to counteract
// the previousIncludingPseudo() that will be done by the loop.
if (otherList)
- current = ElementTraversal::nextIncludingPseudo(*otherList);
+ current = NodeRenderingTraversal::next(otherList, listNode);
}
return 0;
}
@@ -195,7 +193,7 @@ inline int RenderListItem::calcValue() const
return m_explicitValue;
Node* list = enclosingList(this);
- HTMLOListElement* oListElement = (list && list->hasTagName(olTag)) ? toHTMLOListElement(list) : 0;
+ HTMLOListElement* oListElement = isHTMLOListElement(list) ? toHTMLOListElement(list) : 0;
int valueStep = 1;
if (oListElement && oListElement->isReversed())
valueStep = -1;
@@ -243,7 +241,7 @@ static RenderObject* getParentOfFirstLineBox(RenderBlockFlow* curr, RenderObject
break;
if (curr->isListItem() && inQuirksMode && currChild->node() &&
- (currChild->node()->hasTagName(ulTag)|| currChild->node()->hasTagName(olTag)))
+ (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*currChild->node())))
break;
RenderObject* lineBox = getParentOfFirstLineBox(toRenderBlockFlow(currChild), marker);
@@ -259,65 +257,82 @@ void RenderListItem::updateValue()
if (!m_hasExplicitValue) {
m_isValueUpToDate = false;
if (m_marker)
- m_marker->setNeedsLayoutAndPrefWidthsRecalc();
+ m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
static RenderObject* firstNonMarkerChild(RenderObject* parent)
{
- RenderObject* result = parent->firstChild();
+ RenderObject* result = parent->slowFirstChild();
while (result && result->isListMarker())
result = result->nextSibling();
return result;
}
-void RenderListItem::updateMarkerLocation()
+void RenderListItem::updateMarkerLocationAndInvalidateWidth()
{
- // Sanity check the location of our marker.
- if (m_marker) {
- RenderObject* markerParent = m_marker->parent();
- RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
- if (!lineBoxParent) {
- // If the marker is currently contained inside an anonymous box,
- // then we are the only item in that anonymous box (since no line box
- // parent was found). It's ok to just leave the marker where it is
- // in this case.
- if (markerParent && markerParent->isAnonymousBlock())
- lineBoxParent = markerParent;
- else
- lineBoxParent = this;
- }
+ ASSERT(m_marker);
+
+ // FIXME: We should not modify the structure of the render tree
+ // during layout. crbug.com/370461
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
+ // Removing and adding the marker can trigger repainting in
+ // containers other than ourselves, so we need to disable LayoutState.
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+ if (updateMarkerLocation()) {
+ // If the marker is inside we need to redo the preferred width calculations
+ // as the size of the item now includes the size of the list marker.
+ if (m_marker->isInside())
+ containingBlock()->updateLogicalWidth();
+ }
+}
- if (markerParent != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) {
- // Removing and adding the marker can trigger repainting in
- // containers other than ourselves, so we need to disable LayoutState.
- LayoutStateDisabler layoutStateDisabler(view());
- updateFirstLetter();
- m_marker->remove();
- if (markerParent)
- markerParent->dirtyLinesFromChangedChild(m_marker);
- if (!lineBoxParent)
- lineBoxParent = this;
- lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
- m_marker->updateMarginsAndContent();
- // If markerParent is an anonymous block that has lost all its children, destroy it.
- if (markerParent && markerParent->isAnonymousBlock() && !markerParent->firstChild() && !toRenderBlock(markerParent)->continuation())
- markerParent->destroy();
-
- // If the marker is inside we need to redo the preferred width calculations
- // as the size of the item now includes the size of the list marker.
- if (m_marker->isInside())
- containingBlock()->updateLogicalWidth();
- }
+bool RenderListItem::updateMarkerLocation()
+{
+ ASSERT(m_marker);
+ RenderObject* markerParent = m_marker->parent();
+ RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
+ if (!lineBoxParent) {
+ // If the marker is currently contained inside an anonymous box, then we
+ // are the only item in that anonymous box (since no line box parent was
+ // found). It's ok to just leave the marker where it is in this case.
+ if (markerParent && markerParent->isAnonymousBlock())
+ lineBoxParent = markerParent;
+ else
+ lineBoxParent = this;
+ }
+
+ if (markerParent != lineBoxParent) {
+ updateFirstLetter();
+ m_marker->remove();
+ // FIXME(crbug.com/391009): Investigate whether this call is needed.
+ if (markerParent)
+ markerParent->dirtyLinesFromChangedChild(m_marker);
+ lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
+ m_marker->updateMarginsAndContent();
+ // If markerParent is an anonymous block with no children, destroy it.
+ if (markerParent && markerParent->isAnonymousBlock() && !toRenderBlock(markerParent)->firstChild() && !toRenderBlock(markerParent)->continuation())
+ markerParent->destroy();
+ return true;
}
+
+ return false;
}
void RenderListItem::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
- updateMarkerLocation();
+ if (m_marker) {
+ // The marker must be autosized before calling
+ // updateMarkerLocationAndInvalidateWidth. It cannot be done in the
+ // parent's beginLayout because it is not yet in the render tree.
+ if (FastTextAutosizer* textAutosizer = document().fastTextAutosizer())
+ textAutosizer->inflateListItem(this, m_marker);
+
+ updateMarkerLocationAndInvalidateWidth();
+ }
+
RenderBlockFlow::layout();
}
@@ -340,18 +355,17 @@ void RenderListItem::positionListMarker()
bool adjustOverflow = false;
LayoutUnit markerLogicalLeft;
- RootInlineBox* root = m_marker->inlineBoxWrapper()->root();
+ RootInlineBox& root = m_marker->inlineBoxWrapper()->root();
bool hitSelfPaintingLayer = false;
- RootInlineBox* rootBox = m_marker->inlineBoxWrapper()->root();
- LayoutUnit lineTop = rootBox->lineTop();
- LayoutUnit lineBottom = rootBox->lineBottom();
+ LayoutUnit lineTop = root.lineTop();
+ LayoutUnit lineBottom = root.lineBottom();
// FIXME: Need to account for relative positioning in the layout overflow.
if (style()->isLeftToRightDirection()) {
LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, logicalLeftOffsetForLine(blockOffset, false), false);
markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - borderStart() + m_marker->marginStart();
- m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft);
+ m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogicalLeft - markerOldLogicalLeft).toFloat());
for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
@@ -374,7 +388,7 @@ void RenderListItem::positionListMarker()
} else {
LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false);
markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd();
- m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft);
+ m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogicalLeft - markerOldLogicalLeft).toFloat());
for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
@@ -437,33 +451,10 @@ const String& RenderListItem::markerText() const
return nullAtom.string();
}
-String RenderListItem::markerTextWithSuffix() const
-{
- if (!m_marker)
- return String();
-
- // Append the suffix for the marker in the right place depending
- // on the direction of the text (right-to-left or left-to-right).
-
- const String& markerText = m_marker->text();
- const String markerSuffix = m_marker->suffix();
- StringBuilder result;
-
- if (!m_marker->style()->isLeftToRightDirection())
- result.append(markerSuffix);
-
- result.append(markerText);
-
- if (m_marker->style()->isLeftToRightDirection())
- result.append(markerSuffix);
-
- return result.toString();
-}
-
void RenderListItem::explicitValueChanged()
{
if (m_marker)
- m_marker->setNeedsLayoutAndPrefWidthsRecalc();
+ m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
Node* listNode = enclosingList(this);
for (RenderListItem* item = this; item; item = nextListItem(listNode, item))
item->updateValue();
@@ -492,6 +483,13 @@ void RenderListItem::clearExplicitValue()
explicitValueChanged();
}
+void RenderListItem::setNotInList(bool notInList)
+{
+ m_notInList = notInList;
+ if (m_marker)
+ updateMarkerLocation();
+}
+
static RenderListItem* previousOrNextItem(bool isListReversed, Node* list, RenderListItem* item)
{
return isListReversed ? previousListItem(list, item) : nextListItem(list, item);
@@ -499,18 +497,28 @@ static RenderListItem* previousOrNextItem(bool isListReversed, Node* list, Rende
void RenderListItem::updateListMarkerNumbers()
{
+ // If distribution recalc is needed, updateListMarkerNumber will be re-invoked
+ // after distribution is calculated.
+ if (node()->document().childNeedsDistributionRecalc())
+ return;
+
Node* listNode = enclosingList(this);
- // The list node can be the shadow root which has no renderer.
ASSERT(listNode);
- if (!listNode)
- return;
bool isListReversed = false;
- HTMLOListElement* oListElement = (listNode && listNode->hasTagName(olTag)) ? toHTMLOListElement(listNode) : 0;
+ HTMLOListElement* oListElement = isHTMLOListElement(listNode) ? toHTMLOListElement(listNode) : 0;
if (oListElement) {
oListElement->itemCountChanged();
isListReversed = oListElement->isReversed();
}
+
+ // FIXME: The n^2 protection below doesn't help if the elements were inserted after the
+ // the list had already been displayed.
+
+ // Avoid an O(n^2) walk over the children below when they're all known to be attaching.
+ if (listNode->needsAttach())
+ return;
+
for (RenderListItem* item = previousOrNextItem(isListReversed, listNode, this); item; item = previousOrNextItem(isListReversed, listNode, item)) {
if (!item->m_isValueUpToDate) {
// If an item has been marked for update before, we can safely
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.h b/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.h
index 76f6087ea4b..ca46d46bf42 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderListItem.h
@@ -42,40 +42,41 @@ public:
void setExplicitValue(int value);
void clearExplicitValue();
- void setNotInList(bool notInList) { m_notInList = notInList; }
+ void setNotInList(bool);
bool notInList() const { return m_notInList; }
const String& markerText() const;
- String markerTextWithSuffix() const;
void updateListMarkerNumbers();
- void updateMarkerLocation();
static void updateItemValuesForOrderedList(const HTMLOListElement*);
static unsigned itemCountForOrderedList(const HTMLOListElement*);
+ bool isEmpty() const;
+
private:
- virtual const char* renderName() const { return "RenderListItem"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderListItem"; }
- virtual bool isListItem() const { return true; }
+ virtual bool isListItem() const OVERRIDE { return true; }
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
virtual void insertedIntoTree() OVERRIDE;
virtual void willBeRemovedFromTree() OVERRIDE;
- virtual bool isEmpty() const;
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ // Returns true if we re-attached and updated the location of the marker.
+ bool updateMarkerLocation();
+ void updateMarkerLocationAndInvalidateWidth();
void positionListMarker();
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
- virtual void addOverflowFromChildren();
+ virtual void addOverflowFromChildren() OVERRIDE;
inline int calcValue() const;
void updateValueNow() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.cpp
index f05497493e5..492c3620d2f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.cpp
@@ -28,7 +28,6 @@
#include "core/dom/Document.h"
#include "core/fetch/ImageResource.h"
#include "core/rendering/GraphicsContextAnnotator.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderView.h"
@@ -1078,10 +1077,10 @@ RenderListMarker* RenderListMarker::createAnonymous(RenderListItem* item)
return renderer;
}
-void RenderListMarker::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderListMarker::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
- if (style() && (newStyle->listStylePosition() != style()->listStylePosition() || newStyle->listStyleType() != style()->listStyleType()))
- setNeedsLayoutAndPrefWidthsRecalc();
+ if (style() && (newStyle.listStylePosition() != style()->listStylePosition() || newStyle.listStyleType() != style()->listStyleType()))
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
RenderBox::styleWillChange(diff, newStyle);
}
@@ -1116,11 +1115,11 @@ LayoutRect RenderListMarker::localSelectionRect()
InlineBox* box = inlineBoxWrapper();
if (!box)
return LayoutRect(LayoutPoint(), size());
- RootInlineBox* root = m_inlineBoxWrapper->root();
- LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
- if (root->block()->style()->isHorizontalWritingMode())
- return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
- return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
+ RootInlineBox& root = inlineBoxWrapper()->root();
+ LayoutUnit newLogicalTop = root.block().style()->isFlippedBlocksWritingMode() ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() : root.selectionTop() - inlineBoxWrapper()->logicalTop();
+ if (root.block().style()->isHorizontalWritingMode())
+ return LayoutRect(0, newLogicalTop, width(), root.selectionHeight());
+ return LayoutRect(newLogicalTop, 0, root.selectionHeight(), height());
}
void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -1136,7 +1135,6 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
LayoutPoint boxOrigin(paintOffset + location());
LayoutRect overflowRect(visualOverflowRect());
overflowRect.moveBy(boxOrigin);
- overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
return;
@@ -1301,21 +1299,19 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
}
const UChar suffix = listMarkerSuffix(type, m_listItem->value());
+ UChar suffixStr[2] = {
+ style()->isLeftToRightDirection() ? suffix : ' ',
+ style()->isLeftToRightDirection() ? ' ' : suffix
+ };
+ TextRun suffixRun = RenderBlockFlow::constructTextRun(this, font, suffixStr, 2, style(), style()->direction());
+ TextRunPaintInfo suffixRunInfo(suffixRun);
+ suffixRunInfo.bounds = marker;
+
if (style()->isLeftToRightDirection()) {
context->drawText(font, textRunPaintInfo, textOrigin);
-
- UChar suffixSpace[2] = { suffix, ' ' };
- TextRun suffixRun = RenderBlockFlow::constructTextRun(this, font, suffixSpace, 2, style());
- TextRunPaintInfo suffixRunInfo(suffixRun);
- suffixRunInfo.bounds = marker;
context->drawText(font, suffixRunInfo, textOrigin + IntSize(font.width(textRun), 0));
} else {
- UChar spaceSuffix[2] = { ' ', suffix };
- TextRun suffixRun = RenderBlockFlow::constructTextRun(this, font, spaceSuffix, 2, style());
- TextRunPaintInfo suffixRunInfo(suffixRun);
- suffixRunInfo.bounds = marker;
context->drawText(font, suffixRunInfo, textOrigin);
-
context->drawText(font, textRunPaintInfo, textOrigin + IntSize(font.width(suffixRun), 0));
}
}
@@ -1325,7 +1321,6 @@ void RenderListMarker::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
if (isImage()) {
updateMarginsAndContent();
setWidth(m_image->imageSize(this, style()->effectiveZoom()).width());
@@ -1355,9 +1350,9 @@ void RenderListMarker::imageChanged(WrappedImagePtr o, const IntRect*)
return;
if (width() != m_image->imageSize(this, style()->effectiveZoom()).width() || height() != m_image->imageSize(this, style()->effectiveZoom()).height() || m_image->errorOccurred())
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
else
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderListMarker::updateMarginsAndContent()
@@ -1379,7 +1374,9 @@ void RenderListMarker::updateContent()
// 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.
int bulletWidth = style()->fontMetrics().ascent() / 2;
- m_image->setContainerSizeForRenderer(this, IntSize(bulletWidth, bulletWidth), style()->effectiveZoom());
+ IntSize defaultBulletSize(bulletWidth, bulletWidth);
+ IntSize imageSize = calculateImageIntrinsicDimensions(m_image.get(), defaultBulletSize, DoNotScaleByEffectiveZoom);
+ m_image->setContainerSizeForRenderer(this, imageSize, style()->effectiveZoom());
return;
}
@@ -1583,7 +1580,7 @@ void RenderListMarker::computePreferredLogicalWidths()
else {
LayoutUnit itemWidth = font.width(m_text);
UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' };
- LayoutUnit suffixSpaceWidth = font.width(RenderBlockFlow::constructTextRun(this, font, suffixSpace, 2, style()));
+ LayoutUnit suffixSpaceWidth = font.width(RenderBlockFlow::constructTextRun(this, font, suffixSpace, 2, style(), style()->direction()));
logicalWidth = itemWidth + suffixSpaceWidth;
}
break;
@@ -1809,7 +1806,7 @@ IntRect RenderListMarker::getRelativeMarkerRect()
const Font& font = style()->font();
int itemWidth = font.width(m_text);
UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' };
- int suffixSpaceWidth = font.width(RenderBlockFlow::constructTextRun(this, font, suffixSpace, 2, style()));
+ int suffixSpaceWidth = font.width(RenderBlockFlow::constructTextRun(this, font, suffixSpace, 2, style(), style()->direction()));
relativeRect = IntRect(0, 0, itemWidth + suffixSpaceWidth, font.fontMetrics().height());
}
@@ -1826,25 +1823,24 @@ void RenderListMarker::setSelectionState(SelectionState state)
// The selection state for our containing block hierarchy is updated by the base class call.
RenderBox::setSelectionState(state);
- if (m_inlineBoxWrapper && canUpdateSelectionOnRootLineBoxes())
- if (RootInlineBox* root = m_inlineBoxWrapper->root())
- root->setHasSelectedChildren(state != SelectionNone);
+ if (inlineBoxWrapper() && canUpdateSelectionOnRootLineBoxes())
+ inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone);
}
-LayoutRect RenderListMarker::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
+LayoutRect RenderListMarker::selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool clipToVisibleContent)
{
ASSERT(!needsLayout());
if (selectionState() == SelectionNone || !inlineBoxWrapper())
return LayoutRect();
- RootInlineBox* root = inlineBoxWrapper()->root();
- LayoutRect rect(0, root->selectionTop() - y(), width(), root->selectionHeight());
+ RootInlineBox& root = inlineBoxWrapper()->root();
+ LayoutRect rect(0, root.selectionTop() - y(), width(), root.selectionHeight());
if (clipToVisibleContent)
- computeRectForRepaint(repaintContainer, rect);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect);
else
- rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
+ rect = localToContainerQuad(FloatRect(rect), paintInvalidationContainer).enclosingBoundingBox();
return rect;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.h b/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.h
index d0002ffb973..278626a3c5b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderListMarker.h
@@ -49,34 +49,34 @@ public:
private:
RenderListMarker(RenderListItem*);
- virtual const char* renderName() const { return "RenderListMarker"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderListMarker"; }
virtual void computePreferredLogicalWidths() OVERRIDE;
- virtual bool isListMarker() const { return true; }
+ virtual bool isListMarker() const OVERRIDE { return true; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
- virtual InlineBox* createInlineBox();
+ virtual InlineBox* createInlineBox() OVERRIDE;
- virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
- virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+ virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
+ virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
- bool isImage() const;
+ virtual bool isImage() const OVERRIDE;
bool isText() const { return !isImage(); }
- virtual void setSelectionState(SelectionState);
- virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) OVERRIDE;
- virtual bool canBeSelectionLeaf() const { return true; }
+ virtual void setSelectionState(SelectionState) OVERRIDE;
+ virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool clipToVisibleContent = true) OVERRIDE;
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return true; }
void updateMargins();
void updateContent();
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
IntRect getRelativeMarkerRect();
LayoutRect localSelectionRect();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.cpp
index a40fed1583d..4b1e9a20c00 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.cpp
@@ -46,12 +46,13 @@
#include "core/rendering/RenderMarquee.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/html/HTMLMarqueeElement.h"
#include "core/frame/FrameView.h"
#include "core/frame/UseCounter.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
+#include "platform/LengthFunctions.h"
using namespace std;
@@ -172,7 +173,7 @@ void RenderMarquee::start()
m_stopped = false;
}
- m_timer.startRepeating(speed() * 0.001);
+ m_timer.startRepeating(speed() * 0.001, FROM_HERE);
}
void RenderMarquee::suspend()
@@ -194,8 +195,11 @@ void RenderMarquee::updateMarqueePosition()
EMarqueeBehavior behavior = style()->marqueeBehavior();
m_start = computePosition(direction(), behavior == MALTERNATE);
m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
- if (!m_stopped)
+ if (!m_stopped) {
+ // Hits in compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html during layout.
+ DisableCompositingQueryAsserts disabler;
start();
+ }
}
}
@@ -215,7 +219,7 @@ const char* RenderMarquee::renderName() const
void RenderMarquee::styleDidChange(StyleDifference difference, const RenderStyle* oldStyle)
{
- RenderBlock::styleDidChange(difference, oldStyle);
+ RenderBlockFlow::styleDidChange(difference, oldStyle);
RenderStyle* s = style();
@@ -248,20 +252,20 @@ void RenderMarquee::styleDidChange(StyleDifference difference, const RenderStyle
if (speed() != marqueeSpeed()) {
m_speed = marqueeSpeed();
if (m_timer.isActive())
- m_timer.startRepeating(speed() * 0.001);
+ m_timer.startRepeating(speed() * 0.001, FROM_HERE);
}
// Check the loop count to see if we should now stop.
bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
if (activate && !m_timer.isActive())
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
else if (!activate && m_timer.isActive())
m_timer.stop();
}
-void RenderMarquee::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
+void RenderMarquee::layoutBlock(bool relayoutChildren)
{
- RenderBlockFlow::layoutBlock(relayoutChildren, pageLogicalHeight);
+ RenderBlockFlow::layoutBlock(relayoutChildren);
updateMarqueePosition();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.h
index f69801dd44f..a089b234697 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMarquee.h
@@ -52,8 +52,6 @@
namespace WebCore {
-class RenderLayer;
-
// This class handles the auto-scrolling for <marquee>
class RenderMarquee FINAL : public RenderBlockFlow {
public:
@@ -83,15 +81,13 @@ public:
void timerFired();
private:
- virtual const char* renderName() const OVERRIDE FINAL;
-
- virtual bool isMarquee() const OVERRIDE FINAL { return true; }
+ virtual const char* renderName() const OVERRIDE;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+ virtual bool isMarquee() const OVERRIDE { return true; }
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE FINAL;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void layoutBlock(bool relayoutChildren) OVERRIDE;
int m_currentLoop;
int m_totalLoops;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.cpp
index aacc6ae38a9..0062b292055 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.cpp
@@ -28,8 +28,6 @@
#include "core/rendering/RenderMedia.h"
#include "core/html/HTMLMediaElement.h"
-#include "core/rendering/LayoutRectRecorder.h"
-#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderView.h"
namespace WebCore {
@@ -51,7 +49,6 @@ HTMLMediaElement* RenderMedia::mediaElement() const
void RenderMedia::layout()
{
- LayoutRectRecorder recorder(*this);
LayoutSize oldSize = contentBoxRect().size();
RenderImage::layout();
@@ -61,30 +58,17 @@ void RenderMedia::layout()
return;
bool controlsNeedLayout = controlsRenderer->needsLayout();
- // If the region chain has changed we also need to relayout the controls to update the region box info.
- // FIXME: We can do better once we compute region box info for RenderReplaced, not only for RenderBlock.
- const RenderFlowThread* flowThread = flowThreadContainingBlock();
- if (flowThread && !controlsNeedLayout) {
- if (flowThread->pageLogicalSizeChanged())
- controlsNeedLayout = true;
- }
-
LayoutSize newSize = contentBoxRect().size();
if (newSize == oldSize && !controlsNeedLayout)
return;
- // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or
- // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
- // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+ LayoutState state(*this, locationOffset());
controlsRenderer->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
controlsRenderer->forceLayout();
clearNeedsLayout();
-
- statePusher.pop();
}
void RenderMedia::paintReplaced(PaintInfo&, const LayoutPoint&)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.h
index ada064b59c0..c970b2909db 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMedia.h
@@ -40,27 +40,33 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderMedia, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
HTMLMediaElement* mediaElement() const;
protected:
- virtual void layout();
+ virtual void layout() OVERRIDE;
private:
virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
+ virtual LayerType layerTypeRequired() const OVERRIDE { return NormalLayer; }
+
// FIXME: RenderMedia::layout makes assumptions about what children are allowed
// so we can't support generated content.
virtual bool canHaveGeneratedChildren() const OVERRIDE FINAL { return false; }
virtual bool canHaveChildren() const OVERRIDE FINAL { return true; }
- virtual const char* renderName() const { return "RenderMedia"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderMedia"; }
virtual bool isMedia() const OVERRIDE FINAL { return true; }
virtual bool isImage() const OVERRIDE FINAL { return false; }
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
RenderObjectChildList m_children;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.cpp
index da2babc48d5..bdf6b1367c8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.cpp
@@ -29,7 +29,7 @@
#include "core/rendering/RenderMediaControlElements.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h"
#include "core/rendering/RenderView.h"
namespace WebCore {
@@ -41,17 +41,16 @@ RenderTextTrackContainerElement::RenderTextTrackContainerElement(Element* elemen
void RenderTextTrackContainerElement::layout()
{
- LayoutRectRecorder recorder(*this);
- RenderBlock::layout();
+ RenderBlockFlow::layout();
if (style()->display() == NONE)
return;
ASSERT(mediaControlElementType(node()) == MediaTextTrackDisplayContainer);
- LayoutStateDisabler layoutStateDisabler(view());
+ DeprecatedScheduleStyleRecalcDuringLayout marker(node()->document().lifecycle());
+
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
static_cast<MediaControlTextTrackContainerElement*>(node())->updateSizes();
}
-
} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.h
index 90a7d5ea1f2..b22aa736013 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControlElements.h
@@ -39,8 +39,7 @@ public:
RenderTextTrackContainerElement(Element*);
private:
- virtual void layout();
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void layout() OVERRIDE;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.cpp
index 13d1620367a..90b28aa442f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.cpp
@@ -106,7 +106,7 @@ static bool paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInf
if (!hasSource(mediaElement))
return paintMediaButton(paintInfo.context, rect, mediaPlayDisabled);
- return paintMediaButton(paintInfo.context, rect, mediaElement->canPlay() ? mediaPlay : mediaPause);
+ return paintMediaButton(paintInfo.context, rect, mediaControlElementType(object->node()) == MediaPlayButton ? mediaPlay : mediaPause);
}
static bool paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
@@ -115,7 +115,7 @@ static bool paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& p
if (!mediaElement)
return false;
- if (!hasSource(mediaElement) || !mediaElement->canPlay())
+ if (!hasSource(mediaElement) || !mediaElement->togglePlayStateWillPlay())
return false;
static Image* mediaOverlayPlay = platformResource("mediaplayerOverlayPlay");
@@ -133,9 +133,7 @@ static void paintRoundedSliderBackground(const IntRect& rect, const RenderStyle*
int borderRadius = rect.height() / 2;
IntSize radii(borderRadius, borderRadius);
Color sliderBackgroundColor = Color(11, 11, 11);
- context->save();
context->fillRoundedRect(rect, radii, radii, radii, radii, sliderBackgroundColor);
- context->restore();
}
static void paintSliderRangeHighlight(const IntRect& rect, const RenderStyle* style, GraphicsContext* context, int startPosition, int endPosition, Color startColor, Color endColor)
@@ -156,10 +154,8 @@ static void paintSliderRangeHighlight(const IntRect& rect, const RenderStyle* st
// Make sure the range width is bigger than border radius at the edges to retain rounded corners.
if (startOffset < borderRadius && rangeWidth < borderRadius)
rangeWidth = borderRadius;
- if (endOffset < borderRadius && rangeWidth < borderRadius) {
- startPosition -= borderRadius - rangeWidth;
+ if (endOffset < borderRadius && rangeWidth < borderRadius)
rangeWidth = borderRadius;
- }
// Set rectangle to highlight range.
IntRect highlightRect = rect;
@@ -365,16 +361,11 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R
return paintMediaFullscreenButton(object, paintInfo, rect);
case MediaOverlayPlayButton:
return paintMediaOverlayPlayButton(object, paintInfo, rect);
- case MediaVolumeSliderMuteButton:
- case MediaSeekBackButton:
- case MediaSeekForwardButton:
case MediaVolumeSliderContainer:
case MediaTimelineContainer:
case MediaCurrentTimeDisplay:
case MediaTimeRemainingDisplay:
case MediaControlsPanel:
- case MediaRewindButton:
- case MediaReturnToRealtimeButton:
case MediaStatusDisplay:
case MediaHideClosedCaptionsButton:
case MediaTextTrackDisplayContainer:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.h
index 8f40830228b..f007d6490ff 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMediaControls.h
@@ -34,7 +34,6 @@ namespace WebCore {
struct PaintInfo;
-class HTMLMediaElement;
class IntRect;
class RenderObject;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.cpp
index 57c8afc1cf8..f900e5885f0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.cpp
@@ -25,26 +25,27 @@
#include "config.h"
#include "core/rendering/RenderMenuList.h"
-#include <math.h>
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/accessibility/AXMenuList.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/NodeRenderStyle.h"
+#include "core/frame/FrameHost.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLOptGroupElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/page/Chrome.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
-#include "core/page/Page.h"
#include "core/rendering/RenderBR.h"
#include "core/rendering/RenderScrollbar.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
#include "platform/fonts/FontCache.h"
#include "platform/geometry/IntSize.h"
+#include "platform/text/PlatformLocale.h"
+#include <math.h>
using namespace std;
@@ -61,16 +62,21 @@ RenderMenuList::RenderMenuList(Element* element)
, m_lastActiveIndex(-1)
, m_popupIsVisible(false)
{
- ASSERT(element);
- ASSERT(element->isHTMLElement());
- ASSERT(element->hasTagName(HTMLNames::selectTag));
+ ASSERT(isHTMLSelectElement(element));
}
RenderMenuList::~RenderMenuList()
{
if (m_popup)
m_popup->disconnectClient();
- m_popup = 0;
+ m_popup = nullptr;
+}
+
+// FIXME: Instead of this hack we should add a ShadowRoot to <select> with no insertion point
+// to prevent children from rendering.
+bool RenderMenuList::isChildAllowed(RenderObject* object, RenderStyle*) const
+{
+ return object->isAnonymous() && !object->isRenderFullScreen();
}
void RenderMenuList::createInnerBlock()
@@ -93,16 +99,13 @@ void RenderMenuList::adjustInnerStyle()
RenderStyle* innerStyle = m_innerBlock->style();
innerStyle->setFlexGrow(1);
innerStyle->setFlexShrink(1);
- // min-width: 0; is needed for correct shrinking.
- // FIXME: Remove this line when https://bugs.webkit.org/show_bug.cgi?id=111790 is fixed.
- innerStyle->setMinWidth(Length(0, Fixed));
// Use margin:auto instead of align-items:center to get safe centering, i.e.
// when the content overflows, treat it the same as align-items: flex-start.
// But we only do that for the cases where html.css would otherwise use center.
- if (style()->alignItems() == AlignCenter) {
+ if (style()->alignItems() == ItemPositionCenter) {
innerStyle->setMarginTop(Length());
innerStyle->setMarginBottom(Length());
- innerStyle->setAlignSelf(AlignFlexStart);
+ innerStyle->setAlignSelf(ItemPositionFlexStart);
}
innerStyle->setPaddingLeft(Length(RenderTheme::theme().popupInternalPaddingLeft(style()), Fixed));
@@ -112,7 +115,7 @@ void RenderMenuList::adjustInnerStyle()
if (m_optionStyle) {
if ((m_optionStyle->direction() != innerStyle->direction() || m_optionStyle->unicodeBidi() != innerStyle->unicodeBidi()))
- m_innerBlock->setNeedsLayoutAndPrefWidthsRecalc();
+ m_innerBlock->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
innerStyle->setTextAlign(style()->isLeftToRightDirection() ? LEFT : RIGHT);
innerStyle->setDirection(m_optionStyle->direction());
innerStyle->setUnicodeBidi(m_optionStyle->unicodeBidi());
@@ -160,13 +163,13 @@ void RenderMenuList::styleDidChange(StyleDifference diff, const RenderStyle* old
void RenderMenuList::updateOptionsWidth()
{
float maxOptionWidth = 0;
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
int size = listItems.size();
FontCachePurgePreventer fontCachePurgePreventer;
for (int i = 0; i < size; ++i) {
HTMLElement* element = listItems[i];
- if (!element->hasTagName(optionTag))
+ if (!isHTMLOptionElement(*element))
continue;
String text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
@@ -175,7 +178,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 += minimumValueForLength(optionStyle->textIndent(), 0, view());
+ optionWidth += minimumValueForLength(optionStyle->textIndent(), 0);
if (!text.isEmpty())
optionWidth += style()->font().width(text);
maxOptionWidth = max(maxOptionWidth, optionWidth);
@@ -189,7 +192,7 @@ void RenderMenuList::updateOptionsWidth()
m_optionsWidth = width;
if (parent())
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderMenuList::updateFromElement()
@@ -199,29 +202,65 @@ void RenderMenuList::updateFromElement()
m_optionsChanged = false;
}
- if (m_popupIsVisible)
+ if (m_popupIsVisible) {
m_popup->updateFromElement();
- else
- setTextFromOption(selectElement()->selectedIndex());
+ } else {
+ if (selectElement()->suggestedIndex() >= 0)
+ setTextFromOption(selectElement()->suggestedIndex());
+ else
+ setTextFromOption(selectElement()->selectedIndex());
+ }
}
void RenderMenuList::setTextFromOption(int optionIndex)
{
HTMLSelectElement* select = selectElement();
- const Vector<HTMLElement*>& listItems = select->listItems();
- int size = listItems.size();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = select->listItems();
+ const int size = listItems.size();
- int i = select->optionToListIndex(optionIndex);
String text = emptyString();
- if (i >= 0 && i < size) {
- Element* element = listItems[i];
- if (element->hasTagName(optionTag)) {
- text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
- m_optionStyle = element->renderStyle();
+ m_optionStyle.clear();
+
+ if (multiple()) {
+ unsigned selectedCount = 0;
+ int firstSelectedIndex = -1;
+ for (int i = 0; i < size; ++i) {
+ Element* element = listItems[i];
+ if (!isHTMLOptionElement(*element))
+ continue;
+
+ if (toHTMLOptionElement(element)->selected()) {
+ if (++selectedCount == 1)
+ firstSelectedIndex = i;
+ }
+ }
+
+ if (selectedCount == 1) {
+ ASSERT(0 <= firstSelectedIndex);
+ ASSERT(firstSelectedIndex < size);
+ HTMLOptionElement* selectedOptionElement = toHTMLOptionElement(listItems[firstSelectedIndex]);
+ ASSERT(selectedOptionElement->selected());
+ text = selectedOptionElement->textIndentedToRespectGroupLabel();
+ m_optionStyle = selectedOptionElement->renderStyle();
+ } else {
+ Locale& locale = select->locale();
+ String localizedNumberString = locale.convertToLocalizedNumber(String::number(selectedCount));
+ text = locale.queryString(blink::WebLocalizedString::SelectMenuListText, localizedNumberString);
+ ASSERT(!m_optionStyle);
+ }
+ } else {
+ const int i = select->optionToListIndex(optionIndex);
+ if (i >= 0 && i < size) {
+ Element* element = listItems[i];
+ if (isHTMLOptionElement(*element)) {
+ text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+ m_optionStyle = element->renderStyle();
+ }
}
}
setText(text.stripWhiteSpace());
+
didUpdateActiveOption(optionIndex);
}
@@ -229,6 +268,9 @@ void RenderMenuList::setText(const String& s)
{
if (s.isEmpty()) {
if (!m_buttonText || !m_buttonText->isBR()) {
+ // FIXME: We should not modify the structure of the render tree
+ // during layout. crbug.com/370462
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
if (m_buttonText)
m_buttonText->destroy();
m_buttonText = new RenderBR(&document());
@@ -239,6 +281,9 @@ void RenderMenuList::setText(const String& s)
if (m_buttonText && !m_buttonText->isBR())
m_buttonText->setText(s.impl(), true);
else {
+ // FIXME: We should not modify the structure of the render tree
+ // during layout. crbug.com/370462
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
if (m_buttonText)
m_buttonText->destroy();
m_buttonText = new RenderText(&document(), s.impl());
@@ -287,20 +332,21 @@ void RenderMenuList::computePreferredLogicalWidths()
{
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
+ RenderStyle* styleToUse = style();
- if (style()->width().isFixed() && style()->width().value() > 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+ if (styleToUse->width().isFixed() && styleToUse->width().value() > 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->width().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+ if (styleToUse->minWidth().isFixed() && styleToUse->minWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
}
- if (style()->maxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+ if (styleToUse->maxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
}
LayoutUnit toAdd = borderAndPaddingWidth();
@@ -315,7 +361,7 @@ void RenderMenuList::showPopup()
if (m_popupIsVisible)
return;
- if (document().page()->chrome().hasOpenedPopup())
+ if (document().frameHost()->chrome().hasOpenedPopup())
return;
// Create m_innerBlock here so it ends up as the first child.
@@ -323,7 +369,7 @@ void RenderMenuList::showPopup()
// inside the showPopup call and it would fail.
createInnerBlock();
if (!m_popup)
- m_popup = document().page()->chrome().createPopupMenu(*document().frame(), this);
+ m_popup = document().frameHost()->chrome().createPopupMenu(*document().frame(), this);
m_popupIsVisible = true;
FloatQuad quad(localToAbsoluteQuad(FloatQuad(borderBoundingBox())));
@@ -385,35 +431,25 @@ void RenderMenuList::didUpdateActiveOption(int optionIndex)
String RenderMenuList::itemText(unsigned listIndex) const
{
HTMLSelectElement* select = selectElement();
- const Vector<HTMLElement*>& listItems = select->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = select->listItems();
if (listIndex >= listItems.size())
return String();
String itemString;
Element* element = listItems[listIndex];
- if (isHTMLOptGroupElement(element))
- itemString = toHTMLOptGroupElement(element)->groupLabelText();
- else if (element->hasTagName(optionTag))
- itemString = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+ if (isHTMLOptGroupElement(*element))
+ itemString = toHTMLOptGroupElement(*element).groupLabelText();
+ else if (isHTMLOptionElement(*element))
+ itemString = toHTMLOptionElement(*element).textIndentedToRespectGroupLabel();
applyTextTransform(style(), itemString, ' ');
return itemString;
}
-String RenderMenuList::itemLabel(unsigned) const
-{
- return String();
-}
-
-String RenderMenuList::itemIcon(unsigned) const
-{
- return String();
-}
-
String RenderMenuList::itemAccessibilityText(unsigned listIndex) const
{
// Allow the accessible name be changed if necessary.
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
if (listIndex >= listItems.size())
return String();
return listItems[listIndex]->fastGetAttribute(aria_labelAttr);
@@ -421,7 +457,7 @@ String RenderMenuList::itemAccessibilityText(unsigned listIndex) const
String RenderMenuList::itemToolTip(unsigned listIndex) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
if (listIndex >= listItems.size())
return String();
return listItems[listIndex]->title();
@@ -429,16 +465,16 @@ String RenderMenuList::itemToolTip(unsigned listIndex) const
bool RenderMenuList::itemIsEnabled(unsigned listIndex) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
if (listIndex >= listItems.size())
return false;
HTMLElement* element = listItems[listIndex];
- if (!element->hasTagName(optionTag))
+ if (!isHTMLOptionElement(*element))
return false;
bool groupEnabled = true;
if (Element* parentElement = element->parentElement()) {
- if (isHTMLOptGroupElement(parentElement))
+ if (isHTMLOptGroupElement(*parentElement))
groupEnabled = !parentElement->isDisabledFormControl();
}
if (!groupEnabled)
@@ -449,7 +485,7 @@ bool RenderMenuList::itemIsEnabled(unsigned listIndex) const
PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
if (listIndex >= listItems.size()) {
// If we are making an out of bounds access, then we want to use the style
// of a different option element (index 0). However, if there isn't an option element
@@ -474,7 +510,7 @@ PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const
void RenderMenuList::getItemBackgroundColor(unsigned listIndex, Color& itemBackgroundColor, bool& itemHasCustomBackgroundColor) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
if (listIndex >= listItems.size()) {
itemBackgroundColor = resolveColor(CSSPropertyBackgroundColor);
itemHasCustomBackgroundColor = false;
@@ -485,7 +521,7 @@ void RenderMenuList::getItemBackgroundColor(unsigned listIndex, Color& itemBackg
Color backgroundColor;
if (element->renderStyle())
backgroundColor = resolveColor(element->renderStyle(), CSSPropertyBackgroundColor);
- itemHasCustomBackgroundColor = backgroundColor.isValid() && backgroundColor.alpha();
+ itemHasCustomBackgroundColor = backgroundColor.alpha();
// If the item has an opaque background color, return that.
if (!backgroundColor.hasAlpha()) {
itemBackgroundColor = backgroundColor;
@@ -511,32 +547,6 @@ PopupMenuStyle RenderMenuList::menuStyle() const
s->display() == NONE, s->textIndent(), style()->direction(), isOverride(style()->unicodeBidi()));
}
-HostWindow* RenderMenuList::hostWindow() const
-{
- return document().view()->hostWindow();
-}
-
-PassRefPtr<Scrollbar> RenderMenuList::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
-{
- RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
- if (hasCustomScrollbarStyle)
- widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this->node());
- else
- widget = Scrollbar::create(scrollableArea, orientation, controlSize);
- return widget.release();
-}
-
-int RenderMenuList::clientInsetLeft() const
-{
- return 0;
-}
-
-int RenderMenuList::clientInsetRight() const
-{
- return 0;
-}
-
LayoutUnit RenderMenuList::clientPaddingLeft() const
{
return paddingLeft() + m_innerBlock->paddingLeft();
@@ -576,23 +586,23 @@ void RenderMenuList::popupDidHide()
bool RenderMenuList::itemIsSeparator(unsigned listIndex) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
- return listIndex < listItems.size() && listItems[listIndex]->hasTagName(hrTag);
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
+ return listIndex < listItems.size() && isHTMLHRElement(*listItems[listIndex]);
}
bool RenderMenuList::itemIsLabel(unsigned listIndex) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
- return listIndex < listItems.size() && isHTMLOptGroupElement(listItems[listIndex]);
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
+ return listIndex < listItems.size() && isHTMLOptGroupElement(*listItems[listIndex]);
}
bool RenderMenuList::itemIsSelected(unsigned listIndex) const
{
- const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement()->listItems();
if (listIndex >= listItems.size())
return false;
HTMLElement* element = listItems[listIndex];
- return element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected();
+ return isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selected();
}
void RenderMenuList::setTextFromItem(unsigned listIndex)
@@ -600,9 +610,4 @@ void RenderMenuList::setTextFromItem(unsigned listIndex)
setTextFromOption(selectElement()->listToOptionIndex(listIndex));
}
-FontSelector* RenderMenuList::fontSelector() const
-{
- return document().styleEngine()->fontSelector();
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.h
index 54561e0d673..b7dc98c965b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMenuList.h
@@ -54,39 +54,36 @@ public:
private:
HTMLSelectElement* selectElement() const;
- virtual bool isMenuList() const { return true; }
+ virtual bool isMenuList() const OVERRIDE { return true; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject*);
- virtual bool createsAnonymousWrapper() const { return true; }
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject*) OVERRIDE;
+ virtual bool createsAnonymousWrapper() const OVERRIDE { return true; }
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
- virtual LayoutRect controlClipRect(const LayoutPoint&) const;
- virtual bool hasControlClip() const { return true; }
+ virtual LayoutRect controlClipRect(const LayoutPoint&) const OVERRIDE;
+ virtual bool hasControlClip() const OVERRIDE { return true; }
virtual bool canHaveGeneratedChildren() const OVERRIDE { return false; }
- virtual const char* renderName() const { return "RenderMenuList"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderMenuList"; }
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
// PopupMenuClient methods
virtual void valueChanged(unsigned listIndex, bool fireOnChange = true) OVERRIDE;
virtual void selectionChanged(unsigned, bool) OVERRIDE { }
virtual void selectionCleared() OVERRIDE { }
virtual String itemText(unsigned listIndex) const OVERRIDE;
- virtual String itemLabel(unsigned listIndex) const OVERRIDE;
- virtual String itemIcon(unsigned listIndex) const OVERRIDE;
virtual String itemToolTip(unsigned listIndex) const OVERRIDE;
virtual String itemAccessibilityText(unsigned listIndex) const OVERRIDE;
virtual bool itemIsEnabled(unsigned listIndex) const OVERRIDE;
virtual PopupMenuStyle itemStyle(unsigned listIndex) const OVERRIDE;
virtual PopupMenuStyle menuStyle() const OVERRIDE;
- virtual int clientInsetLeft() const OVERRIDE;
- virtual int clientInsetRight() const OVERRIDE;
virtual LayoutUnit clientPaddingLeft() const OVERRIDE;
virtual LayoutUnit clientPaddingRight() const OVERRIDE;
virtual int listSize() const OVERRIDE;
@@ -95,15 +92,11 @@ private:
virtual bool itemIsSeparator(unsigned listIndex) const OVERRIDE;
virtual bool itemIsLabel(unsigned listIndex) const OVERRIDE;
virtual bool itemIsSelected(unsigned listIndex) const OVERRIDE;
- virtual bool valueShouldChangeOnHotTrack() const OVERRIDE { return true; }
virtual void setTextFromItem(unsigned listIndex) OVERRIDE;
virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) OVERRIDE;
virtual bool multiple() const OVERRIDE;
- virtual FontSelector* fontSelector() const OVERRIDE;
- virtual HostWindow* hostWindow() const OVERRIDE;
- virtual PassRefPtr<Scrollbar> createScrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize) OVERRIDE;
- virtual bool hasLineIfEmpty() const { return true; }
+ virtual bool hasLineIfEmpty() const OVERRIDE { return true; }
// Flexbox defines baselines differently than regular blocks.
// For backwards compatibility, menulists need to do the regular block behavior.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.cpp
index a4982a9bb70..1a26f7ac286 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.cpp
@@ -44,7 +44,7 @@ HTMLMeterElement* RenderMeter::meterElement() const
{
ASSERT(node());
- if (isHTMLMeterElement(node()))
+ if (isHTMLMeterElement(*node()))
return toHTMLMeterElement(node());
ASSERT(node()->shadowHost());
@@ -79,7 +79,7 @@ double RenderMeter::valueRatio() const
void RenderMeter::updateFromElement()
{
- repaint();
+ paintInvalidationForWholeRenderer();
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.h
index d1f1e438aef..51ced2147e4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMeter.h
@@ -34,16 +34,14 @@ public:
virtual ~RenderMeter();
HTMLMeterElement* meterElement() const;
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
private:
virtual void updateLogicalWidth() OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
- virtual const char* renderName() const { return "RenderMeter"; }
- virtual bool isMeter() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderMeter"; }
+ virtual bool isMeter() const OVERRIDE { return true; }
double valueRatio() const;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.cpp
deleted file mode 100644
index 53c1fe86a66..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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 "core/rendering/RenderMultiColumnBlock.h"
-
-#include "core/rendering/RenderMultiColumnFlowThread.h"
-#include "core/rendering/RenderMultiColumnSet.h"
-#include "core/rendering/RenderView.h"
-
-using namespace std;
-
-namespace WebCore {
-
-RenderMultiColumnBlock::RenderMultiColumnBlock(Element* element)
- : RenderBlockFlow(element)
- , m_flowThread(0)
- , m_columnCount(1)
- , m_columnWidth(0)
- , m_columnHeightAvailable(0)
- , m_inBalancingPass(false)
-{
-}
-
-void RenderMultiColumnBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderBlock::styleDidChange(diff, oldStyle);
- for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox())
- child->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK));
-}
-
-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::updateLogicalWidthAndColumnWidth()
-{
- bool relayoutChildren = RenderBlock::updateLogicalWidthAndColumnWidth();
- LayoutUnit oldColumnWidth = m_columnWidth;
- computeColumnCountAndWidth();
- if (m_columnWidth != oldColumnWidth)
- relayoutChildren = true;
- return relayoutChildren;
-}
-
-void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& /*pageLogicalHeight*/, bool& /*pageLogicalHeightChanged*/, bool& /*hasSpecifiedPageLogicalHeight*/)
-{
- // We don't actually update any of the variables. We just subclassed to adjust our column height.
- updateLogicalHeight();
- m_columnHeightAvailable = max<LayoutUnit>(contentLogicalHeight(), 0);
- setLogicalHeight(0);
-}
-
-bool RenderMultiColumnBlock::relayoutForPagination(bool, LayoutUnit, LayoutStateMaintainer& statePusher)
-{
- if (m_inBalancingPass || !requiresBalancing())
- return false;
- m_inBalancingPass = true; // Prevent re-entering this method (and recursion into layout).
-
- bool needsRelayout;
- bool neededRelayout = false;
- bool firstPass = true;
- do {
- // Column heights may change here because of balancing. We may have to do multiple layout
- // passes, depending on how the contents is fitted to the changed column heights. In most
- // cases, laying out again twice or even just once will suffice. Sometimes we need more
- // passes than that, though, but the number of retries should not exceed the number of
- // columns, unless we have a bug.
- needsRelayout = false;
- for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
- if (childBox != m_flowThread && childBox->isRenderMultiColumnSet()) {
- RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox);
- if (multicolSet->calculateBalancedHeight(firstPass)) {
- multicolSet->setChildNeedsLayout(MarkOnlyThis);
- needsRelayout = true;
- }
- }
- }
-
- if (needsRelayout) {
- // Layout again. Column balancing resulted in a new height.
- neededRelayout = true;
- m_flowThread->setChildNeedsLayout(MarkOnlyThis);
- setChildNeedsLayout(MarkOnlyThis);
- if (firstPass)
- statePusher.pop();
- layoutBlock(false);
- }
- firstPass = false;
- } while (needsRelayout);
- m_inBalancingPass = false;
- return neededRelayout;
-}
-
-void RenderMultiColumnBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- if (!m_flowThread) {
- m_flowThread = RenderMultiColumnFlowThread::createAnonymous(&document());
- m_flowThread->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK));
- RenderBlock::addChild(m_flowThread);
- }
- m_flowThread->addChild(newChild, beforeChild);
-}
-
-RenderObject* RenderMultiColumnBlock::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope& layoutScope)
-{
- if (!m_flowThread)
- return 0;
-
- // Update the dimensions of our regions before we lay out the flow thread.
- // FIXME: Eventually this is going to get way more complicated, and we will be destroying regions
- // instead of trying to keep them around.
- bool shouldInvalidateRegions = false;
- for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
- if (childBox == m_flowThread)
- continue;
-
- if (relayoutChildren || childBox->needsLayout()) {
- if (!m_inBalancingPass && childBox->isRenderMultiColumnSet())
- toRenderMultiColumnSet(childBox)->prepareForLayout();
- shouldInvalidateRegions = true;
- }
- }
-
- if (shouldInvalidateRegions)
- m_flowThread->invalidateRegions();
-
- if (relayoutChildren)
- layoutScope.setChildNeedsLayout(m_flowThread);
-
- setLogicalTopForChild(m_flowThread, borderBefore() + paddingBefore());
- m_flowThread->layoutIfNeeded();
- determineLogicalLeftPositionForChild(m_flowThread);
-
- return m_flowThread;
-}
-
-const char* RenderMultiColumnBlock::renderName() const
-{
- if (isFloating())
- return "RenderMultiColumnBlock (floating)";
- if (isOutOfFlowPositioned())
- return "RenderMultiColumnBlock (positioned)";
- if (isAnonymousBlock())
- return "RenderMultiColumnBlock (anonymous)";
- // FIXME: Temporary hack while the new generated content system is being implemented.
- if (isPseudoElement())
- return "RenderMultiColumnBlock (generated)";
- if (isAnonymous())
- return "RenderMultiColumnBlock (generated)";
- if (isRelPositioned())
- return "RenderMultiColumnBlock (relative positioned)";
- return "RenderMultiColumnBlock";
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.h
deleted file mode 100644
index ac92d2f9ff9..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnBlock.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 "core/rendering/RenderBlockFlow.h"
-
-namespace WebCore {
-
-class RenderMultiColumnFlowThread;
-
-class RenderMultiColumnBlock FINAL : public RenderBlockFlow {
-public:
- RenderMultiColumnBlock(Element*);
-
- LayoutUnit columnHeightAvailable() const { return m_columnHeightAvailable; }
-
- LayoutUnit columnWidth() const { return m_columnWidth; }
- unsigned columnCount() const { return m_columnCount; }
-
- RenderMultiColumnFlowThread* flowThread() const { return m_flowThread; }
-
- bool requiresBalancing() const { return !m_columnHeightAvailable || style()->columnFill() == ColumnFillBalance; }
-
-private:
- virtual bool isRenderMultiColumnBlock() const { return true; }
-
- virtual const char* renderName() const;
-
- virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) OVERRIDE;
-
- virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
-
- virtual bool updateLogicalWidthAndColumnWidth() OVERRIDE;
- virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight) OVERRIDE;
- virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&) OVERRIDE;
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
-
- void computeColumnCountAndWidth();
-
- void ensureColumnSets();
-
- RenderMultiColumnFlowThread* m_flowThread;
- 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.
- LayoutUnit m_columnHeightAvailable; // Total height available to columns, or 0 if auto.
- bool m_inBalancingPass; // Set when relayouting for column balancing.
-};
-
-DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderMultiColumnBlock, isRenderMultiColumnBlock());
-
-} // namespace WebCore
-
-#endif // RenderMultiColumnBlock_h
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.cpp
index 1a2fc6f74b2..9b50901bcba 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.cpp
@@ -26,12 +26,15 @@
#include "config.h"
#include "core/rendering/RenderMultiColumnFlowThread.h"
-#include "core/rendering/RenderMultiColumnBlock.h"
#include "core/rendering/RenderMultiColumnSet.h"
namespace WebCore {
RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
+ : m_columnCount(1)
+ , m_columnHeightAvailable(0)
+ , m_inBalancingPass(false)
+ , m_needsColumnHeightsRecalculation(false)
{
setFlowThreadState(InsideInFlowThread);
}
@@ -40,72 +43,249 @@ RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread()
{
}
-RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Document* document)
+RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Document& document, RenderStyle* parentStyle)
{
RenderMultiColumnFlowThread* renderer = new RenderMultiColumnFlowThread();
- renderer->setDocumentForAnonymous(document);
+ renderer->setDocumentForAnonymous(&document);
+ renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
return renderer;
}
-const char* RenderMultiColumnFlowThread::renderName() const
+RenderMultiColumnSet* RenderMultiColumnFlowThread::firstMultiColumnSet() const
{
- return "RenderMultiColumnFlowThread";
+ for (RenderObject* sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
+ if (sibling->isRenderMultiColumnSet())
+ return toRenderMultiColumnSet(sibling);
+ }
+ return 0;
}
-void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const
{
- // We simply remain at our intrinsic height.
- computedValues.m_extent = logicalHeight;
- computedValues.m_position = logicalTop;
+ for (RenderObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; sibling = sibling->previousSibling()) {
+ if (sibling->isRenderMultiColumnSet())
+ return toRenderMultiColumnSet(sibling);
+ }
+ return 0;
}
-LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const
-{
- RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
- return parentBlock->columnWidth();
-}
-
-void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /*offset*/)
-{
- // This function ensures we have the correct column set information at all times.
- // For a simple multi-column layout in continuous media, only one column set child is required.
- // Once a column is nested inside an enclosing pagination context, the number of column sets
- // required becomes 2n-1, where n is the total number of nested pagination contexts. For example:
- //
- // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column set.
- // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, all the subsequent pages, then the last page).
- // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets.
- //
- // In addition, column spans will force a column set to "split" into before/after sets around the spanning element.
- //
- // Finally, we will need to deal with columns inside regions. If regions have variable widths, then there will need
- // to be unique column sets created inside any region whose width is different from its surrounding regions. This is
- // actually pretty similar to the spanning case, in that we break up the column sets whenever the width varies.
- //
- // FIXME: For now just make one column set. This matches the old multi-column code.
- // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the
- // new code as soon as possible.
- RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion());
- if (firstSet)
+void RenderMultiColumnFlowThread::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+ RenderBlockFlow::addChild(newChild, beforeChild);
+ if (firstMultiColumnSet())
return;
+ // For now we only create one column set. It's created as soon as the multicol container gets
+ // any content at all.
+ RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, multiColumnBlockFlow()->style());
+
+ // Need to skip RenderBlockFlow's implementation of addChild(), or we'd get redirected right
+ // back here.
+ multiColumnBlockFlow()->RenderBlock::addChild(newSet);
+
invalidateRegions();
+}
- RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
- firstSet = RenderMultiColumnSet::createAnonymous(this);
- firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock->style(), BLOCK));
- parentBlock->RenderBlock::addChild(firstSet);
+void RenderMultiColumnFlowThread::populate()
+{
+ RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
+ ASSERT(!nextSibling());
+ // Reparent children preceding the flow thread into the flow thread. It's multicol content
+ // now. At this point there's obviously nothing after the flow thread, but renderers (column
+ // sets and spanners) will be inserted there as we insert elements into the flow thread.
+ multicolContainer->moveChildrenTo(this, multicolContainer->firstChild(), this, true);
+}
+
+void RenderMultiColumnFlowThread::evacuateAndDestroy()
+{
+ RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
+
+ // Remove all sets.
+ while (RenderMultiColumnSet* columnSet = firstMultiColumnSet())
+ columnSet->destroy();
- // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're
- // typically in the middle of laying out the thread, attempting to paginate, and we need to do
- // some rudimentary "layout" of the set now, so that pagination will work.
- firstSet->prepareForLayout();
+ ASSERT(!previousSibling());
+ ASSERT(!nextSibling());
+ // Finally we can promote all flow thread's children. Before we move them to the flow thread's
+ // container, we need to unregister the flow thread, so that they aren't just re-added again to
+ // the flow thread that we're trying to empty.
+ multicolContainer->resetMultiColumnFlowThread();
+ moveAllChildrenTo(multicolContainer, true);
+
+ // FIXME: it's scary that neither destroy() nor the move*Children* methods take care of this,
+ // and instead leave you with dangling root line box pointers. But since this is how it is done
+ // in other parts of the code that deal with reparenting renderers, let's do the cleanup on our
+ // own here as well.
+ deleteLineBoxTree();
+
+ destroy();
+}
+
+LayoutSize RenderMultiColumnFlowThread::columnOffset(const LayoutPoint& point) const
+{
+ if (!hasValidRegionInfo())
+ return LayoutSize(0, 0);
+
+ LayoutPoint flowThreadPoint(point);
+ flipForWritingMode(flowThreadPoint);
+ LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : flowThreadPoint.x();
+ RenderRegion* renderRegion = regionAtBlockOffset(blockOffset);
+ if (!renderRegion)
+ return LayoutSize(0, 0);
+ return toRenderMultiColumnSet(renderRegion)->flowThreadTranslationAtOffset(blockOffset);
+}
+
+bool RenderMultiColumnFlowThread::needsNewWidth() const
+{
+ LayoutUnit newWidth;
+ unsigned dummyColumnCount; // We only care if used column-width changes.
+ calculateColumnCountAndWidth(newWidth, dummyColumnCount);
+ return newWidth != logicalWidth();
+}
+
+void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLayoutScope& layoutScope)
+{
+ if (relayoutChildren)
+ layoutScope.setChildNeedsLayout(this);
+
+ if (!needsLayout()) {
+ // Just before the multicol container (our parent RenderBlockFlow) finishes laying out, it
+ // will call recalculateColumnHeights() on us unconditionally, but we only want that method
+ // to do any work if we actually laid out the flow thread. Otherwise, the balancing
+ // machinery would kick in needlessly, and trigger additional layout passes. Furthermore, we
+ // actually depend on a proper flowthread layout pass in order to do balancing, since it's
+ // flowthread layout that sets up content runs.
+ m_needsColumnHeightsRecalculation = false;
+ return;
+ }
+
+ for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
+ if (!m_inBalancingPass) {
+ // This is the initial layout pass. We need to reset the column height, because contents
+ // typically have changed.
+ columnSet->resetColumnHeight();
+ }
+ }
+
+ invalidateRegions();
+ m_needsColumnHeightsRecalculation = requiresBalancing();
+ layout();
+}
+
+bool RenderMultiColumnFlowThread::recalculateColumnHeights()
+{
+ // All column sets that needed layout have now been laid out, so we can finally validate them.
validateRegions();
+
+ if (!m_needsColumnHeightsRecalculation)
+ return false;
+
+ // Column heights may change here because of balancing. We may have to do multiple layout
+ // passes, depending on how the contents is fitted to the changed column heights. In most
+ // cases, laying out again twice or even just once will suffice. Sometimes we need more
+ // passes than that, though, but the number of retries should not exceed the number of
+ // columns, unless we have a bug.
+ bool needsRelayout = false;
+ for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
+ needsRelayout |= multicolSet->recalculateColumnHeight(m_inBalancingPass ? RenderMultiColumnSet::StretchBySpaceShortage : RenderMultiColumnSet::GuessFromFlowThreadPortion);
+ if (needsRelayout) {
+ // Once a column set gets a new column height, that column set and all successive column
+ // sets need to be laid out over again, since their logical top will be affected by
+ // this, and therefore their column heights may change as well, at least if the multicol
+ // height is constrained.
+ multicolSet->setChildNeedsLayout(MarkOnlyThis);
+ }
+ }
+
+ if (needsRelayout)
+ setChildNeedsLayout(MarkOnlyThis);
+
+ m_inBalancingPass = needsRelayout;
+ return needsRelayout;
+}
+
+void RenderMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width, unsigned& count) const
+{
+ RenderBlock* columnBlock = multiColumnBlockFlow();
+ const RenderStyle* columnStyle = columnBlock->style();
+ LayoutUnit availableWidth = columnBlock->contentLogicalWidth();
+ LayoutUnit columnGap = columnBlock->columnGap();
+ LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->columnWidth()));
+ unsigned computedColumnCount = max<int>(1, columnStyle->columnCount());
+
+ ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidth());
+ if (columnStyle->hasAutoColumnWidth() && !columnStyle->hasAutoColumnCount()) {
+ count = computedColumnCount;
+ width = std::max<LayoutUnit>(0, (availableWidth - ((count - 1) * columnGap)) / count);
+ } else if (!columnStyle->hasAutoColumnWidth() && columnStyle->hasAutoColumnCount()) {
+ count = std::max<LayoutUnit>(1, (availableWidth + columnGap) / (computedColumnWidth + columnGap));
+ width = ((availableWidth + columnGap) / count) - columnGap;
+ } else {
+ count = std::max<LayoutUnit>(std::min<LayoutUnit>(computedColumnCount, (availableWidth + columnGap) / (computedColumnWidth + columnGap)), 1);
+ width = ((availableWidth + columnGap) / count) - columnGap;
+ }
+}
+
+const char* RenderMultiColumnFlowThread::renderName() const
+{
+ return "RenderMultiColumnFlowThread";
+}
+
+void RenderMultiColumnFlowThread::addRegionToThread(RenderRegion* renderRegion)
+{
+ RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion);
+ if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) {
+ RenderRegionList::iterator it = m_regionList.find(nextSet);
+ ASSERT(it != m_regionList.end());
+ m_regionList.insertBefore(it, columnSet);
+ } else {
+ m_regionList.add(columnSet);
+ }
+ renderRegion->setIsValid(true);
+}
+
+void RenderMultiColumnFlowThread::willBeRemovedFromTree()
+{
+ // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
+ // are siblings of this object, and there may be pointers to this object's sibling somewhere
+ // further up on the call stack.
+ for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet())
+ columnSet->detachRegion();
+ multiColumnBlockFlow()->resetMultiColumnFlowThread();
+ RenderFlowThread::willBeRemovedFromTree();
+}
+
+void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+ // We simply remain at our intrinsic height.
+ computedValues.m_extent = logicalHeight;
+ computedValues.m_position = logicalTop;
+}
+
+void RenderMultiColumnFlowThread::updateLogicalWidth()
+{
+ LayoutUnit columnWidth;
+ calculateColumnCountAndWidth(columnWidth, m_columnCount);
+ setLogicalWidth(columnWidth);
+}
+
+void RenderMultiColumnFlowThread::layout()
+{
+ RenderFlowThread::layout();
+ if (RenderMultiColumnSet* lastSet = lastMultiColumnSet())
+ lastSet->expandToEncompassFlowThreadContentsIfNeeded();
}
void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage)
{
+ // Only positive values are interesting (and allowed) here. Zero space shortage may be reported
+ // when we're at the top of a column and the element has zero height. Ignore this, and also
+ // ignore any negative values, which may occur when we set an early break in order to honor
+ // widows in the next column.
+ if (spaceShortage <= 0)
+ return;
+
if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlockOffset(offset)))
multicolSet->recordSpaceShortage(spaceShortage);
}
@@ -116,4 +296,28 @@ void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay
multicolSet->updateMinimumColumnHeight(minHeight);
}
+RenderRegion* RenderMultiColumnFlowThread::regionAtBlockOffset(LayoutUnit /*offset*/) const
+{
+ // For now there's only one column set, so this is easy:
+ return firstMultiColumnSet();
+}
+
+bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, RenderObject* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment)
+{
+ if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlockOffset(offset))) {
+ multicolSet->addContentRun(offset);
+ if (offsetBreakAdjustment)
+ *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRemainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit();
+ return true;
+ }
+ return false;
+}
+
+bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
+{
+ if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
+ return columnSet->pageLogicalHeight();
+ return false;
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.h
index ace5c43cbfc..ff5784835b1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnFlowThread.h
@@ -31,21 +31,118 @@
namespace WebCore {
+class RenderMultiColumnSet;
+
+// Flow thread implementation for CSS multicol. This will be inserted as an anonymous child block of
+// the actual multicol container (i.e. the RenderBlockFlow whose style computes to non-auto
+// column-count and/or column-width). RenderMultiColumnFlowThread is the heart of the multicol
+// implementation, and there is only one instance per multicol container. Child content of the
+// multicol container is parented into the flow thread at the time of renderer insertion.
+//
+// Apart from this flow thread child, the multicol container will also have RenderMultiColumnSet
+// "region" children, which are used to position the columns visually. The flow thread is in charge
+// of layout, and, after having calculated the column width, it lays out content as if everything
+// were in one tall single column, except that there will typically be some amount of blank space
+// (also known as pagination struts) at the offsets where the actual column boundaries are. This
+// way, content that needs to be preceded by a break will appear at the top of the next
+// column. Content needs to be preceded by a break when there's a forced break or when the content
+// is unbreakable and cannot fully fit in the same column as the preceding piece of
+// content. Although a RenderMultiColumnFlowThread is laid out, it does not take up any space in its
+// container. It's the RenderMultiColumnSet objects that take up the necessary amount of space, and
+// make sure that the columns are painted and hit-tested correctly.
+//
+// The width of the flow thread is the same as the column width. The width of a column set is the
+// same as the content box width of the multicol container; in other words exactly enough to hold
+// the number of columns to be used, stacked horizontally, plus column gaps between them.
+//
+// Since it's the first child of the multicol container, the flow thread is laid out first, albeit
+// in a slightly special way, since it's not to take up any space in its ancestors. Afterwards, the
+// column sets are laid out. They get their height from the columns that they hold. In single
+// column-row constrained height non-balancing cases this will simply be the same as the content
+// height of the multicol container itself. In most other cases we'll have to calculate optimal
+// column heights ourselves, though. This process is referred to as column balancing, and then we
+// infer the column set height from the flow thread's height.
+//
+// More on column balancing: the columns' height is unknown in the first layout pass when
+// balancing. This means that we cannot insert any implicit (soft / unforced) breaks (and pagination
+// struts) when laying out the contents of the flow thread. We'll just lay out everything in tall
+// single strip. After the initial flow thread layout pass we can determine a tentative / minimal /
+// initial column height. This is calculated by simply dividing the flow thread's height by the
+// number of specified columns. In the layout pass that follows, we can insert breaks (and
+// pagination struts) at column boundaries, since we now have a column height. It may very easily
+// turn out that the calculated height wasn't enough, though. We'll notice this at end of layout. If
+// we end up with too many columns (i.e. columns overflowing the multicol container), it wasn't
+// enough. In this case we need to increase the column heights. We'll increase them by the lowest
+// amount of space that could possibly affect where the breaks occur (see
+// RenderMultiColumnSet::recordSpaceShortage()). We'll relayout (to find new break points and the
+// new lowest amount of space increase that could affect where they occur, in case we need another
+// round) until we've reached an acceptable height (where everything fits perfectly in the number of
+// columns that we have specified). The rule of thumb is that we shouldn't have to perform more of
+// such iterations than the number of columns that we have.
+//
+// For each layout iteration done for column balancing, the flow thread will need a deep layout if
+// column heights changed in the previous pass, since column height changes may affect break points
+// and pagination struts anywhere in the tree, and currently no way exists to do this in a more
+// optimized manner.
class RenderMultiColumnFlowThread FINAL : public RenderFlowThread {
public:
- ~RenderMultiColumnFlowThread();
+ virtual ~RenderMultiColumnFlowThread();
+
+ static RenderMultiColumnFlowThread* createAnonymous(Document&, RenderStyle* parentStyle);
+
+ virtual bool isRenderMultiColumnFlowThread() const OVERRIDE FINAL { return true; }
+
+ RenderBlockFlow* multiColumnBlockFlow() const { return toRenderBlockFlow(parent()); }
+
+ RenderMultiColumnSet* firstMultiColumnSet() const;
+ RenderMultiColumnSet* lastMultiColumnSet() const;
+
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+
+ // Populate the flow thread with what's currently its siblings. Called when a regular block
+ // becomes a multicol container.
+ void populate();
- static RenderMultiColumnFlowThread* createAnonymous(Document*);
+ // Empty the flow thread by moving everything to the parent. Remove all multicol specific
+ // renderers. Then destroy the flow thread. Called when a multicol container becomes a regular
+ // block.
+ void evacuateAndDestroy();
+
+ unsigned columnCount() const { return m_columnCount; }
+ LayoutUnit columnHeightAvailable() const { return m_columnHeightAvailable; }
+ void setColumnHeightAvailable(LayoutUnit available) { m_columnHeightAvailable = available; }
+ bool requiresBalancing() const { return !columnHeightAvailable() || multiColumnBlockFlow()->style()->columnFill() == ColumnFillBalance; }
+
+ virtual LayoutSize columnOffset(const LayoutPoint&) const OVERRIDE FINAL;
+
+ // Do we need to set a new width and lay out?
+ bool needsNewWidth() const;
+
+ void layoutColumns(bool relayoutChildren, SubtreeLayoutScope&);
+
+ bool recalculateColumnHeights();
private:
RenderMultiColumnFlowThread();
+ void calculateColumnCountAndWidth(LayoutUnit& width, unsigned& count) const;
+
virtual const char* renderName() const OVERRIDE;
+ virtual void addRegionToThread(RenderRegion*) OVERRIDE;
+ virtual void willBeRemovedFromTree() OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) OVERRIDE;
- virtual LayoutUnit initialLogicalWidth() const OVERRIDE;
+ virtual void updateLogicalWidth() OVERRIDE FINAL;
+ virtual void layout() OVERRIDE FINAL;
virtual void setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) OVERRIDE;
virtual void updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeight) OVERRIDE;
+ virtual RenderRegion* regionAtBlockOffset(LayoutUnit) const OVERRIDE;
+ virtual bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0) OVERRIDE;
+ virtual bool isPageLogicalHeightKnown() const OVERRIDE;
+
+ unsigned m_columnCount; // The used value of column-count
+ LayoutUnit m_columnHeightAvailable; // Total height available to columns, or 0 if auto.
+ bool m_inBalancingPass; // Set when relayouting for column balancing.
+ bool m_needsColumnHeightsRecalculation; // Set when we need to recalculate the column set heights after layout.
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.cpp
index 449073752ae..eee9aee2b43 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.cpp
@@ -28,7 +28,6 @@
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderMultiColumnBlock.h"
#include "core/rendering/RenderMultiColumnFlowThread.h"
using namespace std;
@@ -36,91 +35,202 @@ using namespace std;
namespace WebCore {
RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread)
- : RenderRegionSet(0, flowThread)
- , m_computedColumnCount(1)
- , m_computedColumnWidth(0)
- , m_computedColumnHeight(0)
- , m_maxColumnHeight(LayoutUnit::max())
- , m_minSpaceShortage(LayoutUnit::max())
+ : RenderRegion(0, flowThread)
+ , m_columnHeight(0)
+ , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight())
+ , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight())
, m_minimumColumnHeight(0)
- , m_forcedBreaksCount(0)
- , m_maximumDistanceBetweenForcedBreaks(0)
- , m_forcedBreakOffset(0)
{
}
-RenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* flowThread)
+RenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* flowThread, RenderStyle* parentStyle)
{
Document& document = flowThread->document();
RenderMultiColumnSet* renderer = new RenderMultiColumnSet(flowThread);
renderer->setDocumentForAnonymous(&document);
+ renderer->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
return renderer;
}
-LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) const
+RenderMultiColumnSet* RenderMultiColumnSet::nextSiblingMultiColumnSet() const
+{
+ for (RenderObject* sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
+ if (sibling->isRenderMultiColumnSet())
+ return toRenderMultiColumnSet(sibling);
+ }
+ return 0;
+}
+
+RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() const
+{
+ for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->previousSibling()) {
+ if (sibling->isRenderMultiColumnSet())
+ return toRenderMultiColumnSet(sibling);
+ }
+ return 0;
+}
+
+LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockOffset) const
{
- RenderMultiColumnBlock* multicolBlock = toRenderMultiColumnBlock(parent());
- LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore() - multicolBlock->paddingBefore();
+ unsigned columnIndex = columnIndexAtOffset(blockOffset);
+ LayoutRect portionRect(flowThreadPortionRectAt(columnIndex));
+ flipForWritingMode(portionRect);
+ LayoutRect columnRect(columnRectAt(columnIndex));
+ flipForWritingMode(columnRect);
+ return contentBoxRect().location() + columnRect.location() - portionRect.location();
+}
- height -= contentLogicalTop;
+LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) const
+{
+ // Adjust for the top offset within the content box of the multicol container (containing
+ // block), unless this is the first set. We know that the top offset for the first set will be
+ // zero, but if the multicol container has non-zero top border or padding, the set's top offset
+ // (initially being 0 and relative to the border box) will be negative until it has been laid
+ // out. Had we used this bogus offset, we would calculate the wrong height, and risk performing
+ // a wasted layout iteration. Of course all other sets (if any) have this problem in the first
+ // layout pass too, but there's really nothing we can do there until the flow thread has been
+ // laid out anyway.
+ if (previousSiblingMultiColumnSet()) {
+ RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
+ LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPaddingBefore();
+ height -= contentLogicalTop;
+ }
return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created.
}
LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
{
- LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x());
unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns);
- return portionLogicalTop + columnIndex * computedColumnHeight();
+ return logicalTopInFlowThread() + columnIndex * pageLogicalHeight();
}
void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight)
{
- m_computedColumnHeight = newHeight;
- if (m_computedColumnHeight > m_maxColumnHeight)
- m_computedColumnHeight = m_maxColumnHeight;
+ m_columnHeight = newHeight;
+ if (m_columnHeight > m_maxColumnHeight)
+ m_columnHeight = m_maxColumnHeight;
// FIXME: the height may also be affected by the enclosing pagination context, if any.
}
-bool RenderMultiColumnSet::calculateBalancedHeight(bool initial)
+unsigned RenderMultiColumnSet::findRunWithTallestColumns() const
+{
+ unsigned indexWithLargestHeight = 0;
+ LayoutUnit largestHeight;
+ LayoutUnit previousOffset = logicalTopInFlowThread();
+ size_t runCount = m_contentRuns.size();
+ ASSERT(runCount);
+ for (size_t i = 0; i < runCount; i++) {
+ const ContentRun& run = m_contentRuns[i];
+ LayoutUnit height = run.columnLogicalHeight(previousOffset);
+ if (largestHeight < height) {
+ largestHeight = height;
+ indexWithLargestHeight = i;
+ }
+ previousOffset = run.breakOffset();
+ }
+ return indexWithLargestHeight;
+}
+
+void RenderMultiColumnSet::distributeImplicitBreaks()
+{
+#ifndef NDEBUG
+ // There should be no implicit breaks assumed at this point.
+ for (unsigned i = 0; i < m_contentRuns.size(); i++)
+ ASSERT(!m_contentRuns[i].assumedImplicitBreaks());
+#endif // NDEBUG
+
+ // Insert a final content run to encompass all content. This will include overflow if this is
+ // the last set.
+ addContentRun(logicalBottomInFlowThread());
+ unsigned columnCount = m_contentRuns.size();
+
+ // If there is room for more breaks (to reach the used value of column-count), imagine that we
+ // insert implicit breaks at suitable locations. At any given time, the content run with the
+ // currently tallest columns will get another implicit break "inserted", which will increase its
+ // column count by one and shrink its columns' height. Repeat until we have the desired total
+ // number of breaks. The largest column height among the runs will then be the initial column
+ // height for the balancer to use.
+ while (columnCount < usedColumnCount()) {
+ unsigned index = findRunWithTallestColumns();
+ m_contentRuns[index].assumeAnotherImplicitBreak();
+ columnCount++;
+ }
+}
+
+LayoutUnit RenderMultiColumnSet::calculateColumnHeight(BalancedHeightCalculation calculationMode) const
{
- ASSERT(toRenderMultiColumnBlock(parent())->requiresBalancing());
- LayoutUnit oldColumnHeight = m_computedColumnHeight;
- LayoutUnit currentMinSpaceShortage = m_minSpaceShortage;
- m_minSpaceShortage = LayoutUnit::max();
-
- if (initial) {
- // Start with the lowest imaginable column height.
- LayoutUnit logicalHeightGuess = ceilf(float(flowThread()->logicalHeight()) / float(m_computedColumnCount));
- logicalHeightGuess = max(logicalHeightGuess, m_minimumColumnHeight);
- setAndConstrainColumnHeight(logicalHeightGuess);
-
- // The multicol container now typically needs at least one more layout pass with a new
- // column height, but if height was specified, we only need to do this if we found that we
- // might need less space than that. On the other hand, if we determined that the columns
- // need to be as tall as the specified height of the container, we have already laid it out
- // correctly, and there's no need for another pass.
- return m_computedColumnHeight != oldColumnHeight;
+ if (calculationMode == GuessFromFlowThreadPortion) {
+ // Initial balancing. Start with the lowest imaginable column height. We use the tallest
+ // content run (after having "inserted" implicit breaks), and find its start offset (by
+ // looking at the previous run's end offset, or, if there's no previous run, the set's start
+ // offset in the flow thread).
+ unsigned index = findRunWithTallestColumns();
+ LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : logicalTopInFlowThread();
+ return std::max<LayoutUnit>(m_contentRuns[index].columnLogicalHeight(startOffset), m_minimumColumnHeight);
}
- if (columnCount() <= computedColumnCount()) {
+ if (actualColumnCount() <= usedColumnCount()) {
// With the current column height, the content fits without creating overflowing columns. We're done.
- return false;
+ return m_columnHeight;
+ }
+
+ if (m_contentRuns.size() >= usedColumnCount()) {
+ // Too many forced breaks to allow any implicit breaks. Initial balancing should already
+ // have set a good height. There's nothing more we should do.
+ return m_columnHeight;
}
// If the initial guessed column height wasn't enough, stretch it now. Stretch by the lowest
// amount of space shortage found during layout.
- ASSERT(currentMinSpaceShortage != LayoutUnit::max()); // If this can actually happen, we probably have a bug.
- if (currentMinSpaceShortage == LayoutUnit::max())
- return false; // So bail out rather than looping infinitely.
+ ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height!
+ ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If this happens, we probably have a bug.
+ if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight())
+ return m_columnHeight; // So bail out rather than looping infinitely.
+
+ return m_columnHeight + m_minSpaceShortage;
+}
+
+void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage)
+{
+ if (!multiColumnFlowThread()->requiresBalancing())
+ return;
+ if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last().breakOffset())
+ return;
+ // Append another item as long as we haven't exceeded used column count. What ends up in the
+ // overflow area shouldn't affect column balancing.
+ if (m_contentRuns.size() < usedColumnCount())
+ m_contentRuns.append(ContentRun(endOffsetFromFirstPage));
+}
+
+bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation calculationMode)
+{
+ ASSERT(multiColumnFlowThread()->requiresBalancing());
+
+ LayoutUnit oldColumnHeight = m_columnHeight;
+ if (calculationMode == GuessFromFlowThreadPortion) {
+ // Post-process the content runs and find out where the implicit breaks will occur.
+ distributeImplicitBreaks();
+ }
+ LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode);
+ setAndConstrainColumnHeight(newColumnHeight);
+
+ // After having calculated an initial column height, the multicol container typically needs at
+ // least one more layout pass with a new column height, but if a height was specified, we only
+ // need to do this if we think that we need less space than specified. Conversely, if we
+ // determined that the columns need to be as tall as the specified height of the container, we
+ // have already laid it out correctly, and there's no need for another pass.
- setAndConstrainColumnHeight(m_computedColumnHeight + currentMinSpaceShortage);
+ // We can get rid of the content runs now, if we haven't already done so. They are only needed
+ // to calculate the initial balanced column height. In fact, we have to get rid of them before
+ // the next layout pass, since each pass will rebuild this.
+ m_contentRuns.clear();
- // If we reach the maximum column height (typically set by the height or max-height property),
- // we may not be allowed to stretch further. Return true only if stretching
- // succeeded. Otherwise, we're done.
- ASSERT(m_computedColumnHeight >= oldColumnHeight); // We shouldn't be able to shrink the height!
- return m_computedColumnHeight > oldColumnHeight;
+ if (m_columnHeight == oldColumnHeight)
+ return false; // No change. We're done.
+
+ m_minSpaceShortage = RenderFlowThread::maxLogicalHeight();
+ return true; // Need another pass.
}
void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage)
@@ -135,94 +245,95 @@ void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage)
m_minSpaceShortage = spaceShortage;
}
-void RenderMultiColumnSet::updateLogicalWidth()
+void RenderMultiColumnSet::resetColumnHeight()
{
- RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
- setComputedColumnWidthAndCount(parentBlock->columnWidth(), parentBlock->columnCount()); // FIXME: This will eventually vary if we are contained inside regions.
+ // Nuke previously stored minimum column height. Contents may have changed for all we know.
+ m_minimumColumnHeight = 0;
- // FIXME: When we add regions support, we'll start it off at the width of the multi-column
- // block in that particular region.
- setLogicalWidth(parentBox()->contentLogicalWidth());
+ m_maxColumnHeight = calculateMaxColumnHeight();
- // If we overflow, increase our logical width.
- unsigned colCount = columnCount();
- LayoutUnit colGap = columnGap();
- LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + (colCount - 1) * colGap;
- LayoutUnit currentContentLogicalWidth = contentLogicalWidth();
- LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentContentLogicalWidth);
- if (!delta)
- return;
+ LayoutUnit oldColumnHeight = pageLogicalHeight();
- // Increase our logical width by the delta.
- setLogicalWidth(logicalWidth() + delta);
-}
+ if (multiColumnFlowThread()->requiresBalancing())
+ m_columnHeight = 0;
+ else
+ setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowThread()->columnHeightAvailable()));
-void RenderMultiColumnSet::prepareForLayout()
-{
- RenderMultiColumnBlock* multicolBlock = toRenderMultiColumnBlock(parent());
- RenderStyle* multicolStyle = multicolBlock->style();
+ if (pageLogicalHeight() != oldColumnHeight)
+ setChildNeedsLayout(MarkOnlyThis);
- // Set box logical top.
- ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSet()); // FIXME: multiple set not implemented; need to examine previous set to calculate the correct logical top.
- setLogicalTop(multicolBlock->borderBefore() + multicolBlock->paddingBefore());
-
- // Set box width.
- updateLogicalWidth();
-
- if (multicolBlock->requiresBalancing()) {
- // Set maximum column height. We will not stretch beyond this.
- m_maxColumnHeight = LayoutUnit::max();
- if (!multicolStyle->logicalHeight().isAuto())
- m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multicolStyle->logicalHeight(), -1);
- if (!multicolStyle->logicalMaxHeight().isUndefined()) {
- LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight(multicolStyle->logicalMaxHeight(), -1);
- if (m_maxColumnHeight > logicalMaxHeight)
- m_maxColumnHeight = logicalMaxHeight;
- }
- m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight);
- m_computedColumnHeight = 0; // Restart balancing.
- } else {
- setAndConstrainColumnHeight(heightAdjustedForSetOffset(multicolBlock->columnHeightAvailable()));
- }
+ // Content runs are only needed in the initial layout pass, in order to find an initial column
+ // height, and should have been deleted afterwards. We're about to rebuild the content runs, so
+ // the list needs to be empty.
+ ASSERT(m_contentRuns.isEmpty());
+}
- // Nuke previously stored minimum column height. Contents may have changed for all we know.
- m_minimumColumnHeight = 0;
+void RenderMultiColumnSet::expandToEncompassFlowThreadContentsIfNeeded()
+{
+ ASSERT(multiColumnFlowThread()->lastMultiColumnSet() == this);
+ LayoutRect rect(flowThreadPortionRect());
+
+ // Get the offset within the flow thread in its block progression direction. Then get the
+ // flow thread's remaining logical height including its overflow and expand our rect
+ // to encompass that remaining height and overflow. The idea is that we will generate
+ // additional columns and pages to hold that overflow, since people do write bad
+ // content like <body style="height:0px"> in multi-column layouts.
+ bool isHorizontal = flowThread()->isHorizontalWritingMode();
+ LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x();
+ LayoutRect layoutRect = flowThread()->layoutOverflowRect();
+ LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : layoutRect.maxX()) - logicalTopOffset;
+ setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect.width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height()));
}
void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
- computedValues.m_extent = m_computedColumnHeight;
+ computedValues.m_extent = m_columnHeight;
computedValues.m_position = logicalTop;
}
+LayoutUnit RenderMultiColumnSet::calculateMaxColumnHeight() const
+{
+ RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
+ RenderStyle* multicolStyle = multicolBlock->style();
+ LayoutUnit availableHeight = multiColumnFlowThread()->columnHeightAvailable();
+ LayoutUnit maxColumnHeight = availableHeight ? availableHeight : RenderFlowThread::maxLogicalHeight();
+ if (!multicolStyle->logicalMaxHeight().isUndefined()) {
+ LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight(multicolStyle->logicalMaxHeight(), -1);
+ if (logicalMaxHeight != -1 && maxColumnHeight > logicalMaxHeight)
+ maxColumnHeight = logicalMaxHeight;
+ }
+ return heightAdjustedForSetOffset(maxColumnHeight);
+}
+
LayoutUnit RenderMultiColumnSet::columnGap() const
{
- // FIXME: Eventually we will cache the column gap when the widths of columns start varying, but for now we just
- // go to the parent block to get the gap.
- RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
+ RenderBlockFlow* parentBlock = multiColumnBlockFlow();
if (parentBlock->style()->hasNormalColumnGap())
return parentBlock->style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
return parentBlock->style()->columnGap();
}
-unsigned RenderMultiColumnSet::columnCount() const
+unsigned RenderMultiColumnSet::actualColumnCount() const
{
// We must always return a value of 1 or greater. Column count = 0 is a meaningless situation,
// and will confuse and cause problems in other parts of the code.
- if (!computedColumnHeight())
+ if (!pageLogicalHeight())
return 1;
// Our portion rect determines our column count. We have as many columns as needed to fit all the content.
LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width();
- unsigned count = ceil(static_cast<float>(logicalHeightInColumns) / computedColumnHeight());
+ if (!logicalHeightInColumns)
+ return 1;
+
+ unsigned count = ceil(logicalHeightInColumns.toFloat() / pageLogicalHeight().toFloat());
ASSERT(count >= 1);
return count;
}
LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
{
- LayoutUnit colLogicalWidth = computedColumnWidth();
- LayoutUnit colLogicalHeight = computedColumnHeight();
+ LayoutUnit colLogicalWidth = pageLogicalWidth();
+ LayoutUnit colLogicalHeight = pageLogicalHeight();
LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft();
LayoutUnit colGap = columnGap();
@@ -249,20 +360,20 @@ unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset, ColumnInde
if (mode == ClampToExistingColumns) {
LayoutUnit flowThreadLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX();
if (offset >= flowThreadLogicalBottom)
- return columnCount() - 1;
+ return actualColumnCount() - 1;
}
// Just divide by the column height to determine the correct column.
- return static_cast<float>(offset - flowThreadLogicalTop) / computedColumnHeight();
+ return (offset - flowThreadLogicalTop).toFloat() / pageLogicalHeight().toFloat();
}
LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const
{
LayoutRect portionRect = flowThreadPortionRect();
if (isHorizontalWritingMode())
- portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * computedColumnHeight(), portionRect.width(), computedColumnHeight());
+ portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * pageLogicalHeight(), portionRect.width(), pageLogicalHeight());
else
- portionRect = LayoutRect(portionRect.x() + index * computedColumnHeight(), portionRect.y(), computedColumnHeight(), portionRect.height());
+ portionRect = LayoutRect(portionRect.x() + index * pageLogicalHeight(), portionRect.y(), pageLogicalHeight(), portionRect.height());
return portionRect;
}
@@ -308,7 +419,7 @@ void RenderMultiColumnSet::paintObject(PaintInfo& paintInfo, const LayoutPoint&
if (style()->visibility() != VISIBLE)
return;
- RenderBlock::paintObject(paintInfo, paintOffset);
+ RenderBlockFlow::paintObject(paintInfo, paintOffset);
// FIXME: Right now we're only painting in the foreground phase.
// Columns should technically respect phases and allow for background/float/foreground overlap etc., just like
@@ -326,7 +437,7 @@ void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
if (paintInfo.context->paintingDisabled())
return;
- RenderStyle* blockStyle = toRenderMultiColumnBlock(parent())->style();
+ RenderStyle* blockStyle = multiColumnBlockFlow()->style();
const Color& ruleColor = resolveColor(blockStyle, CSSPropertyWebkitColumnRuleColor);
bool ruleTransparent = blockStyle->columnRuleIsTransparent();
EBorderStyle ruleStyle = blockStyle->columnRuleStyle();
@@ -336,7 +447,7 @@ void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
if (!renderRule)
return;
- unsigned colCount = columnCount();
+ unsigned colCount = actualColumnCount();
if (colCount <= 1)
return;
@@ -346,7 +457,7 @@ void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
LayoutUnit ruleAdd = borderAndPaddingLogicalLeft();
LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
- LayoutUnit inlineDirectionSize = computedColumnWidth();
+ LayoutUnit inlineDirectionSize = pageLogicalWidth();
BoxSide boxSide = isHorizontalWritingMode()
? leftToRight ? BSLeft : BSRight
: leftToRight ? BSTop : BSBottom;
@@ -398,7 +509,7 @@ void RenderMultiColumnSet::repaintFlowThreadContent(const LayoutRect& repaintRec
unsigned endColumn = columnIndexAtOffset(repaintLogicalBottom);
LayoutUnit colGap = columnGap();
- unsigned colCount = columnCount();
+ unsigned colCount = actualColumnCount();
for (unsigned i = startColumn; i <= endColumn; i++) {
LayoutRect colRect = columnRectAt(i);
@@ -451,9 +562,9 @@ void RenderMultiColumnSet::collectLayerFragments(LayerFragments& fragments, cons
unsigned startColumn = columnIndexAtOffset(layerLogicalTop);
unsigned endColumn = columnIndexAtOffset(layerLogicalBottom);
- LayoutUnit colLogicalWidth = computedColumnWidth();
+ LayoutUnit colLogicalWidth = pageLogicalWidth();
LayoutUnit colGap = columnGap();
- unsigned colCount = columnCount();
+ unsigned colCount = actualColumnCount();
for (unsigned i = startColumn; i <= endColumn; i++) {
// Get the portion of the flow thread that corresponds to this column.
@@ -507,6 +618,18 @@ void RenderMultiColumnSet::collectLayerFragments(LayerFragments& fragments, cons
}
}
+void RenderMultiColumnSet::addOverflowFromChildren()
+{
+ unsigned colCount = actualColumnCount();
+ if (!colCount)
+ return;
+
+ LayoutRect lastRect = columnRectAt(colCount - 1);
+ addLayoutOverflow(lastRect);
+ if (!hasOverflowClip())
+ addVisualOverflow(lastRect);
+}
+
const char* RenderMultiColumnSet::renderName() const
{
return "RenderMultiColumnSet";
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.h b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.h
index 3ebfc5e9c56..16c12faaf36 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderMultiColumnSet.h
@@ -27,65 +27,75 @@
#ifndef RenderMultiColumnSet_h
#define RenderMultiColumnSet_h
-#include "core/rendering/RenderRegionSet.h"
+#include "core/rendering/RenderMultiColumnFlowThread.h"
+#include "core/rendering/RenderRegion.h"
+#include "wtf/Vector.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.
+// 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 sets are inserted as anonymous children of the actual multicol container (i.e. the
+// renderer whose style computes to non-auto column-count and/or column-width).
//
-// 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 FINAL : public RenderRegionSet {
+// Being a "region", a column set has no children on its own, but is merely used to slice a portion
+// of the tall "single-column" flow thread into actual columns visually, to convert from flow thread
+// coordinates to visual ones. It is in charge of both positioning columns correctly relatively to
+// the parent multicol container, and to calculate the correct translation for each column's
+// contents, and to paint any rules between them. RenderMultiColumnSet objects are used for
+// painting, hit testing, and any other type of operation that requires mapping from flow thread
+// coordinates to visual coordinates.
+//
+// Column spans result in the creation of new column sets, since a spanning renderer has to be
+// placed in between the column sets that come before and after the span.
+class RenderMultiColumnSet FINAL : public RenderRegion {
public:
- static RenderMultiColumnSet* createAnonymous(RenderFlowThread*);
+ enum BalancedHeightCalculation { GuessFromFlowThreadPortion, StretchBySpaceShortage };
+
+ static RenderMultiColumnSet* createAnonymous(RenderFlowThread*, RenderStyle* parentStyle);
virtual bool isRenderMultiColumnSet() const OVERRIDE { return true; }
- unsigned computedColumnCount() const { return m_computedColumnCount; }
- LayoutUnit computedColumnWidth() const { return m_computedColumnWidth; }
- LayoutUnit computedColumnHeight() const { return m_computedColumnHeight; }
+ virtual LayoutUnit pageLogicalWidth() const OVERRIDE FINAL { return flowThread()->logicalWidth(); }
+ virtual LayoutUnit pageLogicalHeight() const OVERRIDE FINAL { return m_columnHeight; }
- void setComputedColumnWidthAndCount(LayoutUnit width, unsigned count)
+ RenderBlockFlow* multiColumnBlockFlow() const { return toRenderBlockFlow(parent()); }
+ RenderMultiColumnFlowThread* multiColumnFlowThread() const
{
- m_computedColumnWidth = width;
- m_computedColumnCount = count;
+ ASSERT_WITH_SECURITY_IMPLICATION(!flowThread() || flowThread()->isRenderMultiColumnFlowThread());
+ return static_cast<RenderMultiColumnFlowThread*>(flowThread());
}
+ RenderMultiColumnSet* nextSiblingMultiColumnSet() const;
+ RenderMultiColumnSet* previousSiblingMultiColumnSet() const;
+
+ LayoutUnit logicalTopInFlowThread() const { return isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x(); }
+ LayoutUnit logicalBottomInFlowThread() const { return isHorizontalWritingMode() ? flowThreadPortionRect().maxY() : flowThreadPortionRect().maxX(); }
+
+ LayoutUnit logicalHeightInFlowThread() const { return isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width(); }
+
+ // The used CSS value of column-count, i.e. how many columns there are room for without overflowing.
+ unsigned usedColumnCount() const { return multiColumnFlowThread()->columnCount(); }
+
+ // Find the column that contains the given block offset, and return the translation needed to
+ // get from flow thread coordinates to visual coordinates.
+ LayoutSize flowThreadTranslationAtOffset(LayoutUnit) const;
+
LayoutUnit heightAdjustedForSetOffset(LayoutUnit height) const;
void updateMinimumColumnHeight(LayoutUnit height) { m_minimumColumnHeight = std::max(height, m_minimumColumnHeight); }
LayoutUnit minimumColumnHeight() const { return m_minimumColumnHeight; }
- unsigned forcedBreaksCount() const { return m_forcedBreaksCount; }
- LayoutUnit forcedBreakOffset() const { return m_forcedBreakOffset; }
- LayoutUnit maximumDistanceBetweenForcedBreaks() const { return m_maximumDistanceBetweenForcedBreaks; }
- void clearForcedBreaks()
- {
- m_forcedBreaksCount = 0;
- m_maximumDistanceBetweenForcedBreaks = 0;
- m_forcedBreakOffset = 0;
- }
- void addForcedBreak(LayoutUnit offsetFromFirstPage)
- {
- ASSERT(!computedColumnHeight());
- LayoutUnit distanceFromLastBreak = offsetFromFirstPage - m_forcedBreakOffset;
- if (!distanceFromLastBreak)
- return;
- m_forcedBreaksCount++;
- m_maximumDistanceBetweenForcedBreaks = std::max(m_maximumDistanceBetweenForcedBreaks, distanceFromLastBreak);
- m_forcedBreakOffset = offsetFromFirstPage;
- }
+ // Add a content run, specified by its end position. A content run is appended at every
+ // forced/explicit break and at the end of the column set. The content runs are used to
+ // determine where implicit/soft breaks will occur, in order to calculate an initial column
+ // height.
+ void addContentRun(LayoutUnit endOffsetFromFirstPage);
- // Calculate the column height when contents are supposed to be balanced. If 'initial' is set,
- // guess an initial column height; otherwise, stretch the column height a tad. Return true if
- // column height changed and another layout pass is required.
- bool calculateBalancedHeight(bool initial);
+ // (Re-)calculate the column height if it's auto.
+ bool recalculateColumnHeight(BalancedHeightCalculation);
// Record space shortage (the amount of space that would have been enough to prevent some
// element from being moved to the next column) at a column break. The smallest amount of space
@@ -93,9 +103,12 @@ public:
// after layout that the columns weren't tall enough.
void recordSpaceShortage(LayoutUnit spaceShortage);
- virtual void updateLogicalWidth() OVERRIDE;
+ // Reset previously calculated column height. Will mark for layout if needed.
+ void resetColumnHeight();
- void prepareForLayout();
+ // Expand this set's flow thread portion rectangle to contain all trailing flow thread
+ // overflow. Only to be called on the last set.
+ void expandToEncompassFlowThreadContentsIfNeeded();
private:
RenderMultiColumnSet(RenderFlowThread*);
@@ -104,29 +117,26 @@ private:
virtual void paintObject(PaintInfo&, const LayoutPoint& paintOffset) OVERRIDE;
- virtual LayoutUnit pageLogicalWidth() const OVERRIDE { return m_computedColumnWidth; }
- virtual LayoutUnit pageLogicalHeight() const OVERRIDE { return m_computedColumnHeight; }
-
virtual LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const OVERRIDE;
- // FIXME: This will change once we have column sets constrained by enclosing pages, etc.
- virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const OVERRIDE { return m_computedColumnHeight; }
-
- // FIXME: For now we return false, but it's likely we will leverage the auto height region code to do column
- // balancing. That's why we have an override of this function that is distinct from RenderRegionSet's override.
- virtual bool shouldHaveAutoLogicalHeight() const OVERRIDE { return false; }
+ virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const OVERRIDE { return logicalHeightInFlowThread(); }
virtual void repaintFlowThreadContent(const LayoutRect& repaintRect) const OVERRIDE;
virtual void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) OVERRIDE;
- virtual const char* renderName() const;
+ virtual void addOverflowFromChildren() OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE;
void paintColumnRules(PaintInfo&, const LayoutPoint& paintOffset);
+ LayoutUnit calculateMaxColumnHeight() const;
LayoutUnit columnGap() const;
LayoutRect columnRectAt(unsigned index) const;
- unsigned columnCount() const;
+
+ // The "CSS actual" value of column-count. This includes overflowing columns, if any.
+ unsigned actualColumnCount() const;
LayoutRect flowThreadPortionRectAt(unsigned index) const;
LayoutRect flowThreadPortionOverflowRect(const LayoutRect& flowThreadPortion, unsigned index, unsigned colCount, LayoutUnit colGap) const;
@@ -139,17 +149,50 @@ private:
void setAndConstrainColumnHeight(LayoutUnit);
- unsigned m_computedColumnCount;
- LayoutUnit m_computedColumnWidth;
- LayoutUnit m_computedColumnHeight;
+ // Return the index of the content run with the currently tallest columns, taking all implicit
+ // breaks assumed so far into account.
+ unsigned findRunWithTallestColumns() const;
+
+ // Given the current list of content runs, make assumptions about where we need to insert
+ // implicit breaks (if there's room for any at all; depending on the number of explicit breaks),
+ // and store the results. This is needed in order to balance the columns.
+ void distributeImplicitBreaks();
+
+ LayoutUnit calculateColumnHeight(BalancedHeightCalculation) const;
+
+ LayoutUnit m_columnHeight;
// The following variables are used when balancing the column set.
LayoutUnit m_maxColumnHeight; // Maximum column height allowed.
LayoutUnit m_minSpaceShortage; // The smallest amout of space shortage that caused a column break.
LayoutUnit m_minimumColumnHeight;
- unsigned m_forcedBreaksCount; // FIXME: We will ultimately need to cache more information to balance around forced breaks properly.
- LayoutUnit m_maximumDistanceBetweenForcedBreaks;
- LayoutUnit m_forcedBreakOffset;
+
+ // A run of content without explicit (forced) breaks; i.e. a flow thread portion between two
+ // explicit breaks, between flow thread start and an explicit break, between an explicit break
+ // and flow thread end, or, in cases when there are no explicit breaks at all: between flow
+ // thread portion start and flow thread portion end. We need to know where the explicit breaks
+ // are, in order to figure out where the implicit breaks will end up, so that we get the columns
+ // properly balanced. A content run starts out as representing one single column, and will
+ // represent one additional column for each implicit break "inserted" there.
+ class ContentRun {
+ public:
+ ContentRun(LayoutUnit breakOffset)
+ : m_breakOffset(breakOffset)
+ , m_assumedImplicitBreaks(0) { }
+
+ unsigned assumedImplicitBreaks() const { return m_assumedImplicitBreaks; }
+ void assumeAnotherImplicitBreak() { m_assumedImplicitBreaks++; }
+ LayoutUnit breakOffset() const { return m_breakOffset; }
+
+ // Return the column height that this content run would require, considering the implicit
+ // breaks assumed so far.
+ LayoutUnit columnLogicalHeight(LayoutUnit startOffset) const { return ceilf((m_breakOffset - startOffset).toFloat() / float(m_assumedImplicitBreaks + 1)); }
+
+ private:
+ LayoutUnit m_breakOffset; // Flow thread offset where this run ends.
+ unsigned m_assumedImplicitBreaks; // Number of implicit breaks in this run assumed so far.
+ };
+ Vector<ContentRun, 1> m_contentRuns;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderMultiColumnSet, isRenderMultiColumnSet());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.cpp
deleted file mode 100644
index 5a754e99f82..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2013 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 "core/rendering/RenderNamedFlowFragment.h"
-
-#include "core/rendering/FlowThreadController.h"
-#include "core/rendering/RenderBoxRegionInfo.h"
-#include "core/rendering/RenderFlowThread.h"
-#include "core/rendering/RenderNamedFlowThread.h"
-#include "core/rendering/RenderView.h"
-
-using namespace std;
-
-namespace WebCore {
-
-RenderNamedFlowFragment::RenderNamedFlowFragment()
- : RenderRegion(0, 0)
-{
-}
-
-RenderNamedFlowFragment::~RenderNamedFlowFragment()
-{
-}
-
-RenderNamedFlowFragment* RenderNamedFlowFragment::createAnonymous(Document* document)
-{
- RenderNamedFlowFragment* region = new RenderNamedFlowFragment();
- region->setDocumentForAnonymous(document);
- return region;
-}
-
-void RenderNamedFlowFragment::setStyleForNamedFlowFragment(const RenderStyle* parentStyle)
-{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK);
-
- newStyle->setFlowThread(parentStyle->flowThread());
- newStyle->setRegionThread(parentStyle->regionThread());
- newStyle->setRegionFragment(parentStyle->regionFragment());
- newStyle->setShapeInside(parentStyle->shapeInside());
- newStyle->setOverflowX(parentStyle->overflowX());
- newStyle->setOverflowY(parentStyle->overflowY());
-
- setStyle(newStyle.release());
-}
-
-void RenderNamedFlowFragment::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderRegion::styleDidChange(diff, oldStyle);
-
- if (parent() && parent()->needsLayout())
- setNeedsLayout();
-}
-
-// FIXME: flex items as regions with flex-basis: 0 inside a flex container
-// with flex-direction: column should not be treated as auto-height regions
-bool RenderNamedFlowFragment::shouldHaveAutoLogicalHeight() const
-{
- ASSERT(parent());
-
- RenderStyle* styleToUse = parent()->style();
- bool hasSpecifiedEndpointsForHeight = styleToUse->logicalTop().isSpecified() && styleToUse->logicalBottom().isSpecified();
- bool hasAnchoredEndpointsForHeight = isOutOfFlowPositioned() && hasSpecifiedEndpointsForHeight;
- bool hasAutoHeightStyle = styleToUse->logicalHeight().isAuto()
- || styleToUse->logicalHeight().isFitContent()
- || styleToUse->logicalHeight().isMaxContent()
- || styleToUse->logicalHeight().isMinContent();
- return hasAutoHeightStyle && !hasAnchoredEndpointsForHeight;
-}
-
-LayoutUnit RenderNamedFlowFragment::maxPageLogicalHeight() const
-{
- ASSERT(m_flowThread);
- ASSERT(hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase());
- ASSERT(isAnonymous());
- ASSERT(parent());
-
- RenderStyle* styleToUse = parent()->style();
- return styleToUse->logicalMaxHeight().isUndefined() ? RenderFlowThread::maxLogicalHeight() : toRenderBlock(parent())->computeReplacedLogicalHeightUsing(styleToUse->logicalMaxHeight());
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.h b/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.h
deleted file mode 100644
index 79e4d7ceb63..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowFragment.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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 RenderNamedFlowFragment_h
-#define RenderNamedFlowFragment_h
-
-#include "core/rendering/RenderRegion.h"
-
-namespace WebCore {
-
-class Element;
-class RenderStyle;
-
-// RenderNamedFlowFragment represents a region that is responsible for the fragmentation of
-// the RenderNamedFlowThread content.
-//
-// A RenderNamedFlowFragment object is created as an anonymous child for a RenderBlockFlow object
-// that has a valid -webkit-flow-from property.
-//
-// This allows a non-replaced block to behave like a region if needed, following the CSSRegions specification:
-// http://dev.w3.org/csswg/css-regions/#the-flow-from-property.
-// list-item, table-caption, table-cell can become regions in addition to block | inline-block.
-
-class RenderNamedFlowFragment FINAL : public RenderRegion {
-public:
- virtual ~RenderNamedFlowFragment();
- static RenderNamedFlowFragment* createAnonymous(Document*);
-
- void setStyleForNamedFlowFragment(const RenderStyle*);
-
- virtual bool isRenderNamedFlowFragment() const OVERRIDE { return true; }
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
-
- virtual LayoutUnit maxPageLogicalHeight() const OVERRIDE;
-
-protected:
- RenderNamedFlowFragment();
-
-private:
- virtual bool shouldHaveAutoLogicalHeight() const OVERRIDE;
- virtual const char* renderName() const OVERRIDE { return "RenderNamedFlowFragment"; }
-};
-
-DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderNamedFlowFragment, isRenderNamedFlowFragment());
-
-}
-
-#endif // RenderNamedFlowFragment_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.cpp
deleted file mode 100644
index 72049543c9d..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.cpp
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * 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 "core/rendering/RenderNamedFlowThread.h"
-
-#include "RuntimeEnabledFeatures.h"
-#include "bindings/v8/ExceptionStatePlaceholder.h"
-#include "core/dom/NamedFlow.h"
-#include "core/dom/NodeRenderingTraversal.h"
-#include "core/dom/NodeTraversal.h"
-#include "core/dom/Position.h"
-#include "core/dom/Range.h"
-#include "core/dom/Text.h"
-#include "core/inspector/InspectorInstrumentation.h"
-#include "core/rendering/FlowThreadController.h"
-#include "core/rendering/InlineTextBox.h"
-#include "core/rendering/RenderInline.h"
-#include "core/rendering/RenderRegion.h"
-#include "core/rendering/RenderText.h"
-#include "core/rendering/RenderView.h"
-
-namespace WebCore {
-
-RenderNamedFlowThread* RenderNamedFlowThread::createAnonymous(Document* document, PassRefPtr<NamedFlow> namedFlow)
-{
- ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled());
- RenderNamedFlowThread* renderer = new RenderNamedFlowThread(namedFlow);
- renderer->setDocumentForAnonymous(document);
- return renderer;
-}
-
-RenderNamedFlowThread::RenderNamedFlowThread(PassRefPtr<NamedFlow> namedFlow)
- : m_overset(true)
- , m_namedFlow(namedFlow)
- , m_regionLayoutUpdateEventTimer(this, &RenderNamedFlowThread::regionLayoutUpdateEventTimerFired)
- , m_regionOversetChangeEventTimer(this, &RenderNamedFlowThread::regionOversetChangeEventTimerFired)
-{
-}
-
-RenderNamedFlowThread::~RenderNamedFlowThread()
-{
- // The flow thread can be destroyed without unregistering the content nodes if the document is destroyed.
- // This can lead to problems because the nodes are still marked as belonging to a flow thread.
- clearContentNodes();
-
- // Also leave the NamedFlow object in a consistent state by calling mark for destruction.
- setMarkForDestruction();
-}
-
-const char* RenderNamedFlowThread::renderName() const
-{
- return "RenderNamedFlowThread";
-}
-
-void RenderNamedFlowThread::clearContentNodes()
-{
- for (NamedFlowContentNodes::iterator it = m_contentNodes.begin(); it != m_contentNodes.end(); ++it) {
- Node* contentNode = *it;
-
- ASSERT(contentNode && contentNode->isElementNode());
- ASSERT(contentNode->inNamedFlow());
- ASSERT(contentNode->document() == document());
-
- contentNode->clearInNamedFlow();
- }
-
- m_contentNodes.clear();
-}
-
-void RenderNamedFlowThread::updateWritingMode()
-{
- RenderRegion* firstRegion = m_regionList.first();
- if (!firstRegion)
- return;
- if (style()->writingMode() == firstRegion->style()->writingMode())
- return;
-
- // The first region defines the principal writing mode for the entire flow.
- RefPtr<RenderStyle> newStyle = RenderStyle::clone(style());
- newStyle->setWritingMode(firstRegion->style()->writingMode());
- setStyle(newStyle.release());
-}
-
-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)
-{
- // 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.
-
- Node* childNode = newChild->node();
-
- // Do not add anonymous objects.
- if (!childNode)
- return;
-
- ASSERT(childNode->isElementNode());
-
- RenderObject* beforeChild = nextRendererForNode(childNode);
- 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).key;
- 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);
-
- ASSERT(firstRegion->generatingNodeForRegion());
- ASSERT(secondRegion->generatingNodeForRegion());
-
- // If the regions belong to different nodes, compare their position in the DOM.
- if (firstRegion->generatingNodeForRegion() != secondRegion->generatingNodeForRegion()) {
- unsigned short position = firstRegion->generatingNodeForRegion()->compareDocumentPosition(secondRegion->generatingNodeForRegion());
-
- // If the second region is contained in the first one, the first region is "less" if it's :before.
- if (position & Node::DOCUMENT_POSITION_CONTAINED_BY) {
- ASSERT(secondRegion->style()->styleType() == NOPSEUDO);
- return firstRegion->style()->styleType() == BEFORE;
- }
-
- // If the second region contains the first region, the first region is "less" if the second is :after.
- if (position & Node::DOCUMENT_POSITION_CONTAINS) {
- ASSERT(firstRegion->style()->styleType() == NOPSEUDO);
- return secondRegion->style()->styleType() == AFTER;
- }
-
- return (position & Node::DOCUMENT_POSITION_FOLLOWING);
- }
-
- // FIXME: Currently it's not possible for an element to be both a region and have pseudo-children. The case is covered anyway.
- switch (firstRegion->style()->styleType()) {
- case BEFORE:
- // The second region can be the node or the after pseudo-element (before is smaller than any of those).
- return true;
- case AFTER:
- // The second region can be the node or the before pseudo-element (after is greater than any of those).
- return false;
- case NOPSEUDO:
- // The second region can either be the before or the after pseudo-element (the node is only smaller than the after pseudo-element).
- return firstRegion->style()->styleType() == AFTER;
- default:
- break;
- }
-
- ASSERT_NOT_REACHED();
- return true;
-}
-
-// This helper function adds a region to a list preserving the order property of the list.
-static void addRegionToList(RenderRegionList& regionList, RenderRegion* renderRegion)
-{
- if (regionList.isEmpty()) {
- regionList.add(renderRegion);
- } else {
- // Find the first region "greater" than renderRegion.
- RenderRegionList::iterator it = regionList.begin();
- while (it != regionList.end() && !compareRenderRegions(renderRegion, *it))
- ++it;
- regionList.insertBefore(it, renderRegion);
- }
-}
-
-void RenderNamedFlowThread::addRegionToNamedFlowThread(RenderRegion* renderRegion)
-{
- ASSERT(renderRegion);
- ASSERT(!renderRegion->isValid());
-
- if (renderRegion->parentNamedFlowThread())
- addDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
-
- renderRegion->setIsValid(true);
- addRegionToList(m_regionList, renderRegion);
-
- if (m_regionList.first() == renderRegion)
- updateWritingMode();
-}
-
-void RenderNamedFlowThread::addRegionToThread(RenderRegion* renderRegion)
-{
- ASSERT(renderRegion);
- ASSERT(!renderRegion->isValid());
-
- resetMarkForDestruction();
-
- if (renderRegion->parentNamedFlowThread() && renderRegion->parentNamedFlowThread()->dependsOn(this)) {
- // The order of invalid regions is irrelevant.
- m_invalidRegionList.add(renderRegion);
- // Register ourself to get a notification when the state changes.
- renderRegion->parentNamedFlowThread()->m_observerThreadsSet.add(this);
- return;
- }
-
- addRegionToNamedFlowThread(renderRegion);
-
- invalidateRegions();
-}
-
-void RenderNamedFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
-{
- ASSERT(renderRegion);
-
- if (renderRegion->parentNamedFlowThread()) {
- if (!renderRegion->isValid()) {
- ASSERT(m_invalidRegionList.contains(renderRegion));
- m_invalidRegionList.remove(renderRegion);
- 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());
- }
-
- ASSERT(m_regionList.contains(renderRegion));
- bool wasFirst = m_regionList.first() == renderRegion;
- m_regionList.remove(renderRegion);
-
- if (canBeDestroyed())
- setMarkForDestruction();
-
- // After removing all the regions in the flow the following layout needs to dispatch the regionLayoutUpdate event
- if (m_regionList.isEmpty())
- setDispatchRegionLayoutUpdateEvent(true);
- else if (wasFirst)
- updateWritingMode();
-
- invalidateRegions();
-}
-
-void RenderNamedFlowThread::regionChangedWritingMode(RenderRegion* region)
-{
- if (m_regionList.first() == region)
- updateWritingMode();
-}
-
-void RenderNamedFlowThread::computeOversetStateForRegions(LayoutUnit oldClientAfterEdge)
-{
- LayoutUnit height = oldClientAfterEdge;
-
- // FIXME: the visual overflow of middle region (if it is the last one to contain any content in a render flow thread)
- // might not be taken into account because the render flow thread height is greater that that regions height + its visual overflow
- // because of how computeLogicalHeight is implemented for RenderFlowThread (as a sum of all regions height).
- // This means that the middle region will be marked as fit (even if it has visual overflow flowing into the next region)
- if (hasRenderOverflow()
- && ( (isHorizontalWritingMode() && visualOverflowRect().maxY() > clientBoxRect().maxY())
- || (!isHorizontalWritingMode() && visualOverflowRect().maxX() > clientBoxRect().maxX())))
- height = isHorizontalWritingMode() ? visualOverflowRect().maxY() : visualOverflowRect().maxX();
-
- RenderRegion* lastReg = lastRegion();
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x());
- LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().maxY() : region->flowThreadPortionRect().maxX());
- RegionOversetState previousState = region->regionOversetState();
- RegionOversetState state = RegionFit;
- if (flowMin <= 0)
- state = RegionEmpty;
- if (flowMax > 0 && region == lastReg)
- state = RegionOverset;
- region->setRegionOversetState(state);
- // determine whether the NamedFlow object should dispatch a regionLayoutUpdate event
- // FIXME: currently it cannot determine whether a region whose regionOverset state remained either "fit" or "overset" has actually
- // changed, so it just assumes that the NamedFlow should dispatch the event
- if (previousState != state
- || state == RegionFit
- || state == RegionOverset)
- setDispatchRegionLayoutUpdateEvent(true);
-
- if (previousState != state)
- setDispatchRegionOversetChangeEvent(true);
- }
-
- // If the number of regions has changed since we last computed the overset property, schedule the regionOversetChange event.
- if (previousRegionCountChanged()) {
- setDispatchRegionOversetChangeEvent(true);
- updatePreviousRegionCount();
- }
-
- // With the regions overflow state computed we can also set the overset flag for the named flow.
- // If there are no valid regions in the chain, overset is true.
- m_overset = lastReg ? lastReg->regionOversetState() == RegionOverset : true;
-}
-
-void RenderNamedFlowThread::checkInvalidRegions()
-{
- Vector<RenderRegion*> newValidRegions;
- for (RenderRegionList::iterator iter = m_invalidRegionList.begin(); iter != m_invalidRegionList.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->parentNamedFlowThread()->dependsOn(this))
- continue;
-
- newValidRegions.append(region);
- }
-
- for (Vector<RenderRegion*>::iterator iter = newValidRegions.begin(); iter != newValidRegions.end(); ++iter) {
- RenderRegion* region = *iter;
- m_invalidRegionList.remove(region);
- region->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
- addRegionToNamedFlowThread(region);
- }
-
- if (!newValidRegions.isEmpty())
- 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).key;
- if (list.contains(flowThread))
- continue;
- flowThread->pushDependencies(list);
- list.add(flowThread);
- }
-}
-
-// 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());
- ASSERT(contentNode->document() == document());
-
- contentNode->setInNamedFlow();
-
- resetMarkForDestruction();
-
- // 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());
- ASSERT(contentNode->document() == document());
-
- contentNode->clearInNamedFlow();
- m_contentNodes.remove(contentNode);
-
- if (canBeDestroyed())
- setMarkForDestruction();
-}
-
-const AtomicString& RenderNamedFlowThread::flowThreadName() const
-{
- return m_namedFlow->name();
-}
-
-bool RenderNamedFlowThread::isChildAllowed(RenderObject* child, RenderStyle* style) const
-{
- if (!child->node())
- return true;
-
- ASSERT(child->node()->isElementNode());
- Node* originalParent = NodeRenderingTraversal::parent(child->node());
- if (!originalParent || !originalParent->renderer())
- return true;
-
- return originalParent->renderer()->isChildAllowed(child, style);
-}
-
-void RenderNamedFlowThread::dispatchRegionLayoutUpdateEvent()
-{
- RenderFlowThread::dispatchRegionLayoutUpdateEvent();
- InspectorInstrumentation::didUpdateRegionLayout(&document(), m_namedFlow.get());
-
- if (!m_regionLayoutUpdateEventTimer.isActive() && m_namedFlow->hasEventListeners())
- m_regionLayoutUpdateEventTimer.startOneShot(0);
-}
-
-void RenderNamedFlowThread::dispatchRegionOversetChangeEvent()
-{
- RenderFlowThread::dispatchRegionOversetChangeEvent();
- InspectorInstrumentation::didChangeRegionOverset(&document(), m_namedFlow.get());
-
- if (!m_regionOversetChangeEventTimer.isActive() && m_namedFlow->hasEventListeners())
- m_regionOversetChangeEventTimer.startOneShot(0);
-}
-
-void RenderNamedFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*)
-{
- ASSERT(m_namedFlow);
-
- m_namedFlow->dispatchRegionLayoutUpdateEvent();
-}
-
-void RenderNamedFlowThread::regionOversetChangeEventTimerFired(Timer<RenderNamedFlowThread>*)
-{
- ASSERT(m_namedFlow);
-
- m_namedFlow->dispatchRegionOversetChangeEvent();
-}
-
-void RenderNamedFlowThread::setMarkForDestruction()
-{
- if (m_namedFlow->flowState() == NamedFlow::FlowStateNull)
- return;
-
- m_namedFlow->setRenderer(0);
- // After this call ends, the renderer can be safely destroyed.
- // The NamedFlow object may outlive its renderer if it's referenced from a script and may be reatached to one if the named flow is recreated in the stylesheet.
-}
-
-void RenderNamedFlowThread::resetMarkForDestruction()
-{
- if (m_namedFlow->flowState() == NamedFlow::FlowStateCreated)
- return;
-
- m_namedFlow->setRenderer(this);
-}
-
-bool RenderNamedFlowThread::isMarkedForDestruction() const
-{
- // Flow threads in the "NULL" state can be destroyed.
- return m_namedFlow->flowState() == NamedFlow::FlowStateNull;
-}
-
-static bool isContainedInNodes(Vector<Node*> others, Node* node)
-{
- for (size_t i = 0; i < others.size(); i++) {
- Node* other = others.at(i);
- if (other->contains(node))
- return true;
- }
- return false;
-}
-
-static bool boxIntersectsRegion(LayoutUnit logicalTopForBox, LayoutUnit logicalBottomForBox, LayoutUnit logicalTopForRegion, LayoutUnit logicalBottomForRegion)
-{
- bool regionIsEmpty = logicalBottomForRegion != LayoutUnit::max() && logicalTopForRegion != LayoutUnit::min()
- && (logicalBottomForRegion - logicalTopForRegion) <= 0;
- return (logicalBottomForBox - logicalTopForBox) > 0
- && !regionIsEmpty
- && logicalTopForBox < logicalBottomForRegion && logicalTopForRegion < logicalBottomForBox;
-}
-
-// Retrieve the next node to be visited while computing the ranges inside a region.
-static Node* nextNodeInsideContentNode(const Node& currNode, const Node* contentNode)
-{
- ASSERT(contentNode && contentNode->inNamedFlow());
-
- if (currNode.renderer() && currNode.renderer()->isSVGRoot())
- return NodeTraversal::nextSkippingChildren(currNode, contentNode);
- return NodeTraversal::next(currNode, contentNode);
-}
-
-void RenderNamedFlowThread::getRanges(Vector<RefPtr<Range> >& rangeObjects, const RenderRegion* region) const
-{
- LayoutUnit logicalTopForRegion;
- LayoutUnit logicalBottomForRegion;
-
- // extend the first region top to contain everything up to its logical height
- if (region->isFirstRegion())
- logicalTopForRegion = LayoutUnit::min();
- else
- logicalTopForRegion = region->logicalTopForFlowThreadContent();
-
- // extend the last region to contain everything above its y()
- if (region->isLastRegion())
- logicalBottomForRegion = LayoutUnit::max();
- else
- logicalBottomForRegion = region->logicalBottomForFlowThreadContent();
-
- Vector<Node*> nodes;
- // eliminate the contentNodes that are descendants of other contentNodes
- for (NamedFlowContentNodes::const_iterator it = contentNodes().begin(); it != contentNodes().end(); ++it) {
- Node* node = *it;
- if (!isContainedInNodes(nodes, node))
- nodes.append(node);
- }
-
- for (size_t i = 0; i < nodes.size(); i++) {
- Node* contentNode = nodes.at(i);
- if (!contentNode->renderer())
- continue;
-
- RefPtr<Range> range = Range::create(contentNode->document());
- bool foundStartPosition = false;
- bool startsAboveRegion = true;
- bool endsBelowRegion = true;
- bool skipOverOutsideNodes = false;
- Node* lastEndNode = 0;
-
- for (Node* node = contentNode; node; node = nextNodeInsideContentNode(*node, contentNode)) {
- RenderObject* renderer = node->renderer();
- if (!renderer)
- continue;
-
- LayoutRect boundingBox;
- if (renderer->isRenderInline()) {
- boundingBox = toRenderInline(renderer)->linesBoundingBox();
- } else if (renderer->isText()) {
- boundingBox = toRenderText(renderer)->linesBoundingBox();
- } else {
- boundingBox = toRenderBox(renderer)->frameRect();
- if (toRenderBox(renderer)->isRelPositioned())
- boundingBox.move(toRenderBox(renderer)->relativePositionLogicalOffset());
- }
-
- LayoutUnit offsetTop = renderer->containingBlock()->offsetFromLogicalTopOfFirstPage();
- const LayoutPoint logicalOffsetFromTop(isHorizontalWritingMode() ? LayoutUnit() : offsetTop,
- isHorizontalWritingMode() ? offsetTop : LayoutUnit());
-
- boundingBox.moveBy(logicalOffsetFromTop);
-
- LayoutUnit logicalTopForRenderer = region->logicalTopOfFlowThreadContentRect(boundingBox);
- LayoutUnit logicalBottomForRenderer = region->logicalBottomOfFlowThreadContentRect(boundingBox);
-
- // if the bounding box of the current element doesn't intersect the region box
- // close the current range only if the start element began inside the region,
- // otherwise just move the start position after this node and keep skipping them until we found a proper start position.
- if (!boxIntersectsRegion(logicalTopForRenderer, logicalBottomForRenderer, logicalTopForRegion, logicalBottomForRegion)) {
- if (foundStartPosition) {
- if (!startsAboveRegion) {
- if (range->intersectsNode(node, IGNORE_EXCEPTION))
- range->setEndBefore(node, IGNORE_EXCEPTION);
- rangeObjects.append(range->cloneRange(IGNORE_EXCEPTION));
- range = Range::create(contentNode->document());
- startsAboveRegion = true;
- } else {
- skipOverOutsideNodes = true;
- }
- }
- if (skipOverOutsideNodes)
- range->setStartAfter(node, IGNORE_EXCEPTION);
- foundStartPosition = false;
- continue;
- }
-
- // start position
- if (logicalTopForRenderer < logicalTopForRegion && startsAboveRegion) {
- if (renderer->isText()) { // Text crosses region top
- // for Text elements, just find the last textbox that is contained inside the region and use its start() offset as start position
- RenderText* textRenderer = toRenderText(renderer);
- for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if (offsetTop + box->logicalBottom() < logicalTopForRegion)
- continue;
- range->setStart(Position(toText(node), box->start()));
- startsAboveRegion = false;
- break;
- }
- } else { // node crosses region top
- // for all elements, except Text, just set the start position to be before their children
- startsAboveRegion = true;
- range->setStart(Position(node, Position::PositionIsBeforeChildren));
- }
- } else { // node starts inside region
- // for elements that start inside the region, set the start position to be before them. If we found one, we will just skip the others until
- // the range is closed.
- if (startsAboveRegion) {
- startsAboveRegion = false;
- range->setStartBefore(node, IGNORE_EXCEPTION);
- }
- }
- skipOverOutsideNodes = false;
- foundStartPosition = true;
-
- // end position
- if (logicalBottomForRegion < logicalBottomForRenderer && (endsBelowRegion || (!endsBelowRegion && !node->isDescendantOf(lastEndNode)))) {
- // for Text elements, just find just find the last textbox that is contained inside the region and use its start()+len() offset as end position
- if (renderer->isText()) { // Text crosses region bottom
- RenderText* textRenderer = toRenderText(renderer);
- InlineTextBox* lastBox = 0;
- for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if ((offsetTop + box->logicalTop()) < logicalBottomForRegion) {
- lastBox = box;
- continue;
- }
- ASSERT(lastBox);
- if (lastBox)
- range->setEnd(Position(toText(node), lastBox->start() + lastBox->len()));
- break;
- }
- endsBelowRegion = false;
- lastEndNode = node;
- } else { // node crosses region bottom
- // for all elements, except Text, just set the start position to be after their children
- range->setEnd(Position(node, Position::PositionIsAfterChildren));
- endsBelowRegion = true;
- lastEndNode = node;
- }
- } else { // node ends inside region
- // for elements that ends inside the region, set the end position to be after them
- // allow this end position to be changed only by other elements that are not descendants of the current end node
- if (endsBelowRegion || (!endsBelowRegion && !node->isDescendantOf(lastEndNode))) {
- range->setEndAfter(node, IGNORE_EXCEPTION);
- endsBelowRegion = false;
- lastEndNode = node;
- }
- }
- }
- if (foundStartPosition || skipOverOutsideNodes)
- rangeObjects.append(range);
- }
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.h b/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.h
deleted file mode 100644
index 6528c1106c5..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderNamedFlowThread.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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 "core/rendering/RenderFlowThread.h"
-#include "platform/Timer.h"
-#include "wtf/HashCountedSet.h"
-#include "wtf/ListHashSet.h"
-#include "wtf/text/AtomicString.h"
-
-namespace WebCore {
-
-class NamedFlow;
-class Node;
-class RenderNamedFlowThread;
-
-typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
-typedef HashCountedSet<RenderNamedFlowThread*> RenderNamedFlowThreadCountedSet;
-typedef ListHashSet<Node*> NamedFlowContentNodes;
-
-class RenderNamedFlowThread FINAL : public RenderFlowThread {
-public:
- virtual ~RenderNamedFlowThread();
-
- static RenderNamedFlowThread* createAnonymous(Document*, PassRefPtr<NamedFlow>);
-
- const AtomicString& flowThreadName() const;
-
- const RenderRegionList& invalidRenderRegionList() const { return m_invalidRegionList; }
-
- RenderObject* nextRendererForNode(Node*) const;
- RenderObject* previousRendererForNode(Node*) const;
-
- void addFlowChild(RenderObject* newChild);
- 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;
-
- virtual void regionChangedWritingMode(RenderRegion*) OVERRIDE;
-
- bool overset() const { return m_overset; }
- void computeOversetStateForRegions(LayoutUnit oldClientAfterEdge);
-
- 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); }
- bool isMarkedForDestruction() const;
- void getRanges(Vector<RefPtr<Range> >&, const RenderRegion*) const;
-
-protected:
- void setMarkForDestruction();
- void resetMarkForDestruction();
-
-private:
- RenderNamedFlowThread(PassRefPtr<NamedFlow>);
-
- virtual const char* renderName() const OVERRIDE;
- virtual bool isRenderNamedFlowThread() const OVERRIDE { return true; }
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
-
- virtual void dispatchRegionLayoutUpdateEvent() OVERRIDE;
- virtual void dispatchRegionOversetChangeEvent() OVERRIDE;
-
- bool dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const;
- void addDependencyOnFlowThread(RenderNamedFlowThread*);
- void removeDependencyOnFlowThread(RenderNamedFlowThread*);
-
- void addRegionToNamedFlowThread(RenderRegion*);
-
- void checkInvalidRegions();
-
- bool canBeDestroyed() const { return m_invalidRegionList.isEmpty() && m_regionList.isEmpty() && m_contentNodes.isEmpty(); }
- void regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*);
- void regionOversetChangeEventTimerFired(Timer<RenderNamedFlowThread>*);
- void clearContentNodes();
- void updateWritingMode();
-
-private:
- // 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;
-
- RenderRegionList m_invalidRegionList;
-
- bool m_overset : 1;
-
- // The DOM Object that represents a named flow.
- RefPtr<NamedFlow> m_namedFlow;
-
- Timer<RenderNamedFlowThread> m_regionLayoutUpdateEventTimer;
- Timer<RenderNamedFlowThread> m_regionOversetChangeEventTimer;
-};
-
-DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderNamedFlowThread, isRenderNamedFlowThread());
-
-} // namespace WebCore
-
-#endif // RenderNamedFlowThread_h
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderObject.cpp
index 1192be3d768..90af71bf364 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderObject.cpp
@@ -27,48 +27,43 @@
#include "config.h"
#include "core/rendering/RenderObject.h"
-#include "HTMLNames.h"
-#include "RuntimeEnabledFeatures.h"
+#include "core/HTMLNames.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/animation/ActiveAnimations.h"
#include "core/css/resolver/StyleResolver.h"
+#include "core/dom/ElementTraversal.h"
+#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/EditingBoundary.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/htmlediting.h"
+#include "core/fetch/ResourceLoadPriorityOptimizer.h"
#include "core/fetch/ResourceLoader.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLHtmlElement.h"
+#include "core/html/HTMLTableCellElement.h"
#include "core/html/HTMLTableElement.h"
#include "core/page/AutoscrollController.h"
#include "core/page/EventHandler.h"
-#include "core/frame/Frame.h"
-#include "core/frame/FrameView.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
-#include "core/frame/animation/AnimationController.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/FlowThreadController.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderCounter.h"
#include "core/rendering/RenderDeprecatedFlexibleBox.h"
#include "core/rendering/RenderFlexibleBox.h"
+#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderGrid.h"
#include "core/rendering/RenderImage.h"
#include "core/rendering/RenderImageResourceStyleImage.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerCompositor.h"
#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderMarquee.h"
-#include "core/rendering/RenderMultiColumnBlock.h"
-#include "core/rendering/RenderNamedFlowThread.h"
-#include "core/rendering/RenderRegion.h"
-#include "core/rendering/RenderRuby.h"
-#include "core/rendering/RenderRubyText.h"
#include "core/rendering/RenderScrollbarPart.h"
#include "core/rendering/RenderTableCaption.h"
#include "core/rendering/RenderTableCell.h"
@@ -76,15 +71,20 @@
#include "core/rendering/RenderTableRow.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "core/rendering/style/ContentData.h"
-#include "core/rendering/style/CursorList.h"
#include "core/rendering/style/ShadowList.h"
-#include "core/rendering/svg/SVGRenderSupport.h"
+#include "platform/JSONValues.h"
#include "platform/Partitions.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/TraceEvent.h"
+#include "platform/TracedValue.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/GraphicsContext.h"
#include "wtf/RefCountedLeakCounter.h"
#include "wtf/text/StringBuilder.h"
+#include "wtf/text/WTFString.h"
#include <algorithm>
#ifndef NDEBUG
#include <stdio.h>
@@ -94,20 +94,26 @@ using namespace std;
namespace WebCore {
+namespace {
+
+static bool gModifyRenderTreeStructureAnyState = false;
+
+} // namespace
+
using namespace HTMLNames;
#ifndef NDEBUG
-RenderObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(RenderObject* renderObject)
+RenderObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(RenderObject& renderObject)
: m_renderObject(renderObject)
- , m_preexistingForbidden(m_renderObject->isSetNeedsLayoutForbidden())
+ , m_preexistingForbidden(m_renderObject.isSetNeedsLayoutForbidden())
{
- m_renderObject->setNeedsLayoutIsForbidden(true);
+ m_renderObject.setNeedsLayoutIsForbidden(true);
}
RenderObject::SetLayoutNeededForbiddenScope::~SetLayoutNeededForbiddenScope()
{
- m_renderObject->setNeedsLayoutIsForbidden(m_preexistingForbidden);
+ m_renderObject.setNeedsLayoutIsForbidden(m_preexistingForbidden);
}
#endif
@@ -119,7 +125,8 @@ struct SameSizeAsRenderObject {
#endif
unsigned m_bitfields;
unsigned m_bitfields2;
- LayoutRect rects[2]; // Stores the old/new repaint rects.
+ LayoutRect rect; // Stores the previous paint invalidation rect.
+ LayoutPoint position; // Stores the previous position from the paint invalidation container.
};
COMPILE_ASSERT(sizeof(RenderObject) == sizeof(SameSizeAsRenderObject), RenderObject_should_stay_small);
@@ -140,7 +147,7 @@ void RenderObject::operator delete(void* ptr)
RenderObject* RenderObject::createObject(Element* element, RenderStyle* style)
{
- Document& doc = element->document();
+ ASSERT(isAllowedToModifyRenderTreeStructure(element->document()));
// Minimal support for content properties replacing an entire element.
// Works only if we have exactly one piece of content and it's a URL.
@@ -157,20 +164,10 @@ RenderObject* RenderObject::createObject(Element* element, RenderStyle* style)
image->setIsGeneratedContent();
} else
image->setImageResource(RenderImageResource::create());
- image->setStyleInternal(0);
+ image->setStyleInternal(nullptr);
return image;
}
- if (element->hasTagName(rubyTag)) {
- if (style->display() == INLINE)
- return new RenderRubyAsInline(element);
- else if (style->display() == BLOCK)
- return new RenderRubyAsBlock(element);
- }
- // treat <rt> as ruby text ONLY if it still has its default treatment of block
- if (element->hasTagName(rtTag) && style->display() == BLOCK)
- return new RenderRubyText(element);
-
switch (style->display()) {
case NONE:
return 0;
@@ -178,8 +175,6 @@ RenderObject* RenderObject::createObject(Element* element, RenderStyle* style)
return new RenderInline(element);
case BLOCK:
case INLINE_BLOCK:
- if ((!style->hasAutoColumnCount() || !style->hasAutoColumnWidth()) && doc.regionBasedColumnsEnabled())
- return new RenderMultiColumnBlock(element);
return new RenderBlockFlow(element);
case LIST_ITEM:
return new RenderListItem(element);
@@ -217,7 +212,7 @@ DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, renderObjectCounter, ("Rend
RenderObject::RenderObject(Node* node)
: ImageResourceClient()
- , m_style(0)
+ , m_style(nullptr)
, m_node(node)
, m_parent(0)
, m_previous(0)
@@ -235,6 +230,7 @@ RenderObject::RenderObject(Node* node)
RenderObject::~RenderObject()
{
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->removeRenderObject(this);
#ifndef NDEBUG
ASSERT(!m_hasAXObject);
renderObjectCounter.decrement();
@@ -263,31 +259,24 @@ bool RenderObject::isDescendantOf(const RenderObject* obj) const
return false;
}
-bool RenderObject::isBody() const
-{
- return node() && node()->hasTagName(bodyTag);
-}
-
bool RenderObject::isHR() const
{
- return node() && node()->hasTagName(hrTag);
+ return isHTMLHRElement(node());
}
bool RenderObject::isLegend() const
{
- return node() && node()->hasTagName(legendTag);
+ return isHTMLLegendElement(node());
}
void RenderObject::setFlowThreadStateIncludingDescendants(FlowThreadState state)
{
- setFlowThreadState(state);
-
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- // If the child is a fragmentation context it already updated the descendants flag accordingly.
- if (child->isRenderFlowThread())
+ for (RenderObject *object = this; object; object = object->nextInPreOrder(this)) {
+ // If object is a fragmentation context it already updated the descendants flag accordingly.
+ if (object->isRenderFlowThread())
continue;
- ASSERT(state != child->flowThreadState());
- child->setFlowThreadStateIncludingDescendants(state);
+ ASSERT(state != object->flowThreadState());
+ object->setFlowThreadState(state);
}
}
@@ -313,6 +302,8 @@ bool RenderObject::requiresAnonymousTableWrappers(const RenderObject* newChild)
void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
+ ASSERT(isAllowedToModifyRenderTreeStructure(document()));
+
RenderObjectChildList* children = virtualChildren();
ASSERT(children);
if (!children)
@@ -340,7 +331,7 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
// SVG creates renderers for <g display="none">, as SVG requires children of hidden
// <g>s to have renderers - at least that's how our implementation works. Consider:
// <g display="none"><foreignObject><body style="position: relative">FOO...
- // - requiresLayer() would return true for the <body>, creating a new RenderLayer
+ // - layerTypeRequired() would return true for the <body>, creating a new RenderLayer
// - when the document is painted, both layers are painted. The <body> layer doesn't
// know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't.
// To avoid the problem alltogether, detect early if we're inside a hidden SVG subtree
@@ -351,6 +342,8 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
void RenderObject::removeChild(RenderObject* oldChild)
{
+ ASSERT(isAllowedToModifyRenderTreeStructure(document()));
+
RenderObjectChildList* children = virtualChildren();
ASSERT(children);
if (!children)
@@ -361,7 +354,7 @@ void RenderObject::removeChild(RenderObject* oldChild)
RenderObject* RenderObject::nextInPreOrder() const
{
- if (RenderObject* o = firstChild())
+ if (RenderObject* o = slowFirstChild())
return o;
return nextInPreOrderAfterChildren();
@@ -383,7 +376,7 @@ RenderObject* RenderObject::nextInPreOrderAfterChildren() const
RenderObject* RenderObject::nextInPreOrder(const RenderObject* stayWithin) const
{
- if (RenderObject* o = firstChild())
+ if (RenderObject* o = slowFirstChild())
return o;
return nextInPreOrderAfterChildren(stayWithin);
@@ -407,8 +400,8 @@ RenderObject* RenderObject::nextInPreOrderAfterChildren(const RenderObject* stay
RenderObject* RenderObject::previousInPreOrder() const
{
if (RenderObject* o = previousSibling()) {
- while (o->lastChild())
- o = o->lastChild();
+ while (RenderObject* lastChild = o->slowLastChild())
+ o = lastChild;
return o;
}
@@ -425,7 +418,7 @@ RenderObject* RenderObject::previousInPreOrder(const RenderObject* stayWithin) c
RenderObject* RenderObject::childAt(unsigned index) const
{
- RenderObject* child = firstChild();
+ RenderObject* child = slowFirstChild();
for (unsigned i = 0; child && i < index; i++)
child = child->nextSibling();
return child;
@@ -433,10 +426,10 @@ RenderObject* RenderObject::childAt(unsigned index) const
RenderObject* RenderObject::lastLeafChild() const
{
- RenderObject* r = lastChild();
+ RenderObject* r = slowLastChild();
while (r) {
RenderObject* n = 0;
- n = r->lastChild();
+ n = r->slowLastChild();
if (!n)
break;
r = n;
@@ -459,7 +452,7 @@ static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*
return;
}
- for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
+ for (RenderObject* curr = obj->slowFirstChild(); curr; curr = curr->nextSibling())
addLayers(curr, parentLayer, newObject, beforeChild);
}
@@ -483,7 +476,7 @@ void RenderObject::removeLayers(RenderLayer* parentLayer)
return;
}
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling())
curr->removeLayers(parentLayer);
}
@@ -501,7 +494,7 @@ void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
return;
}
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling())
curr->moveLayers(oldParent, newParent);
}
@@ -520,7 +513,7 @@ RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject*
// Step 2: If we don't have a layer, or our layer is the desired parent, then descend
// into our siblings trying to find the next layer whose parent is the desired parent.
if (!ourLayer || ourLayer == parentLayer) {
- for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
+ for (RenderObject* curr = startPoint ? startPoint->nextSibling() : slowFirstChild();
curr; curr = curr->nextSibling()) {
RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
if (nextLayer)
@@ -543,13 +536,13 @@ RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject*
RenderLayer* RenderObject::enclosingLayer() const
{
- const RenderObject* curr = this;
- while (curr) {
- RenderLayer* layer = curr->hasLayer() ? toRenderLayerModelObject(curr)->layer() : 0;
- if (layer)
- return layer;
- curr = curr->parent();
+ for (const RenderObject* current = this; current; current = current->parent()) {
+ if (current->hasLayer())
+ return toRenderLayerModelObject(current)->layer();
}
+ // FIXME: We should remove the one caller that triggers this case and make
+ // this function return a reference.
+ ASSERT(!m_parent && !isRenderView());
return 0;
}
@@ -622,15 +615,6 @@ RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
return 0;
}
-RenderNamedFlowThread* RenderObject::renderNamedFlowThreadWrapper() const
-{
- RenderObject* object = const_cast<RenderObject*>(this);
- while (object && object->isAnonymousBlock() && !object->isRenderNamedFlowThread())
- object = object->parent();
-
- return object && object->isRenderNamedFlowThread() ? toRenderNamedFlowThread(object) : 0;
-}
-
RenderBlock* RenderObject::firstLineBlock() const
{
return 0;
@@ -729,19 +713,12 @@ void RenderObject::checkBlockPositionedObjectsNeedLayout()
if (isRenderBlock())
toRenderBlock(this)->checkPositionedObjectsNeedLayout();
}
-
-void RenderObject::checkNotInPartialLayout()
-{
- // During partial layout, setNeedsLayout(true or false) should not be called.
- ASSERT(!frameView()->partialLayout().isStopping());
-}
#endif
void RenderObject::setPreferredLogicalWidthsDirty(MarkingBehavior markParents)
{
- bool alreadyDirty = preferredLogicalWidthsDirty();
m_bitfields.setPreferredLogicalWidthsDirty(true);
- if (!alreadyDirty && markParents == MarkContainingBlockChain && (isText() || !style()->hasOutOfFlowPosition()))
+ if (markParents == MarkContainingBlockChain && (isText() || !style()->hasOutOfFlowPosition()))
invalidateContainerPreferredLogicalWidths();
}
@@ -771,28 +748,22 @@ void RenderObject::invalidateContainerPreferredLogicalWidths()
}
}
-void RenderObject::setLayerNeedsFullRepaint()
-{
- ASSERT(hasLayer());
- toRenderLayerModelObject(this)->layer()->repainter().setRepaintStatus(NeedsFullRepaint);
-}
-
-void RenderObject::setLayerNeedsFullRepaintForPositionedMovementLayout()
+void RenderObject::setLayerNeedsFullPaintInvalidationForPositionedMovementLayout()
{
ASSERT(hasLayer());
toRenderLayerModelObject(this)->layer()->repainter().setRepaintStatus(NeedsFullRepaintForPositionedMovementLayout);
}
-RenderBlock* RenderObject::containerForFixedPosition(const RenderLayerModelObject* repaintContainer, bool* repaintContainerSkipped) const
+RenderBlock* RenderObject::containerForFixedPosition(const RenderLayerModelObject* paintInvalidationContainer, bool* paintInvalidationContainerSkipped) const
{
- ASSERT(!repaintContainerSkipped || !*repaintContainerSkipped);
+ ASSERT(!paintInvalidationContainerSkipped || !*paintInvalidationContainerSkipped);
ASSERT(!isText());
ASSERT(style()->position() == FixedPosition);
RenderObject* ancestor = parent();
for (; ancestor && !ancestor->canContainFixedPositionObjects(); ancestor = ancestor->parent()) {
- if (repaintContainerSkipped && ancestor == repaintContainer)
- *repaintContainerSkipped = true;
+ if (paintInvalidationContainerSkipped && ancestor == paintInvalidationContainer)
+ *paintInvalidationContainerSkipped = true;
}
ASSERT(!ancestor || !ancestor->isAnonymousBlock());
@@ -816,7 +787,7 @@ RenderBlock* RenderObject::containingBlock() const
if (o->style()->position() != StaticPosition && (!o->isInline() || o->isReplaced()))
break;
- if (o->canContainAbsolutePositionObjects())
+ if (o->canContainFixedPositionObjects())
break;
if (o->style()->hasInFlowPosition() && o->isInline() && !o->isReplaced()) {
@@ -827,6 +798,9 @@ RenderBlock* RenderObject::containingBlock() const
o = o->parent();
}
+ if (o && !o->isRenderBlock())
+ o = o->containingBlock();
+
while (o && o->isAnonymousBlock())
o = o->containingBlock();
} else {
@@ -840,29 +814,66 @@ RenderBlock* RenderObject::containingBlock() const
return toRenderBlock(o);
}
-static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer* layer)
+RenderObject* RenderObject::clippingContainer() const
+{
+ RenderObject* container = const_cast<RenderObject*>(this);
+ while (container) {
+ if (container->style()->position() == FixedPosition) {
+ for (container = container->parent(); container && !container->canContainFixedPositionObjects(); container = container->parent()) {
+ // CSS clip applies to fixed position elements even for ancestors that are not what the
+ // fixed element is positioned with respect to.
+ if (container->hasClip())
+ return container;
+ }
+ } else {
+ container = container->containingBlock();
+ }
+
+ if (!container)
+ return 0;
+ if (container->hasClipOrOverflowClip())
+ return container;
+ }
+ return 0;
+}
+
+bool RenderObject::canRenderBorderImage() const
+{
+ ASSERT(style()->hasBorder());
+
+ StyleImage* borderImage = style()->borderImage().image();
+ return borderImage && borderImage->canRender(*this, style()->effectiveZoom()) && borderImage->isLoaded();
+}
+
+bool RenderObject::mustInvalidateFillLayersPaintOnWidthChange(const FillLayer& layer) const
{
// Nobody will use multiple layers without wanting fancy positioning.
- if (layer->next())
+ if (layer.next())
return true;
// Make sure we have a valid image.
- StyleImage* img = layer->image();
- if (!img || !img->canRender(renderer, renderer->style()->effectiveZoom()))
+ StyleImage* img = layer.image();
+ if (!img || !img->canRender(*this, style()->effectiveZoom()))
return false;
- if (!layer->xPosition().isZero() || !layer->yPosition().isZero())
+ if (layer.repeatX() != RepeatFill && layer.repeatX() != NoRepeatFill)
return true;
- EFillSizeType sizeType = layer->sizeType();
+ if (layer.xPosition().isPercent() && !layer.xPosition().isZero())
+ return true;
+
+ if (layer.backgroundXOrigin() != LeftEdge)
+ return true;
+
+ EFillSizeType sizeType = layer.sizeType();
if (sizeType == Contain || sizeType == Cover)
return true;
if (sizeType == SizeLength) {
- if (layer->sizeLength().width().isPercent() || layer->sizeLength().height().isPercent())
+ if (layer.sizeLength().width().isPercent() && !layer.sizeLength().width().isZero())
return true;
- if (img->isGeneratedImage() && (layer->sizeLength().width().isAuto() || layer->sizeLength().height().isAuto()))
+ if (img->isGeneratedImage() && layer.sizeLength().width().isAuto())
return true;
} else if (img->usesImageContainerSize()) {
return true;
@@ -871,28 +882,76 @@ static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer*
return false;
}
-bool RenderObject::borderImageIsLoadedAndCanBeRendered() const
+bool RenderObject::mustInvalidateFillLayersPaintOnHeightChange(const FillLayer& layer) const
{
- ASSERT(style()->hasBorder());
+ // Nobody will use multiple layers without wanting fancy positioning.
+ if (layer.next())
+ return true;
- StyleImage* borderImage = style()->borderImage().image();
- return borderImage && borderImage->canRender(this, style()->effectiveZoom()) && borderImage->isLoaded();
+ // Make sure we have a valid image.
+ StyleImage* img = layer.image();
+ if (!img || !img->canRender(*this, style()->effectiveZoom()))
+ return false;
+
+ if (layer.repeatY() != RepeatFill && layer.repeatY() != NoRepeatFill)
+ return true;
+
+ if (layer.yPosition().isPercent() && !layer.yPosition().isZero())
+ return true;
+
+ if (layer.backgroundYOrigin() != TopEdge)
+ return true;
+
+ EFillSizeType sizeType = layer.sizeType();
+
+ if (sizeType == Contain || sizeType == Cover)
+ return true;
+
+ if (sizeType == SizeLength) {
+ if (layer.sizeLength().height().isPercent() && !layer.sizeLength().height().isZero())
+ return true;
+ if (img->isGeneratedImage() && layer.sizeLength().height().isAuto())
+ return true;
+ } else if (img->usesImageContainerSize()) {
+ return true;
+ }
+
+ return false;
}
-bool RenderObject::mustRepaintBackgroundOrBorder() const
+bool RenderObject::mustInvalidateBackgroundOrBorderPaintOnWidthChange() const
{
- if (hasMask() && mustRepaintFillLayers(this, style()->maskLayers()))
+ if (hasMask() && mustInvalidateFillLayersPaintOnWidthChange(*style()->maskLayers()))
return true;
// If we don't have a background/border/mask, then nothing to do.
if (!hasBoxDecorations())
return false;
- if (mustRepaintFillLayers(this, style()->backgroundLayers()))
+ if (mustInvalidateFillLayersPaintOnWidthChange(*style()->backgroundLayers()))
+ return true;
+
+ // Our fill layers are ok. Let's check border.
+ if (style()->hasBorder() && canRenderBorderImage())
+ return true;
+
+ return false;
+}
+
+bool RenderObject::mustInvalidateBackgroundOrBorderPaintOnHeightChange() const
+{
+ if (hasMask() && mustInvalidateFillLayersPaintOnHeightChange(*style()->maskLayers()))
+ return true;
+
+ // If we don't have a background/border/mask, then nothing to do.
+ if (!hasBoxDecorations())
+ return false;
+
+ if (mustInvalidateFillLayersPaintOnHeightChange(*style()->backgroundLayers()))
return true;
// Our fill layers are ok. Let's check border.
- if (style()->hasBorder() && borderImageIsLoadedAndCanBeRendered())
+ if (style()->hasBorder() && canRenderBorderImage())
return true;
return false;
@@ -1250,22 +1309,62 @@ void RenderObject::paintOutline(PaintInfo& paintInfo, const LayoutRect& paintRec
graphicsContext->endLayer();
}
-IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms) const
+void RenderObject::addChildFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
{
- if (useTransforms) {
- Vector<FloatQuad> quads;
- absoluteQuads(quads);
-
- size_t n = quads.size();
- if (!n)
- return IntRect();
+ for (RenderObject* current = slowFirstChild(); current; current = current->nextSibling()) {
+ if (current->isText() || current->isListMarker())
+ continue;
- IntRect result = quads[0].enclosingBoundingBox();
- for (size_t i = 1; i < n; ++i)
- result.unite(quads[i].enclosingBoundingBox());
- return result;
+ if (current->isBox()) {
+ RenderBox* box = toRenderBox(current);
+ if (box->hasLayer()) {
+ Vector<IntRect> layerFocusRingRects;
+ box->addFocusRingRects(layerFocusRingRects, LayoutPoint(), box);
+ for (size_t i = 0; i < layerFocusRingRects.size(); ++i) {
+ FloatQuad quadInBox = box->localToContainerQuad(FloatRect(layerFocusRingRects[i]), paintContainer);
+ rects.append(pixelSnappedIntRect(LayoutRect(quadInBox.boundingBox())));
+ }
+ } else {
+ FloatPoint pos(additionalOffset);
+ pos.move(box->locationOffset()); // FIXME: Snap offsets? crbug.com/350474
+ box->addFocusRingRects(rects, flooredIntPoint(pos), paintContainer);
+ }
+ } else {
+ current->addFocusRingRects(rects, additionalOffset, paintContainer);
+ }
}
+}
+
+// FIXME: In repaint-after-layout, we should be able to change the logic to remove the need for this function. See crbug.com/368416.
+LayoutPoint RenderObject::positionFromPaintInvalidationContainer(const RenderLayerModelObject* paintInvalidationContainer) const
+{
+ // FIXME: This assert should be re-enabled when we move paint invalidation to after compositing update. crbug.com/360286
+ // ASSERT(containerForPaintInvalidation() == paintInvalidationContainer);
+
+ LayoutPoint offset = isBox() ? toRenderBox(this)->location() : LayoutPoint();
+ if (paintInvalidationContainer == this)
+ return offset;
+
+ return roundedIntPoint(localToContainerPoint(offset, paintInvalidationContainer));
+}
+
+IntRect RenderObject::absoluteBoundingBoxRect() const
+{
+ Vector<FloatQuad> quads;
+ absoluteQuads(quads);
+ size_t n = quads.size();
+ if (!n)
+ return IntRect();
+
+ IntRect result = quads[0].enclosingBoundingBox();
+ for (size_t i = 1; i < n; ++i)
+ result.unite(quads[i].enclosingBoundingBox());
+ return result;
+}
+
+IntRect RenderObject::absoluteBoundingBoxRectIgnoringTransforms() const
+{
FloatPoint absPos = localToAbsolute();
Vector<IntRect> rects;
absoluteRects(rects, flooredLayoutPoint(absPos));
@@ -1283,18 +1382,11 @@ IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms) const
void RenderObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
{
Vector<IntRect> rects;
- // FIXME: addFocusRingRects() needs to be passed this transform-unaware
- // localToAbsolute() offset here because RenderInline::addFocusRingRects()
- // implicitly assumes that. This doesn't work correctly with transformed
- // descendants.
- FloatPoint absolutePoint = localToAbsolute();
- addFocusRingRects(rects, flooredLayoutPoint(absolutePoint));
+ const RenderLayerModelObject* container = containerForPaintInvalidation();
+ addFocusRingRects(rects, LayoutPoint(localToContainerPoint(FloatPoint(), container)), container);
size_t count = rects.size();
- for (size_t i = 0; i < count; ++i) {
- IntRect rect = rects[i];
- rect.move(-absolutePoint.x(), -absolutePoint.y());
- quads.append(localToAbsoluteQuad(FloatQuad(rect)));
- }
+ for (size_t i = 0; i < count; ++i)
+ quads.append(container->localToAbsoluteQuad(FloatQuad(rects[i])));
}
FloatRect RenderObject::absoluteBoundingBoxRectForRange(const Range* range)
@@ -1317,16 +1409,16 @@ FloatRect RenderObject::absoluteBoundingBoxRectForRange(const Range* range)
void RenderObject::addAbsoluteRectForLayer(LayoutRect& result)
{
if (hasLayer())
- result.unite(absoluteBoundingBoxRectIgnoringTransforms());
- for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+ result.unite(absoluteBoundingBoxRect());
+ for (RenderObject* current = slowFirstChild(); current; current = current->nextSibling())
current->addAbsoluteRectForLayer(result);
}
LayoutRect RenderObject::paintingRootRect(LayoutRect& topLevelRect)
{
- LayoutRect result = absoluteBoundingBoxRectIgnoringTransforms();
+ LayoutRect result = absoluteBoundingBoxRect();
topLevelRect = result;
- for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+ for (RenderObject* current = slowFirstChild(); current; current = current->nextSibling())
current->addAbsoluteRectForLayer(result);
return result;
}
@@ -1335,145 +1427,157 @@ void RenderObject::paint(PaintInfo&, const LayoutPoint&)
{
}
-RenderLayerModelObject* RenderObject::containerForRepaint() const
+const RenderLayerModelObject* RenderObject::containerForPaintInvalidation() const
{
- RenderView* v = view();
- if (!v)
+ if (!isRooted())
return 0;
- RenderLayerModelObject* repaintContainer = 0;
+ return adjustCompositedContainerForSpecialAncestors(enclosingCompositedContainer());
+}
- if (v->usesCompositing()) {
- if (RenderLayer* parentLayer = enclosingLayer()) {
- RenderLayer* compLayer = parentLayer->enclosingCompositingLayerForRepaint();
- if (compLayer)
- repaintContainer = compLayer->renderer();
- }
+const RenderLayerModelObject* RenderObject::enclosingCompositedContainer() const
+{
+ RenderLayerModelObject* container = 0;
+ if (view()->usesCompositing()) {
+ // FIXME: CompositingState is not necessarily up to date for many callers of this function.
+ DisableCompositingQueryAsserts disabler;
+
+ if (RenderLayer* compositingLayer = enclosingLayer()->enclosingCompositingLayerForRepaint())
+ container = compositingLayer->renderer();
}
+ return container;
+}
+
+const RenderLayerModelObject* RenderObject::adjustCompositedContainerForSpecialAncestors(const RenderLayerModelObject* paintInvalidationContainer) const
+{
if (document().view()->hasSoftwareFilters()) {
- if (RenderLayer* parentLayer = enclosingLayer()) {
- RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
- if (enclosingFilterLayer)
- return enclosingFilterLayer->renderer();
- }
+ if (RenderLayer* enclosingFilterLayer = enclosingLayer()->enclosingFilterLayer())
+ return enclosingFilterLayer->renderer();
}
- // 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
- // repainting to do individual region repaints.
- RenderFlowThread* parentRenderFlowThread = flowThreadContainingBlock();
- if (parentRenderFlowThread) {
- // The ancestor document will do the reparenting when the repaint propagates further up.
- // We're just a seamless child document, and we don't need to do the hacking.
- if (parentRenderFlowThread->document() != document())
- return repaintContainer;
- // If we have already found a repaint container then we will repaint into that container only if it is part of the same
- // flow thread. Otherwise we will need to catch the repaint call and send it to the flow thread.
- RenderFlowThread* repaintContainerFlowThread = repaintContainer ? repaintContainer->flowThreadContainingBlock() : 0;
- if (!repaintContainerFlowThread || repaintContainerFlowThread != parentRenderFlowThread)
- repaintContainer = parentRenderFlowThread;
+ // If we have a flow thread, then we need to do individual paint invalidations within the RenderRegions instead.
+ // Return the flow thread as a paint invalidation container in order to create a chokepoint that allows us to change
+ // paint invalidation to do individual region paint invalidations.
+ if (RenderFlowThread* parentRenderFlowThread = flowThreadContainingBlock()) {
+ // If we have already found a paint invalidation container then we will invalidate paints in that container only if it is part of the same
+ // flow thread. Otherwise we will need to catch the paint invalidation call and send it to the flow thread.
+ if (!paintInvalidationContainer || paintInvalidationContainer->flowThreadContainingBlock() != parentRenderFlowThread)
+ paintInvalidationContainer = parentRenderFlowThread;
}
- return repaintContainer;
+ return paintInvalidationContainer ? paintInvalidationContainer : view();
}
-void RenderObject::repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const IntRect& r) const
+bool RenderObject::isPaintInvalidationContainer() const
{
- if (!repaintContainer) {
- view()->repaintViewRectangle(r);
- return;
- }
+ return hasLayer() && toRenderLayerModelObject(this)->layer()->isRepaintContainer();
+}
- if (repaintContainer->compositingState() == PaintsIntoGroupedBacking) {
- ASSERT(repaintContainer->groupedMapping());
+template<typename T> PassRefPtr<JSONValue> jsonObjectForRect(const T& rect)
+{
+ RefPtr<JSONObject> object = JSONObject::create();
+ object->setNumber("x", rect.x());
+ object->setNumber("y", rect.y());
+ object->setNumber("width", rect.width());
+ object->setNumber("height", rect.height());
+ return object.release();
+}
- // Not clean, but if squashing layer does not yet exist here (e.g. repaint invalidation coming from within recomputing compositing requirements)
- // then it's ok to just exit here, since the squashing layer will get repainted when it is newly created.
- if (!repaintContainer->groupedMapping()->squashingLayer())
- return;
+static PassRefPtr<JSONValue> jsonObjectForPaintInvalidationInfo(const IntRect& rect, const String& invalidationReason)
+{
+ RefPtr<JSONObject> object = JSONObject::create();
+ object->setValue("rect", jsonObjectForRect(rect));
+ object->setString("invalidation_reason", invalidationReason);
+ return object.release();
+}
+LayoutRect RenderObject::computePaintInvalidationRect(const RenderLayerModelObject* paintInvalidationContainer) const
+{
+ return clippedOverflowRectForPaintInvalidation(paintInvalidationContainer);
+}
- IntRect offsetRect(r);
+void RenderObject::invalidatePaintUsingContainer(const RenderLayerModelObject* paintInvalidationContainer, const IntRect& r, InvalidationReason invalidationReason) const
+{
+ if (r.isEmpty())
+ return;
- // First, convert the repaint rect into the space of the repaintContainer
- TransformState transformState(TransformState::ApplyTransformDirection, FloatQuad(FloatRect(r)));
- mapLocalToContainer(repaintContainer, transformState, ApplyContainerFlip);
- transformState.flatten();
- offsetRect = transformState.lastPlanarQuad().enclosingBoundingBox();
+ // FIXME: This should be an assert, but editing/selection can trigger this case to invalidate
+ // the selection. crbug.com/368140.
+ if (!isRooted())
+ return;
- // FIXME: the repaint rect computed below could be tighter in uncommon nested transform cases, if we passed the quad
- // directly to the next chunk of code.
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "RenderObject::invalidatePaintUsingContainer()",
+ "object", this->debugName().ascii(),
+ "info", TracedValue::fromJSONValue(jsonObjectForPaintInvalidationInfo(r, invalidationReasonToString(invalidationReason))));
- // Then, convert the repaint rect from repaintConainer space into the squashing GraphicsLayer's coordinates.
- if (repaintContainer->hasTransform())
- offsetRect = repaintContainer->layer()->transform()->mapRect(r);
- offsetRect.move(-repaintContainer->layer()->offsetFromSquashingLayerOrigin());
- repaintContainer->groupedMapping()->squashingLayer()->setNeedsDisplayInRect(offsetRect);
- return;
- }
+ // For querying RenderLayer::compositingState()
+ DisableCompositingQueryAsserts disabler;
- if (repaintContainer->isRenderFlowThread()) {
- toRenderFlowThread(repaintContainer)->repaintRectangleInRegions(r);
+ if (paintInvalidationContainer->isRenderFlowThread()) {
+ toRenderFlowThread(paintInvalidationContainer)->repaintRectangleInRegions(r);
return;
}
- if (repaintContainer->hasFilter() && repaintContainer->layer()->requiresFullLayerImageForFilters()) {
- repaintContainer->layer()->repainter().setFilterBackendNeedsRepaintingInRect(r);
+ if (paintInvalidationContainer->hasFilter() && paintInvalidationContainer->layer()->requiresFullLayerImageForFilters()) {
+ paintInvalidationContainer->layer()->repainter().setFilterBackendNeedsRepaintingInRect(r);
return;
}
RenderView* v = view();
- if (repaintContainer->isRenderView()) {
- ASSERT(repaintContainer == v);
- bool viewHasCompositedLayer = v->hasLayer() && v->layer()->compositingState() == PaintsIntoOwnBacking;
- if (!viewHasCompositedLayer) {
- IntRect repaintRectangle = r;
- if (viewHasCompositedLayer && v->layer()->transform())
- repaintRectangle = v->layer()->transform()->mapRect(r);
- v->repaintViewRectangle(repaintRectangle);
- return;
- }
+ if (paintInvalidationContainer->isRenderView()) {
+ ASSERT(paintInvalidationContainer == v);
+ v->repaintViewRectangle(r);
+ return;
}
if (v->usesCompositing()) {
- ASSERT(repaintContainer->hasLayer() && repaintContainer->layer()->compositingState() == PaintsIntoOwnBacking);
- repaintContainer->layer()->repainter().setBackingNeedsRepaintInRect(r);
+ ASSERT(paintInvalidationContainer->hasLayer() && (paintInvalidationContainer->layer()->compositingState() == PaintsIntoOwnBacking || paintInvalidationContainer->layer()->compositingState() == PaintsIntoGroupedBacking));
+ paintInvalidationContainer->layer()->repainter().setBackingNeedsRepaintInRect(r);
}
}
-void RenderObject::repaint() const
+void RenderObject::paintInvalidationForWholeRenderer() const
{
- // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
- RenderView* view;
- if (!isRooted(&view))
+ if (!isRooted())
return;
- if (view->document().printing())
- return; // Don't repaint if we're printing.
+ if (view()->document().printing())
+ return; // Don't invalidate paints if we're printing.
- RenderLayerModelObject* repaintContainer = containerForRepaint();
- repaintUsingContainer(repaintContainer ? repaintContainer : view, pixelSnappedIntRect(clippedOverflowRectForRepaint(repaintContainer)));
+ // FIXME: really, we're in the paint invalidation phase here, and the following queries are legal.
+ // Until those states are fully fledged, I'll just disable the ASSERTS.
+ DisableCompositingQueryAsserts disabler;
+ const RenderLayerModelObject* paintInvalidationContainer = containerForPaintInvalidation();
+ LayoutRect paintInvalidationRect = boundsRectForPaintInvalidation(paintInvalidationContainer);
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(paintInvalidationRect), InvalidationPaint);
}
-void RenderObject::repaintRectangle(const LayoutRect& r) const
+LayoutRect RenderObject::boundsRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
- RenderView* view;
- if (!isRooted(&view))
+ if (!paintInvalidationContainer)
+ return computePaintInvalidationRect(paintInvalidationContainer);
+ return RenderLayer::computeRepaintRect(this, paintInvalidationContainer->layer());
+}
+
+void RenderObject::invalidatePaintRectangle(const LayoutRect& r) const
+{
+ if (!isRooted())
return;
- if (view->document().printing())
- return; // Don't repaint if we're printing.
+ if (view()->document().printing())
+ return; // Don't invalidate paints if we're printing.
LayoutRect dirtyRect(r);
- // FIXME: layoutDelta needs to be applied in parts before/after transforms and
- // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
- dirtyRect.move(view->layoutDelta());
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // paint invalidation containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+ dirtyRect.move(view()->layoutDelta());
+ }
- RenderLayerModelObject* repaintContainer = containerForRepaint();
- computeRectForRepaint(repaintContainer, dirtyRect);
- repaintUsingContainer(repaintContainer ? repaintContainer : view, pixelSnappedIntRect(dirtyRect));
+ const RenderLayerModelObject* paintInvalidationContainer = containerForPaintInvalidation();
+ RenderLayer::mapRectToRepaintBacking(this, paintInvalidationContainer, dirtyRect);
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(dirtyRect), InvalidationPaintRectangle);
}
IntRect RenderObject::pixelSnappedAbsoluteClippedOverflowRect() const
@@ -1481,84 +1585,165 @@ IntRect RenderObject::pixelSnappedAbsoluteClippedOverflowRect() const
return pixelSnappedIntRect(absoluteClippedOverflowRect());
}
-bool RenderObject::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, bool wasSelfLayout,
- const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox,
- const LayoutRect* newBoundsPtr, const LayoutRect* newOutlineBoxRectPtr)
+const char* RenderObject::invalidationReasonToString(InvalidationReason reason) const
+{
+ switch (reason) {
+ case InvalidationIncremental:
+ return "incremental";
+ case InvalidationSelfLayout:
+ return "self layout";
+ case InvalidationBorderFitLines:
+ return "border fit lines";
+ case InvalidationBorderRadius:
+ return "border radius";
+ case InvalidationBoundsChangeWithBackground:
+ return "bounds change with background";
+ case InvalidationBoundsChange:
+ return "bounds change";
+ case InvalidationLocationChange:
+ return "location change";
+ case InvalidationScroll:
+ return "scroll";
+ case InvalidationSelection:
+ return "selection";
+ case InvalidationLayer:
+ return "layer";
+ case InvalidationPaint:
+ return "invalidate paint";
+ case InvalidationPaintRectangle:
+ return "invalidate paint rectangle";
+ }
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+void RenderObject::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
+{
+ // If we didn't need paint invalidation then our children don't need as well.
+ // Skip walking down the tree as everything should be fine below us.
+ if (!shouldCheckForPaintInvalidationAfterLayout())
+ return;
+
+ clearPaintInvalidationState();
+
+ for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling()) {
+ if (!child->isOutOfFlowPositioned())
+ child->invalidateTreeAfterLayout(paintInvalidationContainer);
+ }
+}
+
+static PassRefPtr<JSONValue> jsonObjectForOldAndNewRects(const LayoutRect& oldRect, const LayoutRect& newRect)
+{
+ RefPtr<JSONObject> object = JSONObject::create();
+
+ object->setValue("old", jsonObjectForRect(oldRect));
+ object->setValue("new", jsonObjectForRect(newRect));
+ return object.release();
+}
+
+bool RenderObject::invalidatePaintAfterLayoutIfNeeded(const RenderLayerModelObject* paintInvalidationContainer, bool wasSelfLayout,
+ const LayoutRect& oldBounds, const LayoutPoint& oldLocation, const LayoutRect* newBoundsPtr, const LayoutPoint* newLocationPtr)
{
RenderView* v = view();
if (v->document().printing())
- return false; // Don't repaint if we're printing.
+ return false; // Don't invalidate paints if we're printing.
// This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
- // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
- LayoutRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer);
- LayoutRect newOutlineBox;
+ // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForPaintInvalidation(paintInvalidationContainer));
+ LayoutRect newBounds = newBoundsPtr ? *newBoundsPtr : computePaintInvalidationRect();
+ LayoutPoint newLocation = newLocationPtr ? (*newLocationPtr) : RenderLayer::positionFromPaintInvalidationContainer(this, paintInvalidationContainer);
+
+ // FIXME: This should use a ConvertableToTraceFormat when they are available in Blink.
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "RenderObject::invalidatePaintAfterLayoutIfNeeded()",
+ "object", this->debugName().ascii(),
+ "info", TracedValue::fromJSONValue(jsonObjectForOldAndNewRects(oldBounds, newBounds)));
+
+ InvalidationReason invalidationReason = wasSelfLayout ? InvalidationSelfLayout : InvalidationIncremental;
- bool fullRepaint = wasSelfLayout;
// Presumably a background or a border exists if border-fit:lines was specified.
- if (!fullRepaint && style()->borderFit() == BorderFitLines)
- fullRepaint = true;
- if (!fullRepaint && style()->hasBorderRadius()) {
+ if (invalidationReason == InvalidationIncremental && style()->borderFit() == BorderFitLines)
+ invalidationReason = InvalidationBorderFitLines;
+
+ if (invalidationReason == InvalidationIncremental && style()->hasBorderRadius()) {
// If a border-radius exists and width/height is smaller than
- // radius width/height, we cannot use delta-repaint.
- RoundedRect oldRoundedRect = style()->getRoundedBorderFor(oldBounds, v);
- RoundedRect newRoundedRect = style()->getRoundedBorderFor(newBounds, v);
- fullRepaint = oldRoundedRect.radii() != newRoundedRect.radii();
+ // radius width/height, we cannot use delta-paint-invalidation.
+ RoundedRect oldRoundedRect = style()->getRoundedBorderFor(oldBounds);
+ RoundedRect newRoundedRect = style()->getRoundedBorderFor(newBounds);
+ if (oldRoundedRect.radii() != newRoundedRect.radii())
+ invalidationReason = InvalidationBorderRadius;
}
- if (!fullRepaint) {
- // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
- // ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
- newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer);
- if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
- fullRepaint = true;
+
+ if (invalidationReason == InvalidationIncremental && compositingState() != PaintsIntoOwnBacking && newLocation != oldLocation)
+ invalidationReason = InvalidationLocationChange;
+
+ // If the bounds are the same then we know that none of the statements below
+ // can match, so we can early out since we will not need to do any
+ // invalidation.
+ if (invalidationReason == InvalidationIncremental && oldBounds == newBounds)
+ return false;
+
+ if (invalidationReason == InvalidationIncremental) {
+ if (oldBounds.width() != newBounds.width() && mustInvalidateBackgroundOrBorderPaintOnWidthChange())
+ invalidationReason = InvalidationBoundsChangeWithBackground;
+ else if (oldBounds.height() != newBounds.height() && mustInvalidateBackgroundOrBorderPaintOnHeightChange())
+ invalidationReason = InvalidationBoundsChangeWithBackground;
}
- if (!repaintContainer)
- repaintContainer = v;
+ // If we shifted, we don't know the exact reason so we are conservative and trigger a full invalidation. Shifting could
+ // be caused by some layout property (left / top) or some in-flow renderer inserted / removed before us in the tree.
+ if (invalidationReason == InvalidationIncremental && newBounds.location() != oldBounds.location())
+ invalidationReason = InvalidationBoundsChange;
+
+ // If the size is zero on one of our bounds then we know we're going to have
+ // to do a full invalidation of either old bounds or new bounds. If we fall
+ // into the incremental invalidation we'll issue two invalidations instead
+ // of one.
+ if (invalidationReason == InvalidationIncremental && (oldBounds.size().isZero() || newBounds.size().isZero()))
+ invalidationReason = InvalidationBoundsChange;
+
+ ASSERT(paintInvalidationContainer);
- if (fullRepaint) {
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds));
+ if (invalidationReason != InvalidationIncremental) {
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(oldBounds), invalidationReason);
if (newBounds != oldBounds)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(newBounds), invalidationReason);
return true;
}
- if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
- return false;
-
LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
if (deltaLeft > 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()), invalidationReason);
else if (deltaLeft < 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()), invalidationReason);
LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
if (deltaRight > 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()), invalidationReason);
else if (deltaRight < 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()), invalidationReason);
LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
if (deltaTop > 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop), invalidationReason);
else if (deltaTop < 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop), invalidationReason);
LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
if (deltaBottom > 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom), invalidationReason);
else if (deltaBottom < 0)
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(oldBounds.x(), newBounds.maxY(), oldBounds.width(), -deltaBottom), invalidationReason);
- if (newOutlineBox == oldOutlineBox)
+ // FIXME: This is a limitation of our visual overflow being a single rectangle.
+ if (!style()->boxShadow() && !style()->hasBorderImageOutsets() && !style()->hasOutline())
return false;
// We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
// two rectangles (but typically only one).
- RenderStyle* outlineStyle = outlineStyleForRepaint();
+ RenderStyle* outlineStyle = outlineStyleForPaintInvalidation();
LayoutUnit outlineWidth = outlineStyle->outlineSize();
LayoutBoxExtent insetShadowExtent = style()->getBoxShadowInsetExtent();
- LayoutUnit width = absoluteValue(newOutlineBox.width() - oldOutlineBox.width());
+ LayoutUnit width = absoluteValue(newBounds.width() - oldBounds.width());
if (width) {
LayoutUnit shadowLeft;
LayoutUnit shadowRight;
@@ -1566,19 +1751,20 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repa
int borderRight = isBox() ? toRenderBox(this)->borderRight() : 0;
LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : LayoutUnit();
LayoutUnit minInsetRightShadowExtent = min<LayoutUnit>(-insetShadowExtent.right(), min<LayoutUnit>(newBounds.width(), oldBounds.width()));
- LayoutUnit borderWidth = max<LayoutUnit>(borderRight, max<LayoutUnit>(valueForLength(style()->borderTopRightRadius().width(), boxWidth, v), valueForLength(style()->borderBottomRightRadius().width(), boxWidth, v)));
- LayoutUnit decorationsWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderWidth + minInsetRightShadowExtent) + max<LayoutUnit>(outlineWidth, shadowRight);
- LayoutRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - decorationsWidth,
- newOutlineBox.y(),
- width + decorationsWidth,
- max(newOutlineBox.height(), oldOutlineBox.height()));
+ LayoutUnit borderWidth = max<LayoutUnit>(borderRight, max<LayoutUnit>(valueForLength(style()->borderTopRightRadius().width(), boxWidth), valueForLength(style()->borderBottomRightRadius().width(), boxWidth)));
+ LayoutUnit decorationsLeftWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderWidth + minInsetRightShadowExtent) + max<LayoutUnit>(outlineWidth, -shadowLeft);
+ LayoutUnit decorationsRightWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderWidth + minInsetRightShadowExtent) + max<LayoutUnit>(outlineWidth, shadowRight);
+ LayoutRect rightRect(newBounds.x() + min(newBounds.width(), oldBounds.width()) - decorationsLeftWidth,
+ newBounds.y(),
+ width + decorationsLeftWidth + decorationsRightWidth,
+ max(newBounds.height(), oldBounds.height()));
LayoutUnit right = min<LayoutUnit>(newBounds.maxX(), oldBounds.maxX());
if (rightRect.x() < right) {
rightRect.setWidth(min(rightRect.width(), right - rightRect.x()));
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(rightRect));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(rightRect), invalidationReason);
}
}
- LayoutUnit height = absoluteValue(newOutlineBox.height() - oldOutlineBox.height());
+ LayoutUnit height = absoluteValue(newBounds.height() - oldBounds.height());
if (height) {
LayoutUnit shadowTop;
LayoutUnit shadowBottom;
@@ -1586,46 +1772,58 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repa
int borderBottom = isBox() ? toRenderBox(this)->borderBottom() : 0;
LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : LayoutUnit();
LayoutUnit minInsetBottomShadowExtent = min<LayoutUnit>(-insetShadowExtent.bottom(), min<LayoutUnit>(newBounds.height(), oldBounds.height()));
- LayoutUnit borderHeight = max<LayoutUnit>(borderBottom, max<LayoutUnit>(valueForLength(style()->borderBottomLeftRadius().height(), boxHeight, v), valueForLength(style()->borderBottomRightRadius().height(), boxHeight, v)));
- LayoutUnit decorationsHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderHeight + minInsetBottomShadowExtent) + max<LayoutUnit>(outlineWidth, shadowBottom);
- LayoutRect bottomRect(newOutlineBox.x(),
- min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - decorationsHeight,
- max(newOutlineBox.width(), oldOutlineBox.width()),
- height + decorationsHeight);
+ LayoutUnit borderHeight = max<LayoutUnit>(borderBottom, max<LayoutUnit>(valueForLength(style()->borderBottomLeftRadius().height(), boxHeight), valueForLength(style()->borderBottomRightRadius().height(), boxHeight)));
+ LayoutUnit decorationsTopHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderHeight + minInsetBottomShadowExtent) + max<LayoutUnit>(outlineWidth, -shadowTop);
+ LayoutUnit decorationsBottomHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderHeight + minInsetBottomShadowExtent) + max<LayoutUnit>(outlineWidth, shadowBottom);
+ LayoutRect bottomRect(newBounds.x(),
+ min(newBounds.maxY(), oldBounds.maxY()) - decorationsTopHeight,
+ max(newBounds.width(), oldBounds.width()),
+ height + decorationsTopHeight + decorationsBottomHeight);
LayoutUnit bottom = min(newBounds.maxY(), oldBounds.maxY());
if (bottomRect.y() < bottom) {
bottomRect.setHeight(min(bottomRect.height(), bottom - bottomRect.y()));
- repaintUsingContainer(repaintContainer, pixelSnappedIntRect(bottomRect));
+ invalidatePaintUsingContainer(paintInvalidationContainer, pixelSnappedIntRect(bottomRect), invalidationReason);
}
}
return false;
}
-void RenderObject::repaintOverflow()
+void RenderObject::invalidatePaintForOverflow()
+{
+}
+
+void RenderObject::invalidatePaintForOverflowIfNeeded()
+{
+ if (shouldInvalidateOverflowForPaint())
+ invalidatePaintForOverflow();
+}
+
+bool RenderObject::checkForPaintInvalidation() const
{
+ return !document().view()->needsFullPaintInvalidation() && everHadLayout();
}
-bool RenderObject::checkForRepaintDuringLayout() const
+bool RenderObject::checkForPaintInvalidationDuringLayout() const
{
- return !document().view()->needsFullRepaint() && !hasLayer() && everHadLayout();
+ return !RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && checkForPaintInvalidation();
}
-LayoutRect RenderObject::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
+LayoutRect RenderObject::rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth) const
{
- LayoutRect r(clippedOverflowRectForRepaint(repaintContainer));
+ LayoutRect r(clippedOverflowRectForPaintInvalidation(paintInvalidationContainer));
r.inflate(outlineWidth);
return r;
}
-LayoutRect RenderObject::clippedOverflowRectForRepaint(const RenderLayerModelObject*) const
+LayoutRect RenderObject::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*) const
{
ASSERT_NOT_REACHED();
return LayoutRect();
}
-void RenderObject::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+void RenderObject::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, bool fixed) const
{
- if (repaintContainer == this)
+ if (paintInvalidationContainer == this)
return;
if (RenderObject* o = parent()) {
@@ -1642,11 +1840,11 @@ void RenderObject::computeRectForRepaint(const RenderLayerModelObject* repaintCo
return;
}
- o->computeRectForRepaint(repaintContainer, rect, fixed);
+ o->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, fixed);
}
}
-void RenderObject::computeFloatRectForRepaint(const RenderLayerModelObject*, FloatRect&, bool) const
+void RenderObject::computeFloatRectForPaintInvalidation(const RenderLayerModelObject*, FloatRect&, bool) const
{
ASSERT_NOT_REACHED();
}
@@ -1714,7 +1912,7 @@ void RenderObject::showRenderTreeAndMark(const RenderObject* markedObject1, cons
if (!this)
return;
- for (const RenderObject* child = firstChild(); child; child = child->nextSibling())
+ for (const RenderObject* child = slowFirstChild(); child; child = child->nextSibling())
child->showRenderTreeAndMark(markedObject1, markedLabel1, markedObject2, markedLabel2, depth + 1);
}
@@ -1727,19 +1925,14 @@ bool RenderObject::isSelectable() const
Color RenderObject::selectionBackgroundColor() const
{
- Color backgroundColor;
- if (isSelectable()) {
- RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
- if (pseudoStyle && resolveColor(pseudoStyle.get(), CSSPropertyBackgroundColor).isValid()) {
- backgroundColor = resolveColor(pseudoStyle.get(), CSSPropertyBackgroundColor).blendWithWhite();
- } else {
- backgroundColor = frame()->selection().isFocusedAndActive() ?
- RenderTheme::theme().activeSelectionBackgroundColor() :
- RenderTheme::theme().inactiveSelectionBackgroundColor();
- }
- }
+ if (!isSelectable())
+ return Color::transparent;
- return backgroundColor;
+ if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyleFromParentOrShadowHost())
+ return resolveColor(pseudoStyle.get(), CSSPropertyBackgroundColor).blendWithWhite();
+ return frame()->selection().isFocusedAndActive() ?
+ RenderTheme::theme().activeSelectionBackgroundColor() :
+ RenderTheme::theme().inactiveSelectionBackgroundColor();
}
Color RenderObject::selectionColor(int colorProperty) const
@@ -1747,19 +1940,15 @@ Color RenderObject::selectionColor(int colorProperty) const
// If the element is unselectable, or we are only painting the selection,
// don't override the foreground color with the selection foreground color.
if (!isSelectable() || (frame()->view()->paintBehavior() & PaintBehaviorSelectionOnly))
- return Color::transparent;
+ return resolveColor(colorProperty);
- Color color;
- if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(PseudoStyleRequest(SELECTION))) {
- Color selectionColor = resolveColor(pseudoStyle.get(), colorProperty);
- color = selectionColor.isValid() ? selectionColor : resolveColor(pseudoStyle.get(), CSSPropertyColor);
- } else {
- color = frame()->selection().isFocusedAndActive() ?
- RenderTheme::theme().activeSelectionForegroundColor() :
- RenderTheme::theme().inactiveSelectionForegroundColor();
- }
-
- return color;
+ if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyleFromParentOrShadowHost())
+ return resolveColor(pseudoStyle.get(), colorProperty);
+ if (!RenderTheme::theme().supportsSelectionForegroundColors())
+ return resolveColor(colorProperty);
+ return frame()->selection().isFocusedAndActive() ?
+ RenderTheme::theme().activeSelectionForegroundColor() :
+ RenderTheme::theme().inactiveSelectionForegroundColor();
}
Color RenderObject::selectionForegroundColor() const
@@ -1796,65 +1985,57 @@ void RenderObject::handleDynamicFloatPositionChange()
}
}
-void RenderObject::setAnimatableStyle(PassRefPtr<RenderStyle> style)
-{
- if (!isText() && style && !RuntimeEnabledFeatures::webAnimationsCSSEnabled()) {
- setStyle(animation().updateAnimations(*this, *style));
- return;
- }
- setStyle(style);
-}
-
StyleDifference RenderObject::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
{
- // If transform changed, and the layer does not paint into its own separate backing, then we need to do a layout.
- // FIXME: The comment above is what the code does, but it is technically not following spec. This means we will
- // not to layout for 3d transforms, but we should be invoking a simplified relayout. Is it possible we are avoiding
- // doing this for some performance reason at this time?
+ if (contextSensitiveProperties & ContextSensitivePropertyTransform && isSVG())
+ diff.setNeedsFullLayout();
+
+ // If transform changed, and the layer does not paint into its own separate backing, then we need to invalidate paints.
if (contextSensitiveProperties & ContextSensitivePropertyTransform) {
// Text nodes share style with their parents but transforms don't apply to them,
// hence the !isText() check.
- // FIXME: when transforms are taken into account for overflow, we will need to do a layout.
- if (!isText() && (!hasLayer() || toRenderLayerModelObject(this)->layer()->compositingState() != PaintsIntoOwnBacking)) {
- // We need to set at least SimplifiedLayout, but if PositionedMovementOnly is already set
- // then we actually need SimplifiedLayoutAndPositionedMovement.
- if (!hasLayer())
- diff = StyleDifferenceLayout; // FIXME: Do this for now since SimplifiedLayout cannot handle updating floating objects lists.
- else if (diff < StyleDifferenceLayoutPositionedMovementOnly)
- diff = StyleDifferenceSimplifiedLayout;
- else if (diff < StyleDifferenceSimplifiedLayout)
- diff = StyleDifferenceSimplifiedLayoutAndPositionedMovement;
- } else if (diff < StyleDifferenceRecompositeLayer)
- diff = StyleDifferenceRecompositeLayer;
- }
-
- // If opacity or filters changed, and the layer does not paint into its own separate backing, then we need to repaint (also
+ if (!isText() && (!hasLayer() || !toRenderLayerModelObject(this)->layer()->styleDeterminedCompositingReasons()))
+ diff.setNeedsRepaintLayer();
+ else
+ diff.setNeedsRecompositeLayer();
+ }
+
+ // If opacity or zIndex changed, and the layer does not paint into its own separate backing, then we need to invalidate paints (also
// ignoring text nodes)
- if (contextSensitiveProperties & ContextSensitivePropertyOpacity && diff <= StyleDifferenceRepaintLayer) {
- if (!isText() && (!hasLayer() || toRenderLayerModelObject(this)->layer()->compositingState() != PaintsIntoOwnBacking))
- diff = StyleDifferenceRepaintLayer;
- else if (diff < StyleDifferenceRecompositeLayer)
- diff = StyleDifferenceRecompositeLayer;
+ if (contextSensitiveProperties & (ContextSensitivePropertyOpacity | ContextSensitivePropertyZIndex)) {
+ if (!isText() && (!hasLayer() || !toRenderLayerModelObject(this)->layer()->styleDeterminedCompositingReasons()))
+ diff.setNeedsRepaintLayer();
+ else
+ diff.setNeedsRecompositeLayer();
}
- if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer() && diff <= StyleDifferenceRepaintLayer) {
+
+ // If filter changed, and the layer does not paint into its own separate backing or it paints with filters, then we need to invalidate paints.
+ if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
RenderLayer* layer = toRenderLayerModelObject(this)->layer();
- if (layer->compositingState() != PaintsIntoOwnBacking || layer->paintsWithFilters())
- diff = StyleDifferenceRepaintLayer;
- else if (diff < StyleDifferenceRecompositeLayer)
- diff = StyleDifferenceRecompositeLayer;
+ if (!layer->styleDeterminedCompositingReasons() || layer->paintsWithFilters())
+ diff.setNeedsRepaintLayer();
+ else
+ diff.setNeedsRecompositeLayer();
}
- // The answer to requiresLayer() for plugins, iframes, and canvas can change without the actual
+ if ((contextSensitiveProperties & ContextSensitivePropertyTextOrColor) && !diff.needsRepaint()
+ && hasImmediateNonWhitespaceTextChildOrPropertiesDependentOnColor())
+ diff.setNeedsRepaintObject();
+
+ // The answer to layerTypeRequired() for plugins, iframes, and canvas can change without the actual
// style changing, 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.
- if (diff == StyleDifferenceEqual && style() && isLayerModelObject()) {
- if (hasLayer() != toRenderLayerModelObject(this)->requiresLayer())
- diff = StyleDifferenceLayout;
+ if (!diff.needsFullLayout() && style() && isLayerModelObject()) {
+ bool requiresLayer = toRenderLayerModelObject(this)->layerTypeRequired() != NoLayer;
+ if (hasLayer() != requiresLayer)
+ diff.setNeedsFullLayout();
}
- // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
- if (diff == StyleDifferenceRepaintLayer && !hasLayer())
- diff = StyleDifferenceRepaint;
+ // If we have no layer(), just treat a RepaintLayer hint as a normal paint invalidation.
+ if (diff.needsRepaintLayer() && !hasLayer()) {
+ diff.clearNeedsRepaint();
+ diff.setNeedsRepaintObject();
+ }
return diff;
}
@@ -1884,7 +2065,9 @@ void RenderObject::setPseudoStyle(PassRefPtr<RenderStyle> pseudoStyle)
inline bool RenderObject::hasImmediateNonWhitespaceTextChildOrPropertiesDependentOnColor() const
{
- for (const RenderObject* r = firstChild(); r; r = r->nextSibling()) {
+ if (style()->hasBorder() || style()->hasOutline())
+ return true;
+ for (const RenderObject* r = slowFirstChild(); r; r = r->nextSibling()) {
if (r->isText() && !toRenderText(r)->isAllCollapsibleWhitespace())
return true;
if (r->style()->hasOutline() || r->style()->hasBorder())
@@ -1893,13 +2076,24 @@ inline bool RenderObject::hasImmediateNonWhitespaceTextChildOrPropertiesDependen
return false;
}
-inline bool RenderObject::shouldRepaintForStyleDifference(StyleDifference diff) const
+void RenderObject::markContainingBlocksForOverflowRecalc()
{
- return diff == StyleDifferenceRepaint || (diff == StyleDifferenceRepaintIfTextOrColorChange && hasImmediateNonWhitespaceTextChildOrPropertiesDependentOnColor());
+ for (RenderBlock* container = containingBlock(); container && !container->childNeedsOverflowRecalcAfterStyleChange(); container = container->containingBlock())
+ container->setChildNeedsOverflowRecalcAfterStyleChange(true);
+}
+
+void RenderObject::setNeedsOverflowRecalcAfterStyleChange()
+{
+ bool neededRecalc = needsOverflowRecalcAfterStyleChange();
+ setSelfNeedsOverflowRecalcAfterStyleChange(true);
+ if (!neededRecalc)
+ markContainingBlocksForOverflowRecalc();
}
void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
{
+ ASSERT(style);
+
if (m_style == style) {
// We need to run through adjustStyleDifference() for iframes, plugins, and canvas so
// style sharing is disabled for them. That should ensure that we never hit this code path.
@@ -1907,14 +2101,14 @@ void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
return;
}
- StyleDifference diff = StyleDifferenceEqual;
+ StyleDifference diff;
unsigned contextSensitiveProperties = ContextSensitivePropertyNone;
if (m_style)
- diff = m_style->diff(style.get(), contextSensitiveProperties);
+ diff = m_style->visualInvalidationDiff(*style, contextSensitiveProperties);
diff = adjustStyleDifference(diff, contextSensitiveProperties);
- styleWillChange(diff, style.get());
+ styleWillChange(diff, *style);
RefPtr<RenderStyle> oldStyle = m_style.release();
setStyleInternal(style);
@@ -1925,15 +2119,8 @@ void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
updateImage(oldStyle ? oldStyle->borderImage().image() : 0, m_style ? m_style->borderImage().image() : 0);
updateImage(oldStyle ? oldStyle->maskBoxImage().image() : 0, m_style ? m_style->maskBoxImage().image() : 0);
- updateShapeImage(oldStyle ? oldStyle->shapeInside() : 0, m_style ? m_style->shapeInside() : 0);
updateShapeImage(oldStyle ? oldStyle->shapeOutside() : 0, m_style ? m_style->shapeOutside() : 0);
- // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
- // during styleDidChange (it's used by clippedOverflowRectForRepaint()).
- // FIXME: Do this more cleanly. http://crbug.com/273904
- if (m_style->outlineWidth() > 0 && m_style->outlineSize() > view()->maximalOutlineSize())
- view()->setMaximalOutlineSize(m_style->outlineSize());
-
bool doesNotNeedLayout = !m_parent || isText();
styleDidChange(diff, oldStyle.get());
@@ -1946,25 +2133,28 @@ void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
return;
// Now that the layer (if any) has been updated, we need to adjust the diff again,
- // check whether we should layout now, and decide if we need to repaint.
+ // check whether we should layout now, and decide if we need to invalidate paints.
StyleDifference updatedDiff = adjustStyleDifference(diff, contextSensitiveProperties);
- if (diff <= StyleDifferenceLayoutPositionedMovementOnly) {
- if (updatedDiff == StyleDifferenceLayout)
+ if (!diff.needsFullLayout()) {
+ if (updatedDiff.needsFullLayout())
setNeedsLayoutAndPrefWidthsRecalc();
- else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly)
- setNeedsPositionedMovementLayout();
- else if (updatedDiff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
+ else if (updatedDiff.needsPositionedMovementLayout())
setNeedsPositionedMovementLayout();
- setNeedsSimplifiedNormalFlowLayout();
- } else if (updatedDiff == StyleDifferenceSimplifiedLayout)
- setNeedsSimplifiedNormalFlowLayout();
}
- if (updatedDiff == StyleDifferenceRepaintLayer || shouldRepaintForStyleDifference(updatedDiff)) {
- // Do a repaint with the new style now, e.g., for example if we go from
- // not having an outline to having an outline.
- repaint();
+ if (contextSensitiveProperties & ContextSensitivePropertyTransform && !needsLayout()) {
+ if (RenderBlock* container = containingBlock())
+ container->setNeedsOverflowRecalcAfterStyleChange();
+ }
+
+ if (updatedDiff.needsRepaint()) {
+ // Invalidate paints with the new style, e.g., for example if we go from not having
+ // an outline to having an outline.
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && needsLayout())
+ setShouldDoFullPaintInvalidationAfterLayout(true);
+ else if (!selfNeedsLayout())
+ paintInvalidationForWholeRenderer();
}
}
@@ -1973,76 +2163,80 @@ static inline bool rendererHasBackground(const RenderObject* renderer)
return renderer && renderer->hasBackground();
}
-void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
if (m_style) {
// If our z-index changes value or our visibility changes,
// we need to dirty our stacking context's z-order list.
- if (newStyle) {
- bool visibilityChanged = m_style->visibility() != newStyle->visibility()
- || m_style->zIndex() != newStyle->zIndex()
- || m_style->hasAutoZIndex() != newStyle->hasAutoZIndex();
- if (visibilityChanged) {
- document().setAnnotatedRegionsDirty(true);
- if (AXObjectCache* cache = document().existingAXObjectCache())
- cache->childrenChanged(parent());
- }
+ bool visibilityChanged = m_style->visibility() != newStyle.visibility()
+ || m_style->zIndex() != newStyle.zIndex()
+ || m_style->hasAutoZIndex() != newStyle.hasAutoZIndex();
+ if (visibilityChanged) {
+ document().setAnnotatedRegionsDirty(true);
+ if (AXObjectCache* cache = document().existingAXObjectCache())
+ cache->childrenChanged(parent());
+ }
- // Keep layer hierarchy visibility bits up to date if visibility changes.
- if (m_style->visibility() != newStyle->visibility()) {
- if (RenderLayer* l = enclosingLayer()) {
- if (newStyle->visibility() == VISIBLE)
- l->setHasVisibleContent();
- else if (l->hasVisibleContent() && (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE)) {
- l->dirtyVisibleContentStatus();
- if (diff > StyleDifferenceRepaintLayer)
- repaint();
- }
+ // Keep layer hierarchy visibility bits up to date if visibility changes.
+ if (m_style->visibility() != newStyle.visibility()) {
+ // We might not have an enclosing layer yet because we might not be in the tree.
+ if (RenderLayer* layer = enclosingLayer()) {
+ if (newStyle.visibility() == VISIBLE) {
+ layer->setHasVisibleContent();
+ } else if (layer->hasVisibleContent() && (this == layer->renderer() || layer->renderer()->style()->visibility() != VISIBLE)) {
+ layer->dirtyVisibleContentStatus();
+ if (diff.needsLayout())
+ paintInvalidationForWholeRenderer();
}
}
}
- if (m_parent && (newStyle->outlineSize() < m_style->outlineSize() || shouldRepaintForStyleDifference(diff)))
- repaint();
- if (isFloating() && (m_style->floating() != newStyle->floating()))
+ if (m_parent && diff.needsRepaintObject()) {
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && (diff.needsLayout() || needsLayout()))
+ setShouldDoFullPaintInvalidationAfterLayout(true);
+ else if (!diff.needsFullLayout() && !selfNeedsLayout())
+ paintInvalidationForWholeRenderer();
+ }
+
+ if (isFloating() && (m_style->floating() != newStyle.floating()))
// For changes in float styles, we need to conceivably remove ourselves
// from the floating objects list.
toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
- else if (isOutOfFlowPositioned() && (m_style->position() != newStyle->position()))
+ else if (isOutOfFlowPositioned() && (m_style->position() != newStyle.position()))
// For changes in positioning styles, we need to conceivably remove ourselves
// from the positioned objects list.
toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
- && (!newStyle->isFloating() && !newStyle->hasOutOfFlowPosition())
+ && (!newStyle.isFloating() && !newStyle.hasOutOfFlowPosition())
&& parent() && (parent()->isRenderBlockFlow() || parent()->isRenderInline());
// Clearing these bits is required to avoid leaving stale renderers.
// FIXME: We shouldn't need that hack if our logic was totally correct.
- if (diff == StyleDifferenceLayout || diff == StyleDifferenceLayoutPositionedMovementOnly) {
+ if (diff.needsLayout()) {
setFloating(false);
clearPositionedState();
}
- } else
+ } else {
s_affectsParentBlock = false;
+ }
if (view()->frameView()) {
bool shouldBlitOnFixedBackgroundImage = false;
-#if ENABLE(FAST_MOBILE_SCROLLING)
- // On low-powered/mobile devices, preventing blitting on a scroll can cause noticeable delays
- // 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;
-#endif
-
- bool newStyleSlowScroll = newStyle && !shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage();
+ if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) {
+ // On low-powered/mobile devices, preventing blitting on a scroll can cause noticeable delays
+ // 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;
+ }
+ bool newStyleSlowScroll = !shouldBlitOnFixedBackgroundImage && newStyle.hasFixedBackgroundImage();
bool oldStyleSlowScroll = m_style && !shouldBlitOnFixedBackgroundImage && m_style->hasFixedBackgroundImage();
- bool drawsRootBackground = isRoot() || (isBody() && !rendererHasBackground(document().documentElement()->renderer()));
+ bool drawsRootBackground = isDocumentElement() || (isBody() && !rendererHasBackground(document().documentElement()->renderer()));
if (drawsRootBackground && !shouldBlitOnFixedBackgroundImage) {
if (view()->compositor()->supportsFixedRootBackgroundCompositing()) {
- if (newStyleSlowScroll && newStyle->hasEntirelyFixedBackground())
+ if (newStyleSlowScroll && newStyle.hasEntirelyFixedBackground())
newStyleSlowScroll = false;
if (oldStyleSlowScroll && m_style->hasEntirelyFixedBackground())
@@ -2057,6 +2251,20 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS
view()->frameView()->addSlowRepaintObject();
}
}
+
+ // Elements with non-auto touch-action will send a SetTouchAction message
+ // on touchstart in EventHandler::handleTouchEvent, and so effectively have
+ // a touchstart handler that must be reported.
+ //
+ // Since a CSS property cannot be applied directly to a text node, a
+ // handler will have already been added for its parent so ignore it.
+ TouchAction oldTouchAction = m_style ? m_style->touchAction() : TouchActionAuto;
+ if (node() && !node()->isTextNode() && (oldTouchAction == TouchActionAuto) != (newStyle.touchAction() == TouchActionAuto)) {
+ if (newStyle.touchAction() != TouchActionAuto)
+ document().didAddTouchEventHandler(node());
+ else
+ document().didRemoveTouchEventHandler(node());
+ }
}
static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderStyle* b)
@@ -2078,7 +2286,7 @@ void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
if (!m_parent)
return;
- if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
+ if (diff.needsFullLayout()) {
RenderCounter::rendererStyleChanged(*this, oldStyle, m_style.get());
// If the object already needs layout, then setNeedsLayout won't do
@@ -2089,21 +2297,20 @@ void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
if (needsLayout() && oldStyle->position() != m_style->position())
markContainingBlocksForLayout();
- if (diff == StyleDifferenceLayout)
+ // Ditto.
+ if (needsOverflowRecalcAfterStyleChange() && oldStyle->position() != m_style->position())
+ markContainingBlocksForOverflowRecalc();
+
+ if (diff.needsFullLayout())
setNeedsLayoutAndPrefWidthsRecalc();
- else
- setNeedsSimplifiedNormalFlowLayout();
- } else if (diff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
- setNeedsPositionedMovementLayout();
- setNeedsSimplifiedNormalFlowLayout();
- } else if (diff == StyleDifferenceLayoutPositionedMovementOnly)
+ } else if (diff.needsPositionedMovementLayout())
setNeedsPositionedMovementLayout();
- // Don't check for repaint here; we need to wait until the layer has been
- // updated by subclasses before we know if we have to repaint (in setStyle()).
+ // Don't check for paint invalidation here; we need to wait until the layer has been
+ // updated by subclasses before we know if we have to invalidate paints (in setStyle()).
if (oldStyle && !areCursorsEqual(oldStyle, style())) {
- if (Frame* frame = this->frame())
+ if (LocalFrame* frame = this->frame())
frame->eventHandler().scheduleCursorUpdate();
}
}
@@ -2111,7 +2318,7 @@ void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
{
// FIXME: We could save this call when the change only affected non-inherited properties.
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling()) {
if (!child->isAnonymous() || child->style()->styleType() != NOPSEUDO)
continue;
@@ -2203,9 +2410,9 @@ FloatQuad RenderObject::absoluteToLocalQuad(const FloatQuad& quad, MapCoordinate
return transformState.lastPlanarQuad();
}
-void RenderObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
+void RenderObject::mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
{
- if (repaintContainer == this)
+ if (paintInvalidationContainer == this)
return;
RenderObject* o = parent();
@@ -2220,15 +2427,12 @@ void RenderObject::mapLocalToContainer(const RenderLayerModelObject* repaintCont
mode &= ~ApplyContainerFlip;
}
- LayoutSize columnOffset;
- o->adjustForColumns(columnOffset, roundedLayoutPoint(transformState.mappedPoint()));
- if (!columnOffset.isZero())
- transformState.move(columnOffset);
+ transformState.move(o->columnOffset(roundedLayoutPoint(transformState.mappedPoint())));
if (o->hasOverflowClip())
transformState.move(-toRenderBox(o)->scrolledContentOffset());
- o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+ o->mapLocalToContainer(paintInvalidationContainer, transformState, mode, wasFixed);
}
const RenderObject* RenderObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
@@ -2269,7 +2473,7 @@ bool RenderObject::shouldUseTransformFromContainer(const RenderObject* container
void RenderObject::getTransformFromContainer(const RenderObject* containerObject, const LayoutSize& offsetInContainer, TransformationMatrix& transform) const
{
transform.makeIdentity();
- transform.translate(offsetInContainer.width(), offsetInContainer.height());
+ transform.translate(offsetInContainer.width().toFloat(), offsetInContainer.height().toFloat());
RenderLayer* layer;
if (hasLayer() && (layer = toRenderLayerModelObject(this)->layer()) && layer->transform())
transform.multiply(layer->currentTransform());
@@ -2288,33 +2492,31 @@ void RenderObject::getTransformFromContainer(const RenderObject* containerObject
}
}
-FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
+FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const RenderLayerModelObject* paintInvalidationContainer, MapCoordinatesFlags mode, bool* wasFixed) const
{
// 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, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed);
+ mapLocalToContainer(paintInvalidationContainer, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed);
transformState.flatten();
return transformState.lastPlanarQuad();
}
-FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
+FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, const RenderLayerModelObject* paintInvalidationContainer, MapCoordinatesFlags mode, bool* wasFixed) const
{
TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
- mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed);
+ mapLocalToContainer(paintInvalidationContainer, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed);
transformState.flatten();
return transformState.lastPlanarPoint();
}
-LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+LayoutSize RenderObject::offsetFromContainer(const RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(o == container());
- LayoutSize offset;
-
- o->adjustForColumns(offset, point);
+ LayoutSize offset = o->columnOffset(point);
if (o->hasOverflowClip())
offset -= toRenderBox(o)->scrolledContentOffset();
@@ -2325,13 +2527,13 @@ LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint&
return offset;
}
-LayoutSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const
+LayoutSize RenderObject::offsetFromAncestorContainer(const RenderObject* container) const
{
LayoutSize offset;
LayoutPoint referencePoint;
const RenderObject* currContainer = this;
do {
- RenderObject* nextContainer = currContainer->container();
+ const RenderObject* nextContainer = currContainer->container();
ASSERT(nextContainer); // This means we reached the top without finding container.
if (!nextContainer)
break;
@@ -2362,21 +2564,15 @@ void RenderObject::computeLayerHitTestRects(LayerHitTestRects& layerRects) const
if (!hasLayer()) {
RenderObject* container = this->container();
- if (container) {
- currentLayer = container->enclosingLayer();
- if (currentLayer && currentLayer->renderer() != container) {
- layerOffset.move(container->offsetFromAncestorContainer(currentLayer->renderer()));
- // If the layer itself is scrolled, we have to undo the subtraction of its scroll
- // offset since we want the offset relative to the scrolling content, not the
- // element itself.
- if (currentLayer->renderer()->hasOverflowClip())
- layerOffset.move(currentLayer->renderBox()->scrolledContentOffset());
- }
- } else {
- currentLayer = enclosingLayer();
+ currentLayer = container->enclosingLayer();
+ if (container && currentLayer->renderer() != container) {
+ layerOffset.move(container->offsetFromAncestorContainer(currentLayer->renderer()));
+ // If the layer itself is scrolled, we have to undo the subtraction of its scroll
+ // offset since we want the offset relative to the scrolling content, not the
+ // element itself.
+ if (currentLayer->renderer()->hasOverflowClip())
+ layerOffset.move(currentLayer->renderBox()->scrolledContentOffset());
}
- if (!currentLayer)
- return;
}
this->addLayerHitTestRects(layerRects, currentLayer, layerOffset, LayoutRect());
@@ -2401,12 +2597,15 @@ void RenderObject::addLayerHitTestRects(LayerHitTestRects& layerRects, const Ren
const size_t maxRectsPerLayer = 100;
LayerHitTestRects::iterator iter = layerRects.find(currentLayer);
+ Vector<WebCore::LayoutRect>* iterValue;
if (iter == layerRects.end())
- iter = layerRects.add(currentLayer, Vector<LayoutRect>()).iterator;
+ iterValue = &layerRects.add(currentLayer, Vector<LayoutRect>()).storedValue->value;
+ else
+ iterValue = &iter->value;
for (size_t i = 0; i < ownRects.size(); i++) {
if (!containerRect.contains(ownRects[i])) {
- iter->value.append(ownRects[i]);
- if (iter->value.size() > maxRectsPerLayer) {
+ iterValue->append(ownRects[i]);
+ if (iterValue->size() > maxRectsPerLayer) {
// Just mark the entire layer instead, and switch to walking the layer
// tree instead of the render tree.
layerRects.remove(currentLayer);
@@ -2428,31 +2627,26 @@ void RenderObject::addLayerHitTestRects(LayerHitTestRects& layerRects, const Ren
// partially redundant rectangles. If we find examples where this is expensive, then we could
// rewrite Region to be more efficient. See https://bugs.webkit.org/show_bug.cgi?id=100814.
if (!isRenderView()) {
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling()) {
curr->addLayerHitTestRects(layerRects, currentLayer, layerOffset, newContainerRect);
}
}
}
-bool RenderObject::isRooted(RenderView** view) const
+bool RenderObject::isRooted() const
{
- const RenderObject* o = this;
- while (o->parent())
- o = o->parent();
-
- if (!o->isRenderView())
- return false;
-
- if (view)
- *view = const_cast<RenderView*>(toRenderView(o));
-
- return true;
+ const RenderObject* object = this;
+ while (object->parent() && !object->hasLayer())
+ object = object->parent();
+ if (object->hasLayer())
+ return toRenderLayerModelObject(object)->layer()->root()->isRootLayer();
+ return false;
}
RenderObject* RenderObject::rendererForRootBackground()
{
- ASSERT(isRoot());
- if (!hasBackground() && node() && isHTMLHtmlElement(node())) {
+ ASSERT(isDocumentElement());
+ if (!hasBackground() && isHTMLHtmlElement(node())) {
// Locate the <body> element using the DOM. This is easier than trying
// to crawl around a render tree with potential :before/:after content and
// anonymous blocks created by inline <body> tags etc. We can locate the <body>
@@ -2471,7 +2665,7 @@ 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;
+ || (document().settings() && document().settings()->shouldRespectImageOrientation() && isHTMLImageElement(node())) ? RespectImageOrientation : DoNotRespectImageOrientation;
}
bool RenderObject::hasOutlineAnnotation() const
@@ -2484,10 +2678,10 @@ bool RenderObject::hasEntirelyFixedBackground() const
return m_style->hasEntirelyFixedBackground();
}
-RenderObject* RenderObject::container(const RenderLayerModelObject* repaintContainer, bool* repaintContainerSkipped) const
+RenderObject* RenderObject::container(const RenderLayerModelObject* paintInvalidationContainer, bool* paintInvalidationContainerSkipped) const
{
- if (repaintContainerSkipped)
- *repaintContainerSkipped = false;
+ if (paintInvalidationContainerSkipped)
+ *paintInvalidationContainerSkipped = false;
// This method is extremely similar to containingBlock(), but with a few notable
// exceptions.
@@ -2505,7 +2699,7 @@ RenderObject* RenderObject::container(const RenderLayerModelObject* repaintConta
EPosition pos = m_style->position();
if (pos == FixedPosition) {
- return containerForFixedPosition(repaintContainer, repaintContainerSkipped);
+ return containerForFixedPosition(paintInvalidationContainer, paintInvalidationContainerSkipped);
} else if (pos == AbsolutePosition) {
// We technically just want our containing block, but
// we may not have one if we're part of an uninstalled
@@ -2517,8 +2711,8 @@ RenderObject* RenderObject::container(const RenderLayerModelObject* repaintConta
if (o->canContainFixedPositionObjects())
break;
- if (repaintContainerSkipped && o == repaintContainer)
- *repaintContainerSkipped = true;
+ if (paintInvalidationContainerSkipped && o == paintInvalidationContainer)
+ *paintInvalidationContainerSkipped = true;
o = o->parent();
}
@@ -2543,7 +2737,7 @@ inline void RenderObject::clearLayoutRootIfNeeded() const
// This indicates a failure to layout the child, which is why
// the layout root is still set to |this|. Make sure to clear it
// since we are getting destroyed.
- view->clearLayoutRoot();
+ view->clearLayoutSubtreeRoot();
}
}
}
@@ -2557,10 +2751,9 @@ void RenderObject::willBeDestroyed()
children->destroyLeftoverChildren();
// If this renderer is being autoscrolled, stop the autoscrolling.
- if (Frame* frame = this->frame()) {
+ if (LocalFrame* frame = this->frame()) {
if (frame->page())
frame->page()->autoscrollController().stopAutoscrollIfNeeded(this);
- frame->animation().cancelAnimations(this);
}
// For accessibility management, notify the parent of the imminent change to its child set.
@@ -2575,18 +2768,6 @@ void RenderObject::willBeDestroyed()
if (AXObjectCache* cache = document().existingAXObjectCache())
cache->remove(this);
-#ifndef NDEBUG
- if (!documentBeingDestroyed() && view() && view()->hasRenderNamedFlowThreads()) {
- // After remove, the object and the associated information should not be in any flow thread.
- 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));
- }
- }
-#endif
-
// If this renderer had a parent, remove should have destroyed any counters
// attached to this renderer and marked the affected other counters for
// reevaluation. This apparently redundant check is here for the case when
@@ -2595,6 +2776,13 @@ void RenderObject::willBeDestroyed()
if (hasCounterNodeMap())
RenderCounter::destroyCounterNodes(*this);
+ // Remove the handler if node had touch-action set. Don't call when
+ // document is being destroyed as all handlers will have been cleared
+ // previously. Handlers are not added for text nodes so don't try removing
+ // for one too. Need to check if m_style is null in cases of partial construction.
+ if (!documentBeingDestroyed() && node() && !node()->isTextNode() && m_style && m_style->touchAction() != TouchActionAuto)
+ document().didRemoveTouchEventHandler(node());
+
setAncestorLineBoxDirty(false);
clearLayoutRootIfNeeded();
@@ -2607,7 +2795,7 @@ void RenderObject::insertedIntoTree()
// Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
// and don't have a layer attached to ourselves.
RenderLayer* layer = 0;
- if (firstChild() || hasLayer()) {
+ if (slowFirstChild() || hasLayer()) {
layer = parent()->enclosingLayer();
addLayers(layer);
}
@@ -2623,9 +2811,6 @@ void RenderObject::insertedIntoTree()
if (!isFloating() && parent()->childrenInline())
parent()->dirtyLinesFromChangedChild(this);
-
- if (RenderNamedFlowThread* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
- containerFlowThread->addFlowChild(this);
}
void RenderObject::willBeRemovedFromTree()
@@ -2635,12 +2820,13 @@ void RenderObject::willBeRemovedFromTree()
// If we remove a visible child from an invisible parent, we don't know the layer visibility any more.
RenderLayer* layer = 0;
if (parent()->style()->visibility() != VISIBLE && style()->visibility() == VISIBLE && !hasLayer()) {
- if ((layer = parent()->enclosingLayer()))
+ layer = parent()->enclosingLayer();
+ if (layer)
layer->dirtyVisibleContentStatus();
}
// Keep our layer hierarchy updated.
- if (firstChild() || hasLayer()) {
+ if (slowFirstChild() || hasLayer()) {
if (!layer)
layer = parent()->enclosingLayer();
removeLayers(layer);
@@ -2651,11 +2837,9 @@ void RenderObject::willBeRemovedFromTree()
removeFromRenderFlowThread();
- if (RenderNamedFlowThread* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
- containerFlowThread->removeFlowChild(this);
-
// Update cached boundaries in SVG renderers if a child is removed.
- parent()->setNeedsBoundariesUpdate();
+ if (parent()->isSVG())
+ parent()->setNeedsBoundariesUpdate();
}
void RenderObject::removeFromRenderFlowThread()
@@ -2677,11 +2861,6 @@ void RenderObject::removeFromRenderFlowThreadRecursive(RenderFlowThread* renderF
child->removeFromRenderFlowThreadRecursive(renderFlowThread);
}
- RenderFlowThread* localFlowThread = renderFlowThread;
- if (flowThreadState() == InsideInFlowThread)
- localFlowThread = flowThreadContainingBlock(); // We have to ask. We can't just assume we are in the same flow thread.
- if (localFlowThread)
- localFlowThread->removeFlowChildInfo(this);
setFlowThreadState(NotInsideFlowThread);
}
@@ -2703,7 +2882,7 @@ void RenderObject::destroyAndCleanupAnonymousWrappers()
if (destroyRootParent->isRenderFlowThread() || destroyRootParent->isAnonymousColumnSpanBlock())
break;
- if (destroyRootParent->firstChild() != this || destroyRootParent->lastChild() != this)
+ if (destroyRootParent->slowFirstChild() != this || destroyRootParent->slowLastChild() != this)
break;
}
@@ -2712,6 +2891,12 @@ void RenderObject::destroyAndCleanupAnonymousWrappers()
// WARNING: |this| is deleted here.
}
+void RenderObject::destroy()
+{
+ willBeDestroyed();
+ postDestroy();
+}
+
void RenderObject::removeShapeImageClient(ShapeValue* shapeValue)
{
if (!shapeValue)
@@ -2720,12 +2905,6 @@ void RenderObject::removeShapeImageClient(ShapeValue* shapeValue)
shapeImage->removeClient(this);
}
-void RenderObject::destroy()
-{
- willBeDestroyed();
- postDestroy();
-}
-
void RenderObject::postDestroy()
{
// It seems ugly that this is not in willBeDestroyed().
@@ -2746,7 +2925,6 @@ void RenderObject::postDestroy()
if (StyleImage* maskBoxImage = m_style->maskBoxImage().image())
maskBoxImage->removeClient(this);
- removeShapeImageClient(m_style->shapeInside());
removeShapeImageClient(m_style->shapeOutside());
}
@@ -2762,9 +2940,13 @@ void RenderObject::updateDragState(bool dragOn)
{
bool valueChanged = (dragOn != isDragging());
setIsDragging(dragOn);
- if (valueChanged && node() && (style()->affectedByDrag() || (node()->isElementNode() && toElement(node())->childrenAffectedByDrag())))
- node()->setNeedsStyleRecalc();
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ if (valueChanged && node()) {
+ if (node()->isElementNode() && toElement(node())->childrenOrSiblingsAffectedByDrag())
+ node()->setNeedsStyleRecalc(SubtreeStyleChange);
+ else if (style()->affectedByDrag())
+ node()->setNeedsStyleRecalc(LocalStyleChange);
+ }
+ for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling())
curr->updateDragState(dragOn);
}
@@ -2773,6 +2955,11 @@ CompositingState RenderObject::compositingState() const
return hasLayer() ? toRenderLayerModelObject(this)->layer()->compositingState() : NotComposited;
}
+CompositingReasons RenderObject::additionalCompositingReasons(CompositingTriggerFlags) const
+{
+ return CompositingReasonNone;
+}
+
bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
{
bool inside = false;
@@ -2839,35 +3026,10 @@ void RenderObject::scheduleRelayout()
}
}
-void RenderObject::layout()
-{
- ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
- RenderObject* child = firstChild();
- while (child) {
- child->layoutIfNeeded();
- ASSERT(!child->needsLayout());
- child = child->nextSibling();
- }
- clearNeedsLayout();
-}
-
-void RenderObject::didLayout(ResourceLoadPriorityOptimizer& priorityModifier)
-{
- for (RenderObject* child = firstChild(); child; child = child->nextSibling())
- child->didLayout(priorityModifier);
-}
-
-void RenderObject::didScroll(ResourceLoadPriorityOptimizer& priorityModifier)
-{
- for (RenderObject* child = firstChild(); child; child = child->nextSibling())
- child->didScroll(priorityModifier);
-}
-
void RenderObject::forceLayout()
{
setSelfNeedsLayout(true);
- setShouldDoFullRepaintAfterLayout(true);
+ setShouldDoFullPaintInvalidationAfterLayout(true);
layout();
}
@@ -2907,13 +3069,13 @@ static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheSta
return rendererForFirstLineStyle->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), parentStyle, style);
}
}
- return 0;
+ return nullptr;
}
PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) const
{
if (!document().styleEngine()->usesFirstLineRules())
- return 0;
+ return nullptr;
ASSERT(!isText());
@@ -2948,20 +3110,19 @@ RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* pa
PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, RenderStyle* ownStyle) const
{
if (pseudoStyleRequest.pseudoId < FIRST_INTERNAL_PSEUDOID && !ownStyle && !style()->hasPseudoStyle(pseudoStyleRequest.pseudoId))
- return 0;
+ return nullptr;
if (!parentStyle) {
ASSERT(!ownStyle);
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);
+ if (!node())
+ return nullptr;
+
+ Element* element = Traversal<Element>::firstAncestorOrSelf(*node());
+ if (!element)
+ return nullptr;
if (pseudoStyleRequest.pseudoId == FIRST_LINE_INHERITED) {
RefPtr<RenderStyle> result = document().ensureStyleResolver().styleForElement(element, parentStyle, DisallowStyleSharing);
@@ -2972,54 +3133,56 @@ PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(const PseudoStyleRe
return document().ensureStyleResolver().pseudoStyleForElement(element, pseudoStyleRequest, parentStyle);
}
-bool RenderObject::hasBlendMode() const
+PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyleFromParentOrShadowHost() const
{
- return RuntimeEnabledFeatures::cssCompositingEnabled() && style() && style()->hasBlendMode();
-}
+ if (!node())
+ return nullptr;
-static Color decorationColor(const RenderObject* object, RenderStyle* style)
-{
- Color result;
- // Check for text decoration color first.
- result = object->resolveColor(style, CSSPropertyTextDecorationColor);
- if (result.isValid())
- return result;
- if (style->textStrokeWidth() > 0) {
- // Prefer stroke color if possible but not if it's fully transparent.
- result = object->resolveColor(style, CSSPropertyWebkitTextStrokeColor);
- if (result.alpha())
- return result;
+ if (ShadowRoot* root = node()->containingShadowRoot()) {
+ if (root->type() == ShadowRoot::UserAgentShadowRoot) {
+ if (Element* shadowHost = node()->shadowHost()) {
+ return shadowHost->renderer()->getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
+ }
+ }
}
- result = object->resolveColor(style, CSSPropertyWebkitTextFillColor);
- return result;
+ return getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
+}
+
+bool RenderObject::hasBlendMode() const
+{
+ return RuntimeEnabledFeatures::cssCompositingEnabled() && style() && style()->hasBlendMode();
}
-void RenderObject::getTextDecorationColors(unsigned decorations, Color& underline, Color& overline,
- Color& linethrough, bool quirksMode, bool firstlineStyle)
+void RenderObject::getTextDecorations(unsigned decorations, AppliedTextDecoration& underline, AppliedTextDecoration& overline, AppliedTextDecoration& linethrough, bool quirksMode, bool firstlineStyle)
{
RenderObject* curr = this;
RenderStyle* styleToUse = 0;
unsigned currDecs = TextDecorationNone;
Color resultColor;
+ TextDecorationStyle resultStyle;
do {
styleToUse = curr->style(firstlineStyle);
currDecs = styleToUse->textDecoration();
currDecs &= decorations;
- resultColor = decorationColor(this, styleToUse);
+ resultColor = styleToUse->visitedDependentDecorationColor();
+ resultStyle = styleToUse->textDecorationStyle();
// Parameter 'decorations' is cast as an int to enable the bitwise operations below.
if (currDecs) {
if (currDecs & TextDecorationUnderline) {
decorations &= ~TextDecorationUnderline;
- underline = resultColor;
+ underline.color = resultColor;
+ underline.style = resultStyle;
}
if (currDecs & TextDecorationOverline) {
decorations &= ~TextDecorationOverline;
- overline = resultColor;
+ overline.color = resultColor;
+ overline.style = resultStyle;
}
if (currDecs & TextDecorationLineThrough) {
decorations &= ~TextDecorationLineThrough;
- linethrough = resultColor;
+ linethrough.color = resultColor;
+ linethrough.style = resultStyle;
}
}
if (curr->isRubyText())
@@ -3027,18 +3190,24 @@ void RenderObject::getTextDecorationColors(unsigned decorations, Color& underlin
curr = curr->parent();
if (curr && curr->isAnonymousBlock() && toRenderBlock(curr)->continuation())
curr = toRenderBlock(curr)->continuation();
- } while (curr && decorations && (!quirksMode || !curr->node() || (!isHTMLAnchorElement(curr->node()) && !curr->node()->hasTagName(fontTag))));
+ } while (curr && decorations && (!quirksMode || !curr->node() || (!isHTMLAnchorElement(*curr->node()) && !isHTMLFontElement(*curr->node()))));
// If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
if (decorations && curr) {
styleToUse = curr->style(firstlineStyle);
- resultColor = decorationColor(this, styleToUse);
- if (decorations & TextDecorationUnderline)
- underline = resultColor;
- if (decorations & TextDecorationOverline)
- overline = resultColor;
- if (decorations & TextDecorationLineThrough)
- linethrough = resultColor;
+ resultColor = styleToUse->visitedDependentDecorationColor();
+ if (decorations & TextDecorationUnderline) {
+ underline.color = resultColor;
+ underline.style = resultStyle;
+ }
+ if (decorations & TextDecorationOverline) {
+ overline.color = resultColor;
+ overline.style = resultStyle;
+ }
+ if (decorations & TextDecorationLineThrough) {
+ linethrough.color = resultColor;
+ linethrough.style = resultStyle;
+ }
}
}
@@ -3052,7 +3221,7 @@ void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
return;
RenderBox* box = toRenderBox(this);
- FloatRect localBounds(FloatPoint(), FloatSize(box->width(), box->height()));
+ FloatRect localBounds(FloatPoint(), FloatSize(box->width().toFloat(), box->height().toFloat()));
FloatRect absBounds = localToAbsoluteQuad(localBounds).boundingBox();
AnnotatedRegionValue region;
@@ -3069,7 +3238,7 @@ void RenderObject::collectAnnotatedRegions(Vector<AnnotatedRegionValue>& regions
return;
addAnnotatedRegions(regions);
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ for (RenderObject* curr = slowFirstChild(); curr; curr = curr->nextSibling())
curr->collectAnnotatedRegions(regions);
}
@@ -3085,14 +3254,7 @@ bool RenderObject::willRenderImage(ImageResource*)
// If we're not in a window (i.e., we're dormant from being in a background tab)
// then we don't want to render either.
- return !document().view()->isOffscreen();
-}
-
-int RenderObject::maximalOutlineSize(PaintPhase p) const
-{
- if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
- return 0;
- return view()->maximalOutlineSize();
+ return document().view()->isVisible();
}
int RenderObject::caretMinOffset() const
@@ -3103,7 +3265,7 @@ int RenderObject::caretMinOffset() const
int RenderObject::caretMaxOffset() const
{
if (isReplaced())
- return node() ? max(1U, node()->childNodeCount()) : 1;
+ return node() ? max(1U, node()->countChildren()) : 1;
if (isHR())
return 1;
return 0;
@@ -3124,22 +3286,6 @@ int RenderObject::nextOffset(int current) const
return current + 1;
}
-void RenderObject::adjustRectForOutlineAndShadow(LayoutRect& rect) const
-{
- int outlineSize = outlineStyleForRepaint()->outlineSize();
- if (const ShadowList* boxShadow = style()->boxShadow()) {
- boxShadow->adjustRectForShadow(rect, outlineSize);
- return;
- }
-
- rect.inflate(outlineSize);
-}
-
-AnimationController& RenderObject::animation() const
-{
- return frame()->animation();
-}
-
bool RenderObject::isInert() const
{
const RenderObject* renderer = this;
@@ -3148,41 +3294,28 @@ bool RenderObject::isInert() const
return renderer->node()->isInert();
}
-void RenderObject::imageChanged(ImageResource* image, const IntRect* rect)
+// touch-action applies to all elements with both width AND height properties.
+// According to the CSS Box Model Spec (http://dev.w3.org/csswg/css-box/#the-width-and-height-properties)
+// width applies to all elements but non-replaced inline elements, table rows, and row groups and
+// height applies to all elements but non-replaced inline elements, table columns, and column groups.
+bool RenderObject::supportsTouchAction() const
{
- imageChanged(static_cast<WrappedImagePtr>(image), rect);
+ if (isInline() && !isReplaced())
+ return false;
+ if (isTableRow() || isRenderTableCol())
+ return false;
+
+ return true;
}
-RenderObject* RenderObject::hoverAncestor() const
+void RenderObject::imageChanged(ImageResource* image, const IntRect* rect)
{
- // When searching for the hover ancestor and encountering a named flow thread,
- // the search will continue with the DOM ancestor of the top-most element
- // in the named flow thread.
- // See https://code.google.com/p/chromium/issues/detail?id=243278
- RenderObject* hoverAncestor = parent();
-
- // Skip anonymous blocks directly flowed into flow threads as it would
- // prevent us from continuing the search on the DOM tree when reaching the named flow thread.
- if (hoverAncestor && hoverAncestor->isAnonymousBlock() && hoverAncestor->parent() && hoverAncestor->parent()->isRenderNamedFlowThread())
- hoverAncestor = hoverAncestor->parent();
-
- if (hoverAncestor && hoverAncestor->isRenderNamedFlowThread()) {
- hoverAncestor = 0;
-
- Node* node = this->node();
- if (node) {
- Node* domAncestorNode = node->parentNode();
- if (domAncestorNode)
- hoverAncestor = domAncestorNode->renderer();
- }
- }
-
- return hoverAncestor;
+ imageChanged(static_cast<WrappedImagePtr>(image), rect);
}
Element* RenderObject::offsetParent() const
{
- if (isRoot() || isBody())
+ if (isDocumentElement() || isBody())
return 0;
if (isOutOfFlowPositioned() && style()->position() == FixedPosition)
@@ -3197,10 +3330,6 @@ Element* RenderObject::offsetParent() const
for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
// Spec: http://www.w3.org/TR/cssom-view/#offset-attributes
- // CSS regions specification says that region flows should return the body element as their offsetParent.
- if (ancestor->isRenderNamedFlowThread())
- return document().body();
-
node = ancestor->node();
if (!node)
@@ -3209,10 +3338,10 @@ Element* RenderObject::offsetParent() const
if (ancestor->isPositioned())
break;
- if (node->hasTagName(HTMLNames::bodyTag))
+ if (isHTMLBodyElement(*node))
break;
- if (!isPositioned() && (isHTMLTableElement(node) || node->hasTagName(tdTag) || node->hasTagName(thTag)))
+ if (!isPositioned() && (isHTMLTableElement(*node) || isHTMLTableCellElement(*node)))
break;
// Webkit specific extension where offsetParent stops at zoom level changes.
@@ -3329,7 +3458,7 @@ FloatRect RenderObject::strokeBoundingBox() const
// Returns the smallest rectangle enclosing all of the painted content
// respecting clipping, masking, filters, opacity, stroke-width and markers
-FloatRect RenderObject::repaintRectInLocalCoordinates() const
+FloatRect RenderObject::paintInvalidationRectInLocalCoordinates() const
{
ASSERT_NOT_REACHED();
return FloatRect();
@@ -3353,25 +3482,35 @@ bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const
return false;
}
-// FIXME: This should really use local coords
-// Works on absolute coords - expensive to call
-bool RenderObject::isContainedInParentBoundingBox() const
+bool RenderObject::isRelayoutBoundaryForInspector() const
{
- if (!parent())
- return false;
+ return objectIsRelayoutBoundary(this);
+}
+
+void RenderObject::clearPaintInvalidationState()
+{
+ setShouldDoFullPaintInvalidationAfterLayout(false);
+ setShouldDoFullPaintInvalidationIfSelfPaintingLayer(false);
+ setOnlyNeededPositionedMovementLayout(false);
+ setShouldInvalidateOverflowForPaint(false);
+ setLayoutDidGetCalled(false);
+ setMayNeedPaintInvalidation(false);
+}
- IntRect parentRect = parent()->absoluteBoundingBoxRect();
- return parentRect.contains(absoluteBoundingBoxRect());
+bool RenderObject::isAllowedToModifyRenderTreeStructure(Document& document)
+{
+ return DeprecatedDisableModifyRenderTreeStructureAsserts::canModifyRenderTreeStateInAnyState()
+ || document.lifecycle().stateAllowsRenderTreeMutations();
}
-bool RenderObject::isRelayoutBoundaryForInspector() const
+DeprecatedDisableModifyRenderTreeStructureAsserts::DeprecatedDisableModifyRenderTreeStructureAsserts()
+ : m_disabler(gModifyRenderTreeStructureAnyState, true)
{
- return objectIsRelayoutBoundary(this);
}
-bool RenderObject::isRenderNamedFlowFragmentContainer() const
+bool DeprecatedDisableModifyRenderTreeStructureAsserts::canModifyRenderTreeStateInAnyState()
{
- return isRenderBlockFlow() && toRenderBlockFlow(this)->renderNamedFlowFragment();
+ return gModifyRenderTreeStructureAnyState;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderObject.h b/chromium/third_party/WebKit/Source/core/rendering/RenderObject.h
index 37044c4e86d..11ca5569050 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderObject.h
@@ -26,48 +26,42 @@
#ifndef RenderObject_h
#define RenderObject_h
+#include "core/dom/DocumentLifecycle.h"
#include "core/dom/Element.h"
#include "core/dom/Position.h"
#include "core/dom/StyleEngine.h"
#include "core/fetch/ImageResourceClient.h"
-#include "core/rendering/CompositingState.h"
-#include "core/rendering/LayoutIndicator.h"
+#include "core/rendering/compositing/CompositingState.h"
#include "core/rendering/PaintPhase.h"
#include "core/rendering/RenderObjectChildList.h"
-#include "core/rendering/ScrollBehavior.h"
+#include "core/rendering/ScrollAlignment.h"
#include "core/rendering/SubtreeLayoutScope.h"
+#include "core/rendering/compositing/CompositingTriggers.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/style/StyleInheritedData.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/LayoutRect.h"
+#include "platform/graphics/CompositingReasons.h"
#include "platform/transforms/TransformationMatrix.h"
namespace WebCore {
class AffineTransform;
-class AnimationController;
class Cursor;
class Document;
class HitTestLocation;
class HitTestResult;
class InlineBox;
class InlineFlowBox;
-class Path;
class Position;
class PseudoStyleRequest;
class RenderBoxModelObject;
-class RenderInline;
class RenderBlock;
class RenderFlowThread;
class RenderGeometryMap;
class RenderLayer;
class RenderLayerModelObject;
-class RenderNamedFlowThread;
-class RenderSVGResourceContainer;
-class RenderTable;
-class RenderTheme;
class RenderView;
-class ResourceLoadPriorityOptimizer;
class TransformState;
struct PaintInfo;
@@ -113,6 +107,21 @@ enum MapCoordinatesMode {
};
typedef unsigned MapCoordinatesFlags;
+enum InvalidationReason {
+ InvalidationIncremental,
+ InvalidationSelfLayout,
+ InvalidationBorderFitLines,
+ InvalidationBorderRadius,
+ InvalidationBoundsChangeWithBackground,
+ InvalidationBoundsChange,
+ InvalidationLocationChange,
+ InvalidationScroll,
+ InvalidationSelection,
+ InvalidationLayer,
+ InvalidationPaint,
+ InvalidationPaintRectangle
+};
+
const int caretWidth = 1;
struct AnnotatedRegionValue {
@@ -135,10 +144,10 @@ const int showTreeCharacterOffset = 39;
class RenderObject : public ImageResourceClient {
friend class RenderBlock;
friend class RenderBlockFlow;
- friend class RenderLayer; // For setParent.
friend class RenderLayerReflectionInfo; // For setParent
friend class RenderLayerScrollableArea; // For setParent.
friend class RenderObjectChildList;
+ WTF_MAKE_NONCOPYABLE(RenderObject);
public:
// Anonymous objects should pass the document as their node, and they will then automatically be
// marked as anonymous in the constructor.
@@ -155,18 +164,13 @@ public:
RenderObject* previousSibling() const { return m_previous; }
RenderObject* nextSibling() const { return m_next; }
- // FIXME: These should be renamed slowFirstChild, slowLastChild, etc.
- // to discourage their use. The virtualChildren() call inside these
- // can be slow for hot code paths.
- // Currently, some subclasses like RenderBlock, override these NON-virtual
- // functions to make these fast when we already have a more specific pointer type.
- RenderObject* firstChild() const
+ RenderObject* slowFirstChild() const
{
if (const RenderObjectChildList* children = virtualChildren())
return children->firstChild();
return 0;
}
- RenderObject* lastChild() const
+ RenderObject* slowLastChild() const
{
if (const RenderObjectChildList* children = virtualChildren())
return children->lastChild();
@@ -213,10 +217,6 @@ public:
return locateFlowThreadContainingBlock();
}
- RenderNamedFlowThread* renderNamedFlowThreadWrapper() const;
-
- virtual bool isEmpty() const { return firstChild() == 0; }
-
#ifndef NDEBUG
void setHasAXObject(bool flag) { m_hasAXObject = flag; }
bool hasAXObject() const { return m_hasAXObject; }
@@ -224,10 +224,10 @@ public:
// Helper class forbidding calls to setNeedsLayout() during its lifetime.
class SetLayoutNeededForbiddenScope {
public:
- explicit SetLayoutNeededForbiddenScope(RenderObject*);
+ explicit SetLayoutNeededForbiddenScope(RenderObject&);
~SetLayoutNeededForbiddenScope();
private:
- RenderObject* m_renderObject;
+ RenderObject& m_renderObject;
bool m_preexistingForbidden;
};
@@ -291,10 +291,13 @@ private:
#endif
void addAbsoluteRectForLayer(LayoutRect& result);
- void setLayerNeedsFullRepaint();
- void setLayerNeedsFullRepaintForPositionedMovementLayout();
+ void setLayerNeedsFullPaintInvalidationForPositionedMovementLayout();
bool requiresAnonymousTableWrappers(const RenderObject*) const;
+ // Gets pseudoStyle from Shadow host(in case of input elements)
+ // or from Parent element.
+ PassRefPtr<RenderStyle> getUncachedPseudoStyleFromParentOrShadowHost() const;
+
public:
#ifndef NDEBUG
void showTreeForThis() const;
@@ -317,11 +320,10 @@ public:
public:
bool isPseudoElement() const { return node() && node()->isPseudoElement(); }
- virtual bool isBR() const { return false; }
virtual bool isBoxModelObject() const { return false; }
+ virtual bool isBR() const { return false; }
+ virtual bool isCanvas() const { return false; }
virtual bool isCounter() const { return false; }
- virtual bool isQuote() const { return false; }
-
virtual bool isDetailsMarker() const { return false; }
virtual bool isEmbeddedObject() const { return false; }
virtual bool isFieldset() const { return false; }
@@ -339,56 +341,44 @@ public:
virtual bool isMenuList() const { return false; }
virtual bool isMeter() const { return false; }
virtual bool isProgress() const { return false; }
+ virtual bool isQuote() const { return false; }
virtual bool isRenderBlock() const { return false; }
virtual bool isRenderBlockFlow() const { return false; }
- virtual bool isRenderSVGBlock() const { return false; };
virtual bool isRenderButton() const { return false; }
+ virtual bool isRenderFlowThread() const { return false; }
+ virtual bool isRenderFullScreen() const { return false; }
+ virtual bool isRenderFullScreenPlaceholder() const { return false; }
+ virtual bool isRenderGrid() const { return false; }
virtual bool isRenderIFrame() const { return false; }
virtual bool isRenderImage() const { return false; }
virtual bool isRenderInline() const { return false; }
+ virtual bool isRenderMultiColumnSet() const { return false; }
virtual bool isRenderPart() const { return false; }
virtual bool isRenderRegion() const { return false; }
- virtual bool isRenderNamedFlowFragment() const { return false; }
+ virtual bool isRenderScrollbarPart() const { return false; }
+ virtual bool isRenderTableCol() const { return false; }
virtual bool isRenderView() const { return false; }
virtual bool isReplica() const { return false; }
-
virtual bool isRuby() const { return false; }
virtual bool isRubyBase() const { return false; }
virtual bool isRubyRun() const { return false; }
virtual bool isRubyText() const { return false; }
-
virtual bool isSlider() const { return false; }
virtual bool isSliderThumb() const { return false; }
virtual bool isTable() const { return false; }
- virtual bool isTableCell() const { return false; }
- virtual bool isRenderTableCol() const { return false; }
virtual bool isTableCaption() const { return false; }
+ virtual bool isTableCell() const { return false; }
virtual bool isTableRow() const { return false; }
virtual bool isTableSection() const { return false; }
- virtual bool isTextControl() const { return false; }
virtual bool isTextArea() const { return false; }
+ virtual bool isTextControl() const { return false; }
virtual bool isTextField() const { return false; }
virtual bool isVideo() const { return false; }
virtual bool isWidget() const { return false; }
- virtual bool isCanvas() const { return false; }
- virtual bool isRenderFullScreen() const { return false; }
- virtual bool isRenderFullScreenPlaceholder() const { return false; }
-
- virtual bool isRenderGrid() const { return false; }
-
- virtual bool isRenderFlowThread() const { return false; }
- virtual bool isRenderNamedFlowThread() const { return false; }
- bool isInFlowRenderFlowThread() const { return isRenderFlowThread() && !isOutOfFlowPositioned(); }
- bool isOutOfFlowRenderFlowThread() const { return isRenderFlowThread() && isOutOfFlowPositioned(); }
- bool isRenderNamedFlowFragmentContainer() const;
-
- virtual bool isRenderMultiColumnBlock() const { return false; }
- virtual bool isRenderMultiColumnSet() const { return false; }
-
- virtual bool isRenderScrollbarPart() const { return false; }
- bool isRoot() const { return document().documentElement() == m_node; }
- bool isBody() const;
+ bool isDocumentElement() const { return document().documentElement() == m_node; }
+ // isBody is called from RenderBox::styleWillChange and is thus quite hot.
+ bool isBody() const { return node() && node()->hasTagName(HTMLNames::bodyTag); }
bool isHR() const;
bool isLegend() const;
@@ -413,7 +403,7 @@ public:
{
m_bitfields.setAncestorLineBoxDirty(value);
if (value)
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
}
enum FlowThreadState {
@@ -429,6 +419,7 @@ public:
// FIXME: Until all SVG renders can be subclasses of RenderSVGModelObject we have
// to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation.
+ virtual bool isSVG() const { return false; }
virtual bool isSVGRoot() const { return false; }
virtual bool isSVGContainer() const { return false; }
virtual bool isSVGTransformableContainer() const { return false; }
@@ -452,7 +443,6 @@ public:
// to inherit from RenderSVGObject -> RenderObject (some need RenderBlock inheritance for instance)
virtual void setNeedsTransformUpdate() { }
virtual void setNeedsBoundariesUpdate();
- virtual bool needsBoundariesUpdate() { return false; }
// Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width.
// This is used for all computation of objectBoundingBox relative units and by SVGLocatable::getBBox().
@@ -465,7 +455,7 @@ public:
// Returns the smallest rectangle enclosing all of the painted content
// respecting clipping, masking, filters, opacity, stroke-width and markers
- virtual FloatRect repaintRectInLocalCoordinates() const;
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const;
// This only returns the transform="" value from the element
// most callsites want localToParentTransform() instead.
@@ -476,7 +466,7 @@ public:
virtual const AffineTransform& localToParentTransform() const;
// SVG uses FloatPoint precise hit testing, and passes the point in parent
- // coordinates instead of in repaint container coordinates. Eventually the
+ // coordinates instead of in paint invalidaiton container coordinates. Eventually the
// rest of the rendering tree will move to a similar model.
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
@@ -529,8 +519,11 @@ public:
};
bool hasBoxDecorations() const { return m_bitfields.boxDecorationState() != NoBoxDecorations; }
bool backgroundIsKnownToBeObscured();
- bool borderImageIsLoadedAndCanBeRendered() const;
- bool mustRepaintBackgroundOrBorder() const;
+ bool canRenderBorderImage() const;
+ bool mustInvalidateBackgroundOrBorderPaintOnWidthChange() const;
+ bool mustInvalidateBackgroundOrBorderPaintOnHeightChange() const;
+ bool mustInvalidateFillLayersPaintOnWidthChange(const FillLayer&) const;
+ bool mustInvalidateFillLayersPaintOnHeightChange(const FillLayer&) const;
bool hasBackground() const { return style()->hasBackground(); }
bool hasEntirelyFixedBackground() const;
@@ -554,6 +547,10 @@ public:
bool preferredLogicalWidthsDirty() const { return m_bitfields.preferredLogicalWidthsDirty(); }
+ bool needsOverflowRecalcAfterStyleChange() const { return m_bitfields.selfNeedsOverflowRecalcAfterStyleChange() || m_bitfields.childNeedsOverflowRecalcAfterStyleChange(); }
+ bool selfNeedsOverflowRecalcAfterStyleChange() const { return m_bitfields.selfNeedsOverflowRecalcAfterStyleChange(); }
+ bool childNeedsOverflowRecalcAfterStyleChange() const { return m_bitfields.childNeedsOverflowRecalcAfterStyleChange(); }
+
bool isSelectionBorder() const;
bool hasClip() const { return isOutOfFlowPositioned() && style()->hasClip(); }
@@ -569,6 +566,8 @@ public:
bool hasBlendMode() const;
+ bool hasShapeOutside() const { return style() && style()->shapeOutside(); }
+
inline bool preservesNewline() const;
// The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
@@ -581,8 +580,7 @@ public:
RenderView* view() const { return document().renderView(); };
FrameView* frameView() const { return document().view(); };
- // Returns true if this renderer is rooted, and optionally returns the hosting view (the root of the hierarchy).
- bool isRooted(RenderView** = 0) const;
+ bool isRooted() const;
Node* node() const
{
@@ -591,7 +589,6 @@ public:
Node* nonPseudoNode() const
{
- ASSERT(!LayoutIndicator::inLayout());
return isPseudoElement() ? 0 : node();
}
@@ -604,26 +601,26 @@ public:
Node* generatingNode() const { return isPseudoElement() ? node()->parentOrShadowHostNode() : node(); }
Document& document() const { return m_node->document(); }
- Frame* frame() const { return document().frame(); }
+ LocalFrame* frame() const { return document().frame(); }
bool hasOutlineAnnotation() const;
bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); }
// Returns the object containing this one. Can be different from parent for positioned elements.
- // If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped
- // is true if the renderer returned is an ancestor of repaintContainer.
- RenderObject* container(const RenderLayerModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const;
+ // If paintInvalidationContainer and paintInvalidationContainerSkipped are not null, on return *paintInvalidationContainerSkipped
+ // is true if the renderer returned is an ancestor of paintInvalidationContainer.
+ RenderObject* container(const RenderLayerModelObject* paintInvalidationContainer = 0, bool* paintInvalidationContainerSkipped = 0) const;
- virtual RenderObject* hoverAncestor() const;
+ virtual RenderObject* hoverAncestor() const { return parent(); }
Element* offsetParent() const;
void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0, SubtreeLayoutScope* = 0);
void setNeedsLayout(MarkingBehavior = MarkContainingBlockChain, SubtreeLayoutScope* = 0);
+ void setNeedsLayoutAndFullPaintInvalidation(MarkingBehavior = MarkContainingBlockChain, SubtreeLayoutScope* = 0);
void clearNeedsLayout();
void setChildNeedsLayout(MarkingBehavior = MarkContainingBlockChain, SubtreeLayoutScope* = 0);
void setNeedsPositionedMovementLayout();
- void setNeedsSimplifiedNormalFlowLayout();
void setPreferredLogicalWidthsDirty(MarkingBehavior = MarkContainingBlockChain);
void clearPreferredLogicalWidthsDirty();
void invalidateContainerPreferredLogicalWidths();
@@ -633,6 +630,11 @@ public:
setNeedsLayout();
setPreferredLogicalWidthsDirty();
}
+ void setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation()
+ {
+ setNeedsLayoutAndFullPaintInvalidation();
+ setPreferredLogicalWidthsDirty();
+ }
void setPositionState(EPosition position)
{
@@ -665,10 +667,12 @@ public:
virtual void paint(PaintInfo&, const LayoutPoint&);
- // Recursive function that computes the size and position of this object and all its descendants.
- virtual void layout();
- virtual void didLayout(ResourceLoadPriorityOptimizer&);
- virtual void didScroll(ResourceLoadPriorityOptimizer&);
+ // Subclasses must reimplement this method to compute the size and position
+ // of this object and all its descendants.
+ virtual void layout() = 0;
+ virtual bool updateImageLoadingPriorities() { return false; }
+ void setHasPendingResourceUpdate(bool hasPendingResourceUpdate) { m_bitfields.setHasPendingResourceUpdate(hasPendingResourceUpdate); }
+ bool hasPendingResourceUpdate() const { return m_bitfields.hasPendingResourceUpdate(); }
/* This function performs a layout only if one is needed. */
void layoutIfNeeded() { if (needsLayout()) layout(); }
@@ -676,17 +680,15 @@ public:
void forceLayout();
void forceChildLayout();
- // True if we can abort layout, leaving a partially laid out tree.
- virtual bool supportsPartialLayout() const { return false; }
-
- // used for element state updates that cannot be fixed with a
- // repaint and do not need a relayout
+ // Used for element state updates that cannot be fixed with a
+ // paint invalidation and do not need a relayout.
virtual void updateFromElement() { }
virtual void addAnnotatedRegions(Vector<AnnotatedRegionValue>&);
void collectAnnotatedRegions(Vector<AnnotatedRegionValue>&);
CompositingState compositingState() const;
+ virtual CompositingReasons additionalCompositingReasons(CompositingTriggerFlags) const;
bool hitTest(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
@@ -698,11 +700,6 @@ public:
virtual void dirtyLinesFromChangedChild(RenderObject*);
- // Called to update a style that is allowed to trigger animations.
- // FIXME: Right now this will typically be called only when updating happens from the DOM on explicit elements.
- // We don't yet handle generated content animation such as first-letter or before/after (we'll worry about this later).
- void setAnimatableStyle(PassRefPtr<RenderStyle>);
-
// Set the style of the object and update the state of the object accordingly.
void setStyle(PassRefPtr<RenderStyle>);
@@ -715,13 +712,10 @@ public:
// returns the containing block level element for this element.
RenderBlock* containingBlock() const;
+ RenderObject* clippingContainer() const;
bool canContainFixedPositionObjects() const
{
- return isRenderView() || (hasTransform() && isRenderBlock()) || isSVGForeignObject() || isOutOfFlowRenderFlowThread();
- }
- bool canContainAbsolutePositionObjects() const
- {
return isRenderView() || (hasTransform() && isRenderBlock()) || isSVGForeignObject();
}
@@ -739,22 +733,23 @@ public:
FloatQuad absoluteToLocalQuad(const FloatQuad&, MapCoordinatesFlags mode = 0) const;
// Convert a local quad into the coordinate system of container, taking transforms into account.
- FloatQuad localToContainerQuad(const FloatQuad&, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags = 0, bool* wasFixed = 0) const;
- FloatPoint localToContainerPoint(const FloatPoint&, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags = 0, bool* wasFixed = 0) const;
+ FloatQuad localToContainerQuad(const FloatQuad&, const RenderLayerModelObject* paintInvalidatinoContainer, MapCoordinatesFlags = 0, bool* wasFixed = 0) const;
+ FloatPoint localToContainerPoint(const FloatPoint&, const RenderLayerModelObject* paintInvalidationContainer, MapCoordinatesFlags = 0, bool* wasFixed = 0) const;
// Return the offset from the container() renderer (excluding transforms). In multi-column layout,
// different offsets apply at different points, so return the offset that applies to the given point.
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
+ virtual LayoutSize offsetFromContainer(const RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
// Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
- LayoutSize offsetFromAncestorContainer(RenderObject*) const;
+ LayoutSize offsetFromAncestorContainer(const RenderObject*) const;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint&) const { }
- // FIXME: useTransforms should go away eventually
- IntRect absoluteBoundingBoxRect(bool useTransform = true) const;
- IntRect absoluteBoundingBoxRectIgnoringTransforms() const { return absoluteBoundingBoxRect(false); }
+ // Computes the position of the given render object in the space of |repaintContainer|.
+ LayoutPoint positionFromPaintInvalidationContainer(const RenderLayerModelObject* paintInvalidationContainer) const;
- bool isContainedInParentBoundingBox() const;
+ IntRect absoluteBoundingBoxRect() const;
+ // FIXME: This function should go away eventually
+ IntRect absoluteBoundingBoxRectIgnoringTransforms() const;
// Build an array of quads in absolute coords for line boxes
virtual void absoluteQuads(Vector<FloatQuad>&, bool* /*wasFixed*/ = 0) const { }
@@ -783,79 +778,91 @@ public:
return style()->visitedDependentColor(colorProperty);
}
- inline Color resolveColor(int colorProperty, Color fallback) const
- {
- Color color = resolveColor(colorProperty);
- return color.isValid() ? color : fallback;
- }
-
- inline Color resolveColor(Color color) const
- {
- return color;
- }
-
// Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
// given new style, without accessing the cache.
PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
// Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead.
- // This is typically only relevant when repainting.
- virtual RenderStyle* outlineStyleForRepaint() const { return style(); }
+ // This is typically only relevant when invalidating paints.
+ virtual RenderStyle* outlineStyleForPaintInvalidation() const { return style(); }
virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
- void getTextDecorationColors(unsigned decorations, Color& underline, Color& overline, Color& linethrough, bool quirksMode = false, bool firstlineStyle = false);
+ struct AppliedTextDecoration {
+ Color color;
+ TextDecorationStyle style;
+ AppliedTextDecoration() : color(Color::transparent), style(TextDecorationStyleSolid) { }
+ };
+
+ void getTextDecorations(unsigned decorations, AppliedTextDecoration& underline, AppliedTextDecoration& overline, AppliedTextDecoration& linethrough, bool quirksMode = false, bool firstlineStyle = false);
// Return the RenderLayerModelObject in the container chain which is responsible for painting this object, or 0
- // if painting is root-relative. This is the container that should be passed to the 'forRepaint'
+ // if painting is root-relative. This is the container that should be passed to the 'forPaintInvalidation'
// methods.
- RenderLayerModelObject* containerForRepaint() const;
- // Actually do the repaint of rect r for this object which has been computed in the coordinate space
- // of repaintContainer. If repaintContainer is 0, repaint via the view.
- void repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const IntRect&) const;
+ const RenderLayerModelObject* containerForPaintInvalidation() const;
+ const RenderLayerModelObject* enclosingCompositedContainer() const;
+ const RenderLayerModelObject* adjustCompositedContainerForSpecialAncestors(const RenderLayerModelObject* paintInvalidationContainer) const;
+ bool isPaintInvalidationContainer() const;
+
+ LayoutRect computePaintInvalidationRect()
+ {
+ return computePaintInvalidationRect(containerForPaintInvalidation());
+ }
+
+ // Returns the paint invalidation rect for this RenderObject in the coordinate space of the paint backing (typically a GraphicsLayer) for |paintInvalidationContainer|.
+ LayoutRect computePaintInvalidationRect(const RenderLayerModelObject* paintInvalidationContainer) const;
+
+ // Returns the rect bounds needed to invalidate the paint of this object, in the coordinate space of the rendering backing of |paintInvalidationContainer|
+ LayoutRect boundsRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const;
- // Repaint the entire object. Called when, e.g., the color of a border changes, or when a border
+ // Actually do the paint invalidate of rect r for this object which has been computed in the coordinate space
+ // of the GraphicsLayer backing of |paintInvalidationContainer|. Note that this coordinaten space is not the same
+ // as the local coordinate space of |paintInvalidationContainer| in the presence of layer squashing.
+ // If |paintInvalidationContainer| is 0, invalidate paints via the view.
+ // FIXME: |paintInvalidationContainer| should never be 0. See crbug.com/363699.
+ void invalidatePaintUsingContainer(const RenderLayerModelObject* paintInvalidationContainer, const IntRect&, InvalidationReason) const;
+
+ // Invalidate the paint of the entire object. Called when, e.g., the color of a border changes, or when a border
// style changes.
- void repaint() const;
+ void paintInvalidationForWholeRenderer() const;
+
+ // Invalidate the paint of a specific subrectangle within a given object. The rect |r| is in the object's coordinate space.
+ void invalidatePaintRectangle(const LayoutRect&) const;
- // Repaint a specific subrectangle within a given object. The rect |r| is in the object's coordinate space.
- void repaintRectangle(const LayoutRect&) const;
+ // Invalidate the paint only if our old bounds and new bounds are different. The caller may pass in newBounds if they are known.
+ bool invalidatePaintAfterLayoutIfNeeded(const RenderLayerModelObject* paintInvalidationContainer, bool wasSelfLayout,
+ const LayoutRect& oldBounds, const LayoutPoint& oldPositionFromPaintInvalidationContainer,
+ const LayoutRect* newBoundsPtr = 0, const LayoutPoint* newPositionFromPaintInvalidationContainer = 0);
- // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known.
- bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, bool wasSelfLayout,
- const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = 0, const LayoutRect* newOutlineBoxPtr = 0);
+ // Walk the tree after layout issuing paint invalidations for renderers that have changed or moved, updating bounds that have changed, and clearing paint invalidation state.
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&);
- virtual void repaintOverflow();
+ virtual void invalidatePaintForOverflow();
+ void invalidatePaintForOverflowIfNeeded();
- bool checkForRepaintDuringLayout() const;
+ bool checkForPaintInvalidation() const;
+ bool checkForPaintInvalidationDuringLayout() const;
- // Returns the rect that should be repainted whenever this object changes. The rect is in the view's
- // coordinate space. This method deals with outlines and overflow.
+ // Returns the rect that should have paint invalidated whenever this object changes. The rect is in the view's
+ // coordinate space. This method deals with outlines and overflow.
LayoutRect absoluteClippedOverflowRect() const
{
- return clippedOverflowRectForRepaint(0);
+ return clippedOverflowRectForPaintInvalidation(0);
}
IntRect pixelSnappedAbsoluteClippedOverflowRect() const;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const;
- virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const;
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap* = 0) const { return LayoutRect(); }
-
- // Given a rect in the object's coordinate space, compute a rect suitable for repainting
- // that rect in the coordinate space of repaintContainer.
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed = false) const;
-
- // If multiple-column layout results in applying an offset to the given point, add the same
- // offset to the given size.
- virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const { }
- LayoutSize offsetForColumns(const LayoutPoint& point) const
- {
- LayoutSize offset;
- adjustForColumns(offset, point);
- return offset;
- }
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const;
+ virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth) const;
- virtual unsigned int length() const { return 1; }
+ // Given a rect in the object's coordinate space, compute a rect suitable for invalidating paints of
+ // that rect in the coordinate space of paintInvalidationContainer.
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed = false) const;
+
+ // Return the offset to the column in which the specified point (in flow-thread coordinates)
+ // lives. This is used to convert a flow-thread point to a visual point.
+ virtual LayoutSize columnOffset(const LayoutPoint&) const { return LayoutSize(); }
+
+ virtual unsigned length() const { return 1; }
bool isFloatingOrOutOfFlowPositioned() const { return (isFloating() || isOutOfFlowPositioned()); }
@@ -864,9 +871,6 @@ 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.
- int maximalOutlineSize(PaintPhase) const;
-
enum SelectionState {
SelectionNone, // The object is not selected.
SelectionStart, // The object either contains the start of a selection run or is the start of a run
@@ -884,8 +888,8 @@ public:
// A single rectangle that encompasses all of the selected objects within this object. Used to determine the tightest
// possible bounding box for the selection.
- LayoutRect selectionRect(bool clipToVisibleContent = true) { return selectionRectForRepaint(0, clipToVisibleContent); }
- virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/ = true) { return LayoutRect(); }
+ LayoutRect selectionRect(bool clipToVisibleContent = true) { return selectionRectForPaintInvalidation(0, clipToVisibleContent); }
+ virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* /*paintInvalidationContainer*/, bool /*clipToVisibleContent*/ = true) { return LayoutRect(); }
virtual bool canBeSelectionLeaf() const { return false; }
bool hasSelectedChildren() const { return selectionState() != SelectionNone; }
@@ -916,7 +920,6 @@ public:
// Virtual function helpers for the deprecated Flexible Box Layout (display: -webkit-box).
virtual bool isDeprecatedFlexibleBox() const { return false; }
- virtual bool isStretchingChildren() const { return false; }
// Virtual function helper for the new FlexibleBox Layout (display: -webkit-flex).
virtual bool isFlexibleBox() const { return false; }
@@ -935,23 +938,25 @@ public:
virtual int previousOffsetForBackwardDeletion(int current) const;
virtual int nextOffset(int current) const;
- virtual void imageChanged(ImageResource*, const IntRect* = 0);
+ virtual void imageChanged(ImageResource*, const IntRect* = 0) OVERRIDE FINAL;
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) { }
- virtual bool willRenderImage(ImageResource*);
+ virtual bool willRenderImage(ImageResource*) OVERRIDE FINAL;
void selectionStartEnd(int& spos, int& epos) const;
void remove() { if (parent()) parent()->removeChild(this); }
- AnimationController& animation() const;
-
bool isInert() const;
+
+ bool supportsTouchAction() const;
+
bool visibleToHitTestRequest(const HitTestRequest& request) const { return style()->visibility() == VISIBLE && (request.ignorePointerEventsNone() || style()->pointerEvents() != PE_NONE) && !isInert(); }
+
bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE && !isInert(); }
// 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(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
// Pushes state onto RenderGeometryMap about how to map coordinates from this renderer to its container, or ancestorToStopAt (whichever is encountered first).
@@ -968,49 +973,64 @@ public:
// Compute a list of hit-test rectangles per layer rooted at this renderer.
virtual void computeLayerHitTestRects(LayerHitTestRects&) const;
- LayoutRect absoluteOutlineBounds() const
- {
- return outlineBoundsForRepaint(0);
- }
-
- // 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.
+ // Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isDocumentElement() is true.
RenderObject* rendererForRootBackground();
RespectImageOrientationEnum shouldRespectImageOrientation() const;
bool isRelayoutBoundaryForInspector() const;
- const LayoutRect& newRepaintRect() const { return m_newRepaintRect; }
- void setNewRepaintRect(const LayoutRect& rect) { m_newRepaintRect = rect; }
+ const LayoutRect& previousPaintInvalidationRect() const { return m_previousPaintInvalidationRect; }
+ void setPreviousPaintInvalidationRect(const LayoutRect& rect) { m_previousPaintInvalidationRect = rect; }
- const LayoutRect& oldRepaintRect() const { return m_oldRepaintRect; }
- void setOldRepaintRect(const LayoutRect& rect) { m_oldRepaintRect = rect; }
+ const LayoutPoint& previousPositionFromPaintInvalidationContainer() const { return m_previousPositionFromPaintInvalidationContainer; }
+ void setPreviousPositionFromPaintInvalidationContainer(const LayoutPoint& location) { m_previousPositionFromPaintInvalidationContainer = location; }
- bool shouldDoFullRepaintAfterLayout() const { return m_bitfields.shouldDoFullRepaintAfterLayout(); }
- void setShouldDoFullRepaintAfterLayout(bool b) { m_bitfields.setShouldDoFullRepaintAfterLayout(b); }
- bool shouldRepaintOverflowIfNeeded() const { return m_bitfields.shouldRepaintOverflowIfNeeded(); }
+ bool shouldDoFullPaintInvalidationAfterLayout() const { return m_bitfields.shouldDoFullPaintInvalidationAfterLayout(); }
+ void setShouldDoFullPaintInvalidationAfterLayout(bool b) { m_bitfields.setShouldDoFullPaintInvalidationAfterLayout(b); }
+ bool shouldInvalidateOverflowForPaint() const { return m_bitfields.shouldInvalidateOverflowForPaint(); }
- void clearRepaintRects()
- {
- setNewRepaintRect(LayoutRect());
- setOldRepaintRect(LayoutRect());
+ bool shouldDoFullPaintInvalidationIfSelfPaintingLayer() const { return m_bitfields.shouldDoFullPaintInvalidationIfSelfPaintingLayer(); }
+ void setShouldDoFullPaintInvalidationIfSelfPaintingLayer(bool b) { m_bitfields.setShouldDoFullPaintInvalidationIfSelfPaintingLayer(b); }
- setShouldDoFullRepaintAfterLayout(false);
- setShouldRepaintOverflowIfNeeded(false);
- setLayoutDidGetCalled(false);
- }
+ bool onlyNeededPositionedMovementLayout() const { return m_bitfields.onlyNeededPositionedMovementLayout(); }
+ void setOnlyNeededPositionedMovementLayout(bool b) { m_bitfields.setOnlyNeededPositionedMovementLayout(b); }
+
+ void clearPaintInvalidationState();
// layoutDidGetCalled indicates whether this render object was re-laid-out
// since the last call to setLayoutDidGetCalled(false) on this object.
bool layoutDidGetCalled() { return m_bitfields.layoutDidGetCalled(); }
void setLayoutDidGetCalled(bool b) { m_bitfields.setLayoutDidGetCalled(b); }
+ bool mayNeedPaintInvalidation() { return m_bitfields.mayNeedPaintInvalidation(); }
+ void setMayNeedPaintInvalidation(bool b)
+ {
+ m_bitfields.setMayNeedPaintInvalidation(b);
+
+ // Make sure our parent is marked as needing invalidation.
+ if (b && parent() && !parent()->mayNeedPaintInvalidation())
+ parent()->setMayNeedPaintInvalidation(b);
+ }
+
+ bool shouldCheckForPaintInvalidationAfterLayout()
+ {
+ return layoutDidGetCalled() || mayNeedPaintInvalidation();
+ }
+
+ bool supportsLayoutStateCachedOffsets() const { return !hasColumns() && !hasTransform() && !hasReflection() && !style()->isFlippedBlocksWritingMode(); }
+
+ void setNeedsOverflowRecalcAfterStyleChange();
+ void markContainingBlocksForOverflowRecalc();
+
protected:
inline bool layerCreationAllowedForSubtree() const;
- // Overrides should call the superclass at the end
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
- // Overrides should call the superclass at the start
+ // Overrides should call the superclass at the end. m_style will be 0 the first time
+ // this function will be called.
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle);
+ // Overrides should call the superclass at the start. |oldStyle| will be 0 the first
+ // time this function is called.
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
void propagateStyleToAnonymousChildren(bool blockChildrenOnly = false);
@@ -1028,11 +1048,10 @@ protected:
void paintFocusRing(PaintInfo&, const LayoutPoint&, RenderStyle*);
void paintOutline(PaintInfo&, const LayoutRect&);
void addPDFURLRect(GraphicsContext*, const LayoutRect&);
+ void addChildFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer);
virtual LayoutRect viewRect() const;
- void adjustRectForOutlineAndShadow(LayoutRect&) const;
-
void clearLayoutRootIfNeeded() const;
virtual void willBeDestroyed();
void postDestroy();
@@ -1057,13 +1076,12 @@ protected:
virtual void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const { };
private:
- RenderBlock* containerForFixedPosition(const RenderLayerModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const;
+ RenderBlock* containerForFixedPosition(const RenderLayerModelObject* paintInvalidationContainer = 0, bool* paintInvalidationContainerSkipped = 0) const;
RenderFlowThread* locateFlowThreadContainingBlock() const;
void removeFromRenderFlowThread();
void removeFromRenderFlowThreadRecursive(RenderFlowThread*);
- bool shouldRepaintForStyleDifference(StyleDifference) const;
bool hasImmediateNonWhitespaceTextChildOrPropertiesDependentOnColor() const;
RenderStyle* cachedFirstLineStyle() const;
@@ -1075,8 +1093,10 @@ private:
#ifndef NDEBUG
void checkBlockPositionedObjectsNeedLayout();
- void checkNotInPartialLayout();
#endif
+ const char* invalidationReasonToString(InvalidationReason) const;
+
+ static bool isAllowedToModifyRenderTreeStructure(Document&);
RefPtr<RenderStyle> m_style;
@@ -1109,18 +1129,25 @@ private:
public:
RenderObjectBitfields(Node* node)
: m_selfNeedsLayout(false)
- // FIXME: shouldDoFullRepaintAfterLayout is needed because we reset
- // the layout bits before repaint when doing repaintAfterLayout.
- // Holding the layout bits until after repaint would remove the need
+ // FIXME: shouldDoFullPaintInvalidationAfterLayout is needed because we reset
+ // the layout bits beforeissing paint invalidations when doing invalidateTreeAfterLayout.
+ // Holding the layout bits until after paint invalidation would remove the need
// for this flag.
- , m_shouldDoFullRepaintAfterLayout(false)
- , m_shouldRepaintOverflowIfNeeded(false)
+ , m_shouldDoFullPaintInvalidationAfterLayout(false)
+ , m_shouldInvalidateOverflowForPaint(false)
+ , m_shouldDoFullPaintInvalidationIfSelfPaintingLayer(false)
+ // FIXME: We should remove mayNeedPaintInvalidation once we are able to
+ // use the other layout flags to detect the same cases. crbug.com/370118
+ , m_mayNeedPaintInvalidation(false)
+ , m_onlyNeededPositionedMovementLayout(false)
, m_needsPositionedMovementLayout(false)
, m_normalChildNeedsLayout(false)
, m_posChildNeedsLayout(false)
, m_needsSimplifiedNormalFlowLayout(false)
, m_preferredLogicalWidthsDirty(false)
, m_floating(false)
+ , m_selfNeedsOverflowRecalcAfterStyleChange(false)
+ , m_childNeedsOverflowRecalcAfterStyleChange(false)
, m_isAnonymous(!node)
, m_isText(false)
, m_isBox(false)
@@ -1142,19 +1169,25 @@ private:
, m_selectionState(SelectionNone)
, m_flowThreadState(NotInsideFlowThread)
, m_boxDecorationState(NoBoxDecorations)
+ , m_hasPendingResourceUpdate(false)
{
}
- // 32 bits have been used in the first word, and 2 in the second.
+ // 32 bits have been used in the first word, and 6 in the second.
ADD_BOOLEAN_BITFIELD(selfNeedsLayout, SelfNeedsLayout);
- ADD_BOOLEAN_BITFIELD(shouldDoFullRepaintAfterLayout, ShouldDoFullRepaintAfterLayout);
- ADD_BOOLEAN_BITFIELD(shouldRepaintOverflowIfNeeded, ShouldRepaintOverflowIfNeeded);
+ ADD_BOOLEAN_BITFIELD(shouldDoFullPaintInvalidationAfterLayout, ShouldDoFullPaintInvalidationAfterLayout);
+ ADD_BOOLEAN_BITFIELD(shouldInvalidateOverflowForPaint, ShouldInvalidateOverflowForPaint);
+ ADD_BOOLEAN_BITFIELD(shouldDoFullPaintInvalidationIfSelfPaintingLayer, ShouldDoFullPaintInvalidationIfSelfPaintingLayer);
+ ADD_BOOLEAN_BITFIELD(mayNeedPaintInvalidation, MayNeedPaintInvalidation);
+ ADD_BOOLEAN_BITFIELD(onlyNeededPositionedMovementLayout, OnlyNeededPositionedMovementLayout);
ADD_BOOLEAN_BITFIELD(needsPositionedMovementLayout, NeedsPositionedMovementLayout);
ADD_BOOLEAN_BITFIELD(normalChildNeedsLayout, NormalChildNeedsLayout);
ADD_BOOLEAN_BITFIELD(posChildNeedsLayout, PosChildNeedsLayout);
ADD_BOOLEAN_BITFIELD(needsSimplifiedNormalFlowLayout, NeedsSimplifiedNormalFlowLayout);
ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty, PreferredLogicalWidthsDirty);
ADD_BOOLEAN_BITFIELD(floating, Floating);
+ ADD_BOOLEAN_BITFIELD(selfNeedsOverflowRecalcAfterStyleChange, SelfNeedsOverflowRecalcAfterStyleChange);
+ ADD_BOOLEAN_BITFIELD(childNeedsOverflowRecalcAfterStyleChange, ChildNeedsOverflowRecalcAfterStyleChange);
ADD_BOOLEAN_BITFIELD(isAnonymous, IsAnonymous);
ADD_BOOLEAN_BITFIELD(isText, IsText);
@@ -1186,6 +1219,9 @@ private:
unsigned m_boxDecorationState : 2; // BoxDecorationState
public:
+
+ ADD_BOOLEAN_BITFIELD(hasPendingResourceUpdate, HasPendingResourceUpdate);
+
bool isOutOfFlowPositioned() const { return m_positionedState == IsOutOfFlowPositioned; }
bool isRelPositioned() const { return m_positionedState == IsRelativelyPositioned; }
bool isStickyPositioned() const { return m_positionedState == IsStickyPositioned; }
@@ -1219,19 +1255,40 @@ private:
void setNeedsSimplifiedNormalFlowLayout(bool b) { m_bitfields.setNeedsSimplifiedNormalFlowLayout(b); }
void setIsDragging(bool b) { m_bitfields.setIsDragging(b); }
void setEverHadLayout(bool b) { m_bitfields.setEverHadLayout(b); }
- void setShouldRepaintOverflowIfNeeded(bool b) { m_bitfields.setShouldRepaintOverflowIfNeeded(b); }
+ void setShouldInvalidateOverflowForPaint(bool b) { m_bitfields.setShouldInvalidateOverflowForPaint(b); }
+ void setSelfNeedsOverflowRecalcAfterStyleChange(bool b) { m_bitfields.setSelfNeedsOverflowRecalcAfterStyleChange(b); }
+ void setChildNeedsOverflowRecalcAfterStyleChange(bool b) { m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(b); }
private:
// Store state between styleWillChange and styleDidChange
static bool s_affectsParentBlock;
- LayoutRect m_oldRepaintRect;
- LayoutRect m_newRepaintRect;
+ // This stores the paint invalidation rect from the previous layout.
+ LayoutRect m_previousPaintInvalidationRect;
+
+ // This stores the position in the paint invalidation container's coordinate.
+ // It is used to detect renderer shifts that forces a full invalidation.
+ LayoutPoint m_previousPositionFromPaintInvalidationContainer;
+};
+
+// FIXME: remove this once the render object lifecycle ASSERTS are no longer hit.
+class DeprecatedDisableModifyRenderTreeStructureAsserts {
+ WTF_MAKE_NONCOPYABLE(DeprecatedDisableModifyRenderTreeStructureAsserts);
+public:
+ DeprecatedDisableModifyRenderTreeStructureAsserts();
+
+ static bool canModifyRenderTreeStateInAnyState();
+
+private:
+ TemporaryChange<bool> m_disabler;
};
+// Allow equality comparisons of RenderObjects by reference or pointer, interchangeably.
+DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(RenderObject)
+
inline bool RenderObject::documentBeingDestroyed() const
{
- return !document().renderer();
+ return document().lifecycle().state() >= DocumentLifecycle::Stopping;
}
inline bool RenderObject::isBeforeContent() const
@@ -1259,27 +1316,30 @@ inline bool RenderObject::isBeforeOrAfterContent() const
return isBeforeContent() || isAfterContent();
}
+// If repaintAfterLayout is enabled, setNeedsLayout() won't cause full paint invalidations as
+// setNeedsLayoutAndFullPaintInvalidation() does. Otherwise the two methods are identical.
inline void RenderObject::setNeedsLayout(MarkingBehavior markParents, SubtreeLayoutScope* layouter)
{
-#ifndef NDEBUG
- checkNotInPartialLayout();
-#endif
ASSERT(!isSetNeedsLayoutForbidden());
bool alreadyNeededLayout = m_bitfields.selfNeedsLayout();
setSelfNeedsLayout(true);
if (!alreadyNeededLayout) {
if (markParents == MarkContainingBlockChain && (!layouter || layouter->root() != this))
markContainingBlocksForLayout(true, 0, layouter);
- if (hasLayer())
- setLayerNeedsFullRepaint();
}
}
+inline void RenderObject::setNeedsLayoutAndFullPaintInvalidation(MarkingBehavior markParents, SubtreeLayoutScope* layouter)
+{
+ setNeedsLayout(markParents, layouter);
+ setShouldDoFullPaintInvalidationAfterLayout(true);
+}
+
inline void RenderObject::clearNeedsLayout()
{
-#ifndef NDEBUG
- checkNotInPartialLayout();
-#endif
+ if (needsPositionedMovementLayoutOnly())
+ setOnlyNeededPositionedMovementLayout(true);
+ setLayoutDidGetCalled(true);
setSelfNeedsLayout(false);
setEverHadLayout(true);
setPosChildNeedsLayout(false);
@@ -1310,19 +1370,7 @@ inline void RenderObject::setNeedsPositionedMovementLayout()
if (!alreadyNeededLayout) {
markContainingBlocksForLayout();
if (hasLayer())
- setLayerNeedsFullRepaintForPositionedMovementLayout();
- }
-}
-
-inline void RenderObject::setNeedsSimplifiedNormalFlowLayout()
-{
- bool alreadyNeededLayout = needsSimplifiedNormalFlowLayout();
- setNeedsSimplifiedNormalFlowLayout(true);
- ASSERT(!isSetNeedsLayoutForbidden());
- if (!alreadyNeededLayout) {
- markContainingBlocksForLayout();
- if (hasLayer())
- setLayerNeedsFullRepaint();
+ setLayerNeedsFullPaintInvalidationForPositionedMovementLayout();
}
}
@@ -1392,6 +1440,12 @@ inline int adjustForAbsoluteZoom(int value, RenderObject* renderer)
return adjustForAbsoluteZoom(value, renderer->style());
}
+inline double adjustDoubleForAbsoluteZoom(double value, RenderObject& renderer)
+{
+ ASSERT(renderer.style());
+ return adjustDoubleForAbsoluteZoom(value, *renderer.style());
+}
+
inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, RenderObject& renderer)
{
ASSERT(renderer.style());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderObjectChildList.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderObjectChildList.cpp
index 80cee464c7d..6fd0358266b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderObjectChildList.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderObjectChildList.cpp
@@ -56,16 +56,21 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render
if (oldChild->isFloatingOrOutOfFlowPositioned())
toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();
- // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
- // that a positioned child got yanked). We also repaint, so that the area exposed when the child
- // disappears gets repainted properly.
- if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
- oldChild->setNeedsLayoutAndPrefWidthsRecalc();
- // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
- if (oldChild->isBody())
- owner->view()->repaint();
- else
- oldChild->repaint();
+ {
+ // FIXME: We should not be allowing repaint during layout. crbug.com/336250
+ AllowPaintInvalidationScope scoper(owner->frameView());
+
+ // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
+ // that a positioned child got yanked). We also repaint, so that the area exposed when the child
+ // disappears gets repainted properly.
+ if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
+ oldChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
+ if (oldChild->isBody())
+ owner->view()->paintInvalidationForWholeRenderer();
+ else
+ oldChild->paintInvalidationForWholeRenderer();
+ }
}
// If we have a line box wrapper, delete it.
@@ -153,7 +158,7 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* n
RenderCounter::rendererSubtreeAttached(newChild);
}
- newChild->setNeedsLayoutAndPrefWidthsRecalc();
+ newChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
if (!owner->normalChildNeedsLayout())
owner->setChildNeedsLayout(); // We may supply the static position for an absolute positioned child.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderOverflow.h b/chromium/third_party/WebKit/Source/core/rendering/RenderOverflow.h
index 2a965c7037a..2860b7cf848 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderOverflow.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderOverflow.h
@@ -50,16 +50,6 @@ public:
const LayoutRect visualOverflowRect() const { return m_visualOverflow; }
LayoutRect contentsVisualOverflowRect() const { return m_contentsVisualOverflow; }
- void setMinYLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setY(overflow); }
- void setMaxYLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setHeight(overflow - m_layoutOverflow.y()); }
- void setMinXLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setX(overflow); }
- void setMaxXLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setWidth(overflow - m_layoutOverflow.x()); }
-
- void setMinYVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setY(overflow); }
- void setMaxYVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setHeight(overflow - m_layoutOverflow.y()); }
- void setMinXVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setX(overflow); }
- void setMaxXVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setWidth(overflow - m_layoutOverflow.x()); }
-
void move(LayoutUnit dx, LayoutUnit dy);
void addLayoutOverflow(const LayoutRect&);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderPart.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderPart.cpp
index c0cbf957881..408a6453598 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderPart.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderPart.cpp
@@ -25,8 +25,8 @@
#include "config.h"
#include "core/rendering/RenderPart.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/plugins/PluginView.h"
#include "core/rendering/HitTestResult.h"
@@ -46,31 +46,14 @@ RenderPart::RenderPart(Element* node)
RenderPart::~RenderPart()
{
- clearWidget();
}
-void RenderPart::setWidget(PassRefPtr<Widget> widget)
+LayerType RenderPart::layerTypeRequired() const
{
- if (widget == this->widget())
- return;
-
- RenderWidget::setWidget(widget);
-
- // make sure the scrollbars are set correctly for restore
- // ### find better fix
- viewCleared();
-}
-
-void RenderPart::viewCleared()
-{
-}
-
-bool RenderPart::requiresLayer() const
-{
- if (RenderWidget::requiresLayer())
- return true;
-
- return requiresAcceleratedCompositing();
+ LayerType type = RenderWidget::layerTypeRequired();
+ if (type != NoLayer)
+ return type;
+ return ForcedLayer;
}
bool RenderPart::requiresAcceleratedCompositing() const
@@ -104,18 +87,15 @@ bool RenderPart::needsPreferredWidthsRecalculation() const
return embeddedContentBox();
}
-RenderBox* RenderPart::embeddedContentBox() const
-{
- if (!node() || !widget() || !widget()->isFrameView())
- return 0;
- return toFrameView(widget())->embeddedContentBox();
-}
-
bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
if (!widget() || !widget()->isFrameView() || !request.allowsChildFrameContent())
return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
+ // FIXME: Until RemoteFrames use RemoteFrameViews, we need an explicit check here.
+ if (toFrameView(widget())->frame().isRemoteFrameTemporary())
+ return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
+
FrameView* childFrameView = toFrameView(widget());
RenderView* childRoot = childFrameView->renderView();
@@ -149,4 +129,11 @@ bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& resul
return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
}
+CompositingReasons RenderPart::additionalCompositingReasons(CompositingTriggerFlags) const
+{
+ if (requiresAcceleratedCompositing())
+ return CompositingReasonIFrame;
+ return CompositingReasonNone;
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderPart.h b/chromium/third_party/WebKit/Source/core/rendering/RenderPart.h
index f26a7e242c5..f0a1699740c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderPart.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderPart.h
@@ -33,22 +33,20 @@ public:
explicit RenderPart(Element*);
virtual ~RenderPart();
- virtual void setWidget(PassRefPtr<Widget>) OVERRIDE FINAL;
- virtual void viewCleared();
-
bool requiresAcceleratedCompositing() const;
virtual bool needsPreferredWidthsRecalculation() const OVERRIDE FINAL;
- virtual RenderBox* embeddedContentBox() const OVERRIDE FINAL;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
protected:
- virtual bool requiresLayer() const;
+ virtual LayerType layerTypeRequired() const OVERRIDE;
private:
virtual bool isRenderPart() const OVERRIDE FINAL { return true; }
- virtual const char* renderName() const { return "RenderPart"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderPart"; }
+
+ virtual CompositingReasons additionalCompositingReasons(CompositingTriggerFlags) const OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderPart, isRenderPart());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.cpp
index 9bf99a86a3d..b3d994d6c3c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.cpp
@@ -54,8 +54,8 @@ void RenderProgress::updateFromElement()
m_position = element->position();
updateAnimationState();
- repaint();
- RenderBlock::updateFromElement();
+ paintInvalidationForWholeRenderer();
+ RenderBlockFlow::updateFromElement();
}
double RenderProgress::animationProgress() const
@@ -71,9 +71,9 @@ bool RenderProgress::isDeterminate() const
void RenderProgress::animationTimerFired(Timer<RenderProgress>*)
{
- repaint();
+ paintInvalidationForWholeRenderer();
if (!m_animationTimer.isActive() && m_animating)
- m_animationTimer.startOneShot(m_animationRepeatInterval);
+ m_animationTimer.startOneShot(m_animationRepeatInterval, FROM_HERE);
}
void RenderProgress::updateAnimationState()
@@ -88,7 +88,7 @@ void RenderProgress::updateAnimationState()
m_animating = animating;
if (m_animating) {
m_animationStartTime = currentTime();
- m_animationTimer.startOneShot(m_animationRepeatInterval);
+ m_animationTimer.startOneShot(m_animationRepeatInterval, FROM_HERE);
} else
m_animationTimer.stop();
}
@@ -98,7 +98,7 @@ HTMLProgressElement* RenderProgress::progressElement() const
if (!node())
return 0;
- if (isHTMLProgressElement(node()))
+ if (isHTMLProgressElement(*node()))
return toHTMLProgressElement(node());
ASSERT(node()->shadowHost());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.h b/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.h
index bd1cac97f15..18d5c5d3e9f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderProgress.h
@@ -37,14 +37,13 @@ public:
double animationStartTime() const { return m_animationStartTime; }
bool isDeterminate() const;
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
HTMLProgressElement* progressElement() const;
private:
- virtual const char* renderName() const { return "RenderProgress"; }
- virtual bool isProgress() const { return true; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual const char* renderName() const OVERRIDE { return "RenderProgress"; }
+ virtual bool isProgress() const OVERRIDE { return true; }
void animationTimerFired(Timer<RenderProgress>*);
void updateAnimationState();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.cpp
index 0614d3aade2..864f98807e9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.cpp
@@ -34,8 +34,7 @@
#include "core/rendering/FlowThreadController.h"
#include "core/rendering/HitTestLocation.h"
#include "core/rendering/PaintInfo.h"
-#include "core/rendering/RenderBoxRegionInfo.h"
-#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderView.h"
using namespace std;
@@ -45,11 +44,7 @@ namespace WebCore {
RenderRegion::RenderRegion(Element* element, RenderFlowThread* flowThread)
: RenderBlockFlow(element)
, m_flowThread(flowThread)
- , m_parentNamedFlowThread(0)
- , m_computedAutoHeight(-1)
, m_isValid(false)
- , m_hasCustomRegionStyle(false)
- , m_hasAutoLogicalHeight(false)
{
}
@@ -62,29 +57,12 @@ LayoutUnit RenderRegion::pageLogicalWidth() const
LayoutUnit RenderRegion::pageLogicalHeight() const
{
ASSERT(m_flowThread);
- if (hasComputedAutoHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
- ASSERT(hasAutoLogicalHeight());
- return computedAutoHeight();
- }
return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
}
-// This method returns the maximum page size of a region with auto-height. This is the initial
-// height value for auto-height regions in the first layout phase of the parent named flow.
-LayoutUnit RenderRegion::maxPageLogicalHeight() const
-{
- ASSERT(m_flowThread);
- ASSERT(hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase());
- return style()->logicalMaxHeight().isUndefined() ? RenderFlowThread::maxLogicalHeight() : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
-}
-
LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const
{
ASSERT(m_flowThread);
- if (hasComputedAutoHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
- ASSERT(hasAutoLogicalHeight());
- return computedAutoHeight();
- }
return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
}
@@ -97,54 +75,30 @@ LayoutRect RenderRegion::overflowRectForFlowThreadPortion(const LayoutRect& flow
{
ASSERT(isValid());
- bool isLastRegionWithRegionFragmentBreak = (isLastPortion && (style()->regionFragment() == BreakRegionFragment));
- if (hasOverflowClip() || isLastRegionWithRegionFragmentBreak)
+ if (hasOverflowClip())
return flowThreadPortionRect;
LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect();
// Only clip along the flow thread axis.
- LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline);
LayoutRect clipRect;
if (m_flowThread->isHorizontalWritingMode()) {
- LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect.y();
- LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
- bool clipX = style()->overflowX() != OVISIBLE;
- LayoutUnit minX = clipX ? flowThreadPortionRect.x() : min(flowThreadPortionRect.x(), flowThreadOverflow.x() - outlineSize);
- LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : max(flowThreadPortionRect.maxX(), (flowThreadOverflow.maxX() + outlineSize));
+ LayoutUnit minY = isFirstPortion ? flowThreadOverflow.y() : flowThreadPortionRect.y();
+ LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) : flowThreadPortionRect.maxY();
+ LayoutUnit minX = min(flowThreadPortionRect.x(), flowThreadOverflow.x());
+ LayoutUnit maxX = max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX());
clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
} else {
- LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect.x();
- LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
- bool clipY = style()->overflowY() != OVISIBLE;
- LayoutUnit minY = clipY ? flowThreadPortionRect.y() : min(flowThreadPortionRect.y(), (flowThreadOverflow.y() - outlineSize));
- LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY() + outlineSize));
+ LayoutUnit minX = isFirstPortion ? flowThreadOverflow.x() : flowThreadPortionRect.x();
+ LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) : flowThreadPortionRect.maxX();
+ LayoutUnit minY = min(flowThreadPortionRect.y(), (flowThreadOverflow.y()));
+ LayoutUnit maxY = max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY()));
clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
}
return clipRect;
}
-RegionOversetState RenderRegion::regionOversetState() const
-{
- if (isValid() && element())
- return element()->regionOversetState();
-
- return RegionUndefined;
-}
-
-void RenderRegion::setRegionOversetState(RegionOversetState state)
-{
- if (element())
- element()->setRegionOversetState(state);
-}
-
-Element* RenderRegion::element() const
-{
- ASSERT(nodeForRegion() && nodeForRegion()->isElementNode());
- return toElement(nodeForRegion());
-}
-
LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
{
return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
@@ -164,148 +118,10 @@ bool RenderRegion::isLastRegion() const
return m_flowThread->lastRegion() == this;
}
-static bool shouldPaintRegionContentsInPhase(PaintPhase phase)
-{
- return phase == PaintPhaseForeground
- || phase == PaintPhaseSelection
- || phase == PaintPhaseTextClip;
-}
-
-void RenderRegion::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
- if (style()->visibility() != VISIBLE)
- return;
-
- RenderBlock::paintObject(paintInfo, paintOffset);
-
- if (!isValid())
- return;
-
- // Delegate painting of content in region to RenderFlowThread.
- // RenderFlowThread is a self painting layer (being a positioned object) who is painting its children, the collected objects.
- // Since we do not want to paint the flow thread content multiple times (for each painting phase of the region object),
- // we allow the flow thread painting only in certain phases.
- if (!shouldPaintRegionContentsInPhase(paintInfo.phase))
- return;
-
- setRegionObjectsRegionStyle();
- m_flowThread->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
- restoreRegionObjectsOriginalStyle();
-}
-
-// Hit Testing
-bool RenderRegion::hitTestFlowThreadContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
-{
- if (!isValid() || action != HitTestForeground)
- return false;
-
- LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
- boundsRect.moveBy(accumulatedOffset);
- if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
- if (m_flowThread->hitTestFlowThreadPortionInRegion(this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), request, result,
- locationInContainer, LayoutPoint(accumulatedOffset.x() + borderLeft() + paddingLeft(), accumulatedOffset.y() + borderTop() + paddingTop())))
- return true;
- }
-
- return false;
-}
-
-void RenderRegion::checkRegionStyle()
-{
- ASSERT(m_flowThread);
- bool customRegionStyle = false;
-
- // FIXME: Region styling doesn't work for pseudo elements.
- if (isElementBasedRegion())
- customRegionStyle = view()->document().ensureStyleResolver().checkRegionStyle(this->element());
-
- setHasCustomRegionStyle(customRegionStyle);
- m_flowThread->checkRegionsWithStyling();
-}
-
-void RenderRegion::incrementAutoLogicalHeightCount()
-{
- ASSERT(isValid());
- ASSERT(m_hasAutoLogicalHeight);
-
- m_flowThread->incrementAutoLogicalHeightRegions();
-}
-
-void RenderRegion::decrementAutoLogicalHeightCount()
-{
- ASSERT(isValid());
-
- m_flowThread->decrementAutoLogicalHeightRegions();
-}
-
-void RenderRegion::updateRegionHasAutoLogicalHeightFlag()
-{
- ASSERT(m_flowThread);
-
- if (!isValid())
- return;
-
- bool didHaveAutoLogicalHeight = m_hasAutoLogicalHeight;
- m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
- if (m_hasAutoLogicalHeight != didHaveAutoLogicalHeight) {
- if (m_hasAutoLogicalHeight) {
- incrementAutoLogicalHeightCount();
- } else {
- clearComputedAutoHeight();
- decrementAutoLogicalHeightCount();
- }
- }
-}
-
-bool RenderRegion::shouldHaveAutoLogicalHeight() const
-{
- bool hasSpecifiedEndpointsForHeight = style()->logicalTop().isSpecified() && style()->logicalBottom().isSpecified();
- bool hasAnchoredEndpointsForHeight = isOutOfFlowPositioned() && hasSpecifiedEndpointsForHeight;
- bool hasAutoHeightStyle = style()->logicalHeight().isAuto() || style()->logicalHeight().isFitContent()
- || style()->logicalHeight().isMaxContent() || style()->logicalHeight().isMinContent();
- return hasAutoHeightStyle && !hasAnchoredEndpointsForHeight;
-}
-
-void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderBlock::styleDidChange(diff, oldStyle);
-
- // If the region is not attached to any thread, there is no need to check
- // whether the region has region styling since no content will be displayed
- // into the region.
- if (!m_flowThread) {
- setHasCustomRegionStyle(false);
- return;
- }
-
- checkRegionStyle();
- updateRegionHasAutoLogicalHeightFlag();
-
- if (oldStyle && oldStyle->writingMode() != style()->writingMode())
- m_flowThread->regionChangedWritingMode(this);
-}
-
-void RenderRegion::layoutBlock(bool relayoutChildren, LayoutUnit)
+void RenderRegion::layoutBlock(bool relayoutChildren)
{
RenderBlockFlow::layoutBlock(relayoutChildren);
- if (isValid()) {
- LayoutRect oldRegionRect(flowThreadPortionRect());
- if (!isHorizontalWritingMode())
- oldRegionRect = oldRegionRect.transposedRect();
-
- if (hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
- m_flowThread->invalidateRegions();
- clearComputedAutoHeight();
- return;
- }
-
- if (!isRenderRegionSet() && (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight())) {
- // This can happen even if we are in the inConstrainedLayoutPhase and it will trigger a pathological layout of the flow thread.
- m_flowThread->invalidateRegions();
- }
- }
-
// FIXME: We need to find a way to set up overflow properly. Our flow thread hasn't gotten a layout
// yet, so we can't look to it for correct information. It's possible we could wait until after the RenderFlowThread
// gets a layout, and then try to propagate overflow information back to the region, and then mark for a second layout.
@@ -314,8 +130,6 @@ void RenderRegion::layoutBlock(bool relayoutChildren, LayoutUnit)
// The big problem though is that overflow needs to be region-specific. We can't simply use the RenderFlowThread's global
// overflow values, since then we'd always think any narrow region had huge overflow (all the way to the width of the
// RenderFlowThread itself).
- //
- // We'll need to expand RenderBoxRegionInfo to also hold left and right overflow values.
}
void RenderRegion::repaintFlowThreadContent(const LayoutRect& repaintRect) const
@@ -345,30 +159,7 @@ void RenderRegion::repaintFlowThreadContentRectangle(const LayoutRect& repaintRe
flipForWritingMode(clippedRect);
// Issue the repaint.
- repaintRectangle(clippedRect);
-}
-
-void RenderRegion::installFlowThread()
-{
- ASSERT(view());
-
- m_flowThread = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
-
- // By now the flow thread should already be added to the rendering tree,
- // so we go up the rendering parents and check that this region is not part of the same
- // flow that it actually needs to display. It would create a circular reference.
- RenderObject* parentObject = parent();
- m_parentNamedFlowThread = 0;
- for ( ; parentObject; parentObject = parentObject->parent()) {
- 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_parentNamedFlowThread)
- m_flowThread = 0;
- break;
- }
- }
+ invalidatePaintRectangle(clippedRect);
}
void RenderRegion::attachRegion()
@@ -379,72 +170,19 @@ void RenderRegion::attachRegion()
// A region starts off invalid.
setIsValid(false);
- // Initialize the flow thread reference and create the flow thread object if needed.
- // The flow thread lifetime is influenced by the number of regions attached to it,
- // and we are attaching the region to the flow thread.
- installFlowThread();
-
if (!m_flowThread)
return;
// Only after adding the region to the thread, the region is marked to be valid.
m_flowThread->addRegionToThread(this);
-
- // The region just got attached to the flow thread, lets check whether
- // it has region styling rules associated.
- checkRegionStyle();
-
- if (!isValid())
- return;
-
- m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
- if (hasAutoLogicalHeight())
- incrementAutoLogicalHeightCount();
}
void RenderRegion::detachRegion()
{
if (m_flowThread) {
m_flowThread->removeRegionFromThread(this);
- if (hasAutoLogicalHeight())
- decrementAutoLogicalHeightCount();
+ m_flowThread = 0;
}
- m_flowThread = 0;
-}
-
-RenderBoxRegionInfo* RenderRegion::renderBoxRegionInfo(const RenderBox* box) const
-{
- ASSERT(isValid());
- return m_renderBoxRegionInfo.get(box);
-}
-
-RenderBoxRegionInfo* RenderRegion::setRenderBoxRegionInfo(const RenderBox* box, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
- bool containingBlockChainIsInset)
-{
- ASSERT(isValid());
-
- OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullptr).iterator->value;
- if (boxInfo)
- *boxInfo = RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset);
- else
- boxInfo = adoptPtr(new RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset));
-
- return boxInfo.get();
-}
-
-PassOwnPtr<RenderBoxRegionInfo> RenderRegion::takeRenderBoxRegionInfo(const RenderBox* box)
-{
- return m_renderBoxRegionInfo.take(box);
-}
-
-void RenderRegion::removeRenderBoxRegionInfo(const RenderBox* box)
-{
- m_renderBoxRegionInfo.remove(box);
-}
-
-void RenderRegion::deleteAllRenderBoxRegionInfo()
-{
- m_renderBoxRegionInfo.clear();
}
LayoutUnit RenderRegion::logicalTopOfFlowThreadContentRect(const LayoutRect& rect) const
@@ -459,167 +197,24 @@ LayoutUnit RenderRegion::logicalBottomOfFlowThreadContentRect(const LayoutRect&
return flowThread()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
}
-void RenderRegion::setRegionObjectsRegionStyle()
-{
- if (!hasCustomRegionStyle())
- return;
-
- // Start from content nodes and recursively compute the style in region for the render objects below.
- // If the style in region was already computed, used that style instead of computing a new one.
- RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
- const NamedFlowContentNodes& contentNodes = namedFlow->contentNodes();
-
- for (NamedFlowContentNodes::const_iterator iter = contentNodes.begin(), end = contentNodes.end(); iter != end; ++iter) {
- const Node* node = *iter;
- // The list of content nodes contains also the nodes with display:none.
- if (!node->renderer())
- continue;
-
- RenderObject* object = node->renderer();
- // If the content node does not flow any of its children in this region,
- // we do not compute any style for them in this region.
- if (!flowThread()->objectInFlowRegion(object, this))
- continue;
-
- // If the object has style in region, use that instead of computing a new one.
- RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(object);
- RefPtr<RenderStyle> objectStyleInRegion;
- bool objectRegionStyleCached = false;
- if (it != m_renderObjectRegionStyle.end()) {
- objectStyleInRegion = it->value.style;
- ASSERT(it->value.cached);
- objectRegionStyleCached = true;
- } else {
- objectStyleInRegion = computeStyleInRegion(object);
- }
-
- setObjectStyleInRegion(object, objectStyleInRegion, objectRegionStyleCached);
-
- computeChildrenStyleInRegion(object);
- }
-}
-
-void RenderRegion::restoreRegionObjectsOriginalStyle()
-{
- if (!hasCustomRegionStyle())
- return;
-
- RenderObjectRegionStyleMap temp;
- for (RenderObjectRegionStyleMap::iterator iter = m_renderObjectRegionStyle.begin(), end = m_renderObjectRegionStyle.end(); iter != end; ++iter) {
- RenderObject* object = const_cast<RenderObject*>(iter->key);
- RefPtr<RenderStyle> objectRegionStyle = object->style();
- RefPtr<RenderStyle> objectOriginalStyle = iter->value.style;
- object->setStyleInternal(objectOriginalStyle);
-
- bool shouldCacheRegionStyle = iter->value.cached;
- if (!shouldCacheRegionStyle) {
- // Check whether we should cache the computed style in region.
- unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
- StyleDifference styleDiff = objectOriginalStyle->diff(objectRegionStyle.get(), changedContextSensitiveProperties);
- if (styleDiff < StyleDifferenceLayoutPositionedMovementOnly)
- shouldCacheRegionStyle = true;
- }
- if (shouldCacheRegionStyle) {
- ObjectRegionStyleInfo styleInfo;
- styleInfo.style = objectRegionStyle;
- styleInfo.cached = true;
- temp.set(object, styleInfo);
- }
- }
-
- m_renderObjectRegionStyle.swap(temp);
-}
-
void RenderRegion::insertedIntoTree()
{
- RenderBlock::insertedIntoTree();
+ RenderBlockFlow::insertedIntoTree();
attachRegion();
}
void RenderRegion::willBeRemovedFromTree()
{
- RenderBlock::willBeRemovedFromTree();
+ RenderBlockFlow::willBeRemovedFromTree();
detachRegion();
}
-PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderObject* object)
-{
- ASSERT(object);
- ASSERT(object->view());
- ASSERT(!object->isAnonymous());
- ASSERT(object->node() && object->node()->isElementNode());
-
- // FIXME: Region styling fails for pseudo-elements because the renderers don't have a node.
- Element* element = toElement(object->node());
- RefPtr<RenderStyle> renderObjectRegionStyle = object->view()->document().ensureStyleResolver().styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
-
- return renderObjectRegionStyle.release();
-}
-
-void RenderRegion::computeChildrenStyleInRegion(const RenderObject* object)
-{
- for (RenderObject* child = object->lastChild(); child; child = child->previousSibling()) {
-
- RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(child);
-
- RefPtr<RenderStyle> childStyleInRegion;
- bool objectRegionStyleCached = false;
- if (it != m_renderObjectRegionStyle.end()) {
- childStyleInRegion = it->value.style;
- objectRegionStyleCached = true;
- } else {
- if (child->isAnonymous() || child->isInFlowRenderFlowThread())
- childStyleInRegion = RenderStyle::createAnonymousStyleWithDisplay(object->style(), child->style()->display());
- else if (child->isText())
- childStyleInRegion = RenderStyle::clone(object->style());
- else
- childStyleInRegion = computeStyleInRegion(child);
- }
-
- setObjectStyleInRegion(child, childStyleInRegion, objectRegionStyleCached);
-
- computeChildrenStyleInRegion(child);
- }
-}
-
-void RenderRegion::setObjectStyleInRegion(RenderObject* object, PassRefPtr<RenderStyle> styleInRegion, bool objectRegionStyleCached)
-{
- ASSERT(object->flowThreadContainingBlock());
-
- RefPtr<RenderStyle> objectOriginalStyle = object->style();
- object->setStyleInternal(styleInRegion);
-
- if (object->isBoxModelObject() && !object->hasBoxDecorations()) {
- bool hasBoxDecorations = object->isTableCell()
- || object->style()->hasBackground()
- || object->style()->hasBorder()
- || object->style()->hasAppearance()
- || object->style()->boxShadow();
- object->setHasBoxDecorations(hasBoxDecorations);
- }
-
- ObjectRegionStyleInfo styleInfo;
- styleInfo.style = objectOriginalStyle;
- styleInfo.cached = objectRegionStyleCached;
- m_renderObjectRegionStyle.set(object, styleInfo);
-}
-
-void RenderRegion::clearObjectStyleInRegion(const RenderObject* object)
-{
- ASSERT(object);
- m_renderObjectRegionStyle.remove(object);
-
- // Clear the style for the children of this object.
- for (RenderObject* child = object->lastChild(); child; child = child->previousSibling())
- clearObjectStyleInRegion(child);
-}
-
void RenderRegion::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
if (!isValid()) {
- RenderBlock::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
+ RenderBlockFlow::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
return;
}
@@ -627,62 +222,4 @@ void RenderRegion::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, La
maxLogicalWidth = m_flowThread->maxPreferredLogicalWidth();
}
-void RenderRegion::getRanges(Vector<RefPtr<Range> >& rangeObjects) const
-{
- RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
- namedFlow->getRanges(rangeObjects, this);
-}
-
-void RenderRegion::updateLogicalHeight()
-{
- RenderBlock::updateLogicalHeight();
-
- if (!hasAutoLogicalHeight())
- return;
-
- // We want to update the logical height based on the computed auto-height
- // only if the view is in the layout phase in which all the
- // auto logical height regions have a computed auto-height.
- if (!m_flowThread->inConstrainedLayoutPhase())
- return;
-
- // There may be regions with auto logical height that during the prerequisite layout phase
- // did not have the chance to layout flow thread content. Because of that, these regions do not
- // have a computedAutoHeight and they will not be able to fragment any flow
- // thread content.
- if (!hasComputedAutoHeight())
- return;
-
- LayoutUnit autoHeight = hasOverrideHeight() ? overrideLogicalContentHeight() : computedAutoHeight();
-
- LayoutUnit newLogicalHeight = autoHeight + borderAndPaddingLogicalHeight();
- ASSERT(newLogicalHeight < RenderFlowThread::maxLogicalHeight());
- if (newLogicalHeight > logicalHeight()) {
- setLogicalHeight(newLogicalHeight);
- // Recalculate position of the render block after new logical height is set.
- // (needed in absolute positioning case with bottom alignment for example)
- RenderBlock::updateLogicalHeight();
- }
-}
-
-Node* RenderRegion::nodeForRegion() const
-{
- if (parent() && isRenderNamedFlowFragment())
- return parent()->node();
- return node();
-}
-
-Node* RenderRegion::generatingNodeForRegion() const
-{
- if (parent() && isRenderNamedFlowFragment())
- return parent()->generatingNode();
- return generatingNode();
-}
-
-bool RenderRegion::isElementBasedRegion() const
-{
- Node* node = nodeForRegion();
- return node && node->isElementNode() && !node->isPseudoElement();
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.h b/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.h
index c05d61359b2..d1a134c6b5f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRegion.h
@@ -37,20 +37,13 @@ namespace WebCore {
struct LayerFragment;
typedef Vector<LayerFragment, 1> LayerFragments;
-class RenderBox;
-class RenderBoxRegionInfo;
class RenderFlowThread;
-class RenderNamedFlowThread;
class RenderRegion : public RenderBlockFlow {
public:
explicit RenderRegion(Element*, RenderFlowThread*);
- virtual bool isRenderRegion() const OVERRIDE { return true; }
-
- bool hitTestFlowThreadContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
-
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual bool isRenderRegion() const OVERRIDE FINAL { return true; }
void setFlowThreadPortionRect(const LayoutRect& rect) { m_flowThreadPortionRect = rect; }
LayoutRect flowThreadPortionRect() const { return m_flowThreadPortionRect; }
@@ -59,167 +52,64 @@ public:
void attachRegion();
void detachRegion();
- RenderNamedFlowThread* parentNamedFlowThread() const { return m_parentNamedFlowThread; }
RenderFlowThread* flowThread() const { return m_flowThread; }
// Valid regions do not create circular dependencies with other flows.
bool isValid() const { return m_isValid; }
void setIsValid(bool valid) { m_isValid = valid; }
- bool hasCustomRegionStyle() const { return m_hasCustomRegionStyle; }
- void setHasCustomRegionStyle(bool hasCustomRegionStyle) { m_hasCustomRegionStyle = hasCustomRegionStyle; }
-
- RenderBoxRegionInfo* renderBoxRegionInfo(const RenderBox*) const;
- RenderBoxRegionInfo* setRenderBoxRegionInfo(const RenderBox*, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
- bool containingBlockChainIsInset);
- PassOwnPtr<RenderBoxRegionInfo> takeRenderBoxRegionInfo(const RenderBox*);
- void removeRenderBoxRegionInfo(const RenderBox*);
-
- void deleteAllRenderBoxRegionInfo();
-
bool isFirstRegion() const;
bool isLastRegion() const;
- void clearObjectStyleInRegion(const RenderObject*);
-
- RegionOversetState regionOversetState() const;
- void setRegionOversetState(RegionOversetState);
-
- // These methods represent the width and height of a "page" and for a RenderRegion they are just the
- // content width and content height of a region. For RenderRegionSets, however, they will be the width and
- // height of a single column or page in the set.
+ // These methods represent the width and height of a "page" and for a RenderRegion they are just
+ // the content width and content height of a region. For RenderMultiColumnSets, however, they
+ // will be the width and height of a single column or page in the set.
virtual LayoutUnit pageLogicalWidth() const;
virtual LayoutUnit pageLogicalHeight() const;
- virtual LayoutUnit maxPageLogicalHeight() const;
LayoutUnit logicalTopOfFlowThreadContentRect(const LayoutRect&) const;
LayoutUnit logicalBottomOfFlowThreadContentRect(const LayoutRect&) const;
LayoutUnit logicalTopForFlowThreadContent() const { return logicalTopOfFlowThreadContentRect(flowThreadPortionRect()); };
LayoutUnit logicalBottomForFlowThreadContent() const { return logicalBottomOfFlowThreadContentRect(flowThreadPortionRect()); };
- void getRanges(Vector<RefPtr<Range> >&) const;
-
// This method represents the logical height of the entire flow thread portion used by the region or set.
// For RenderRegions it matches logicalPaginationHeight(), but for sets it is the height of all the pages
// or columns added together.
virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const;
- bool hasAutoLogicalHeight() const { return m_hasAutoLogicalHeight; }
-
- const LayoutUnit& computedAutoHeight() const
- {
- ASSERT(hasComputedAutoHeight());
- return m_computedAutoHeight;
- }
-
- void setComputedAutoHeight(LayoutUnit computedAutoHeight)
- {
- ASSERT(computedAutoHeight >= 0);
- m_computedAutoHeight = computedAutoHeight;
- }
-
- void clearComputedAutoHeight()
- {
- m_computedAutoHeight = -1;
- }
-
- bool hasComputedAutoHeight() const { return (m_computedAutoHeight >= 0); }
-
// The top of the nearest page inside the region. For RenderRegions, this is just the logical top of the
// flow thread portion we contain. For sets, we have to figure out the top of the nearest column or
// page.
virtual LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
- virtual void expandToEncompassFlowThreadContentsIfNeeded() { };
-
- // Whether or not this region is a set.
- virtual bool isRenderRegionSet() const { return false; }
-
virtual void repaintFlowThreadContent(const LayoutRect& repaintRect) const;
virtual void collectLayerFragments(LayerFragments&, const LayoutRect&, const LayoutRect&) { }
- virtual bool canHaveChildren() const OVERRIDE { return false; }
- virtual bool canHaveGeneratedChildren() const OVERRIDE { return true; }
-
- bool isElementBasedRegion() const;
-
- Node* nodeForRegion() const;
- Node* generatingNodeForRegion() const;
+ virtual bool canHaveChildren() const OVERRIDE FINAL { return false; }
+ virtual bool canHaveGeneratedChildren() const OVERRIDE FINAL { return true; }
virtual const char* renderName() const OVERRIDE { return "RenderRegion"; }
protected:
- void setRegionObjectsRegionStyle();
- void restoreRegionObjectsOriginalStyle();
-
- virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+ virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE FINAL;
LayoutRect overflowRectForFlowThreadPortion(const LayoutRect& flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const;
void repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, const LayoutRect& flowThreadPortionRect,
const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& regionLocation) const;
- virtual bool shouldHaveAutoLogicalHeight() const;
-
private:
- virtual void insertedIntoTree() OVERRIDE;
- virtual void willBeRemovedFromTree() OVERRIDE;
-
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
-
- virtual void updateLogicalHeight() OVERRIDE;
+ virtual void insertedIntoTree() OVERRIDE FINAL;
+ virtual void willBeRemovedFromTree() OVERRIDE FINAL;
- virtual void installFlowThread();
-
- PassRefPtr<RenderStyle> computeStyleInRegion(const RenderObject*);
- void computeChildrenStyleInRegion(const RenderObject*);
- void setObjectStyleInRegion(RenderObject*, PassRefPtr<RenderStyle>, bool objectRegionStyleCached);
-
- void checkRegionStyle();
- void updateRegionHasAutoLogicalHeightFlag();
-
- void incrementAutoLogicalHeightCount();
- void decrementAutoLogicalHeightCount();
-
- Element* element() const;
+ virtual void layoutBlock(bool relayoutChildren) OVERRIDE FINAL;
protected:
RenderFlowThread* m_flowThread;
private:
- // 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.
- RenderNamedFlowThread* m_parentNamedFlowThread;
LayoutRect m_flowThreadPortionRect;
-
- // This map holds unique information about a block that is split across regions.
- // A RenderBoxRegionInfo* tells us about any layout information for a RenderBox that
- // is unique to the region. For now it just holds logical width information for RenderBlocks, but eventually
- // it will also hold a custom style for any box (for region styling).
- typedef HashMap<const RenderBox*, OwnPtr<RenderBoxRegionInfo> > RenderBoxRegionInfoMap;
- RenderBoxRegionInfoMap m_renderBoxRegionInfo;
-
- struct ObjectRegionStyleInfo {
- // Used to store the original style of the object in region
- // so that the original style is properly restored after paint.
- // Also used to store computed style of the object in region between
- // region paintings, so that the style in region is computed only
- // when necessary.
- RefPtr<RenderStyle> style;
- // True if the computed style in region is cached.
- bool cached;
- };
- typedef HashMap<const RenderObject*, ObjectRegionStyleInfo > RenderObjectRegionStyleMap;
- RenderObjectRegionStyleMap m_renderObjectRegionStyle;
-
- LayoutUnit m_computedAutoHeight;
-
bool m_isValid : 1;
- bool m_hasCustomRegionStyle : 1;
- bool m_hasAutoLogicalHeight : 1;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderRegion, isRenderRegion());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.cpp
deleted file mode 100644
index 933611547d9..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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 "core/rendering/RenderRegionSet.h"
-
-#include "core/rendering/RenderFlowThread.h"
-
-namespace WebCore {
-
-RenderRegionSet::RenderRegionSet(Element* element, RenderFlowThread* flowThread)
- : RenderRegion(element, flowThread)
-{
-}
-
-void RenderRegionSet::installFlowThread()
-{
- // We don't have to do anything, since we were able to connect the flow thread
- // in the constructor.
-}
-
-void RenderRegionSet::expandToEncompassFlowThreadContentsIfNeeded()
-{
- // Whenever the last region is a set, it always expands its region rect to consume all
- // of the flow thread content. This is because it is always capable of generating an
- // infinite number of boxes in order to hold all of the remaining content.
- LayoutRect rect(flowThreadPortionRect());
-
- // Get the offset within the flow thread in its block progression direction. Then get the
- // flow thread's remaining logical height including its overflow and expand our rect
- // to encompass that remaining height and overflow. The idea is that we will generate
- // additional columns and pages to hold that overflow, since people do write bad
- // content like <body style="height:0px"> in multi-column layouts.
- bool isHorizontal = flowThread()->isHorizontalWritingMode();
- LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x();
- LayoutRect layoutRect = flowThread()->layoutOverflowRect();
- LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : layoutRect.maxX()) - logicalTopOffset;
- setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect.width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height()));
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.h b/chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.h
deleted file mode 100644
index 6802852d0be..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRegionSet.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 "core/rendering/RenderBoxRegionInfo.h"
-#include "core/rendering/RenderRegion.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(Element*, RenderFlowThread*);
-
-protected:
- virtual bool shouldHaveAutoLogicalHeight() const OVERRIDE { return false; }
-
-private:
- virtual void installFlowThread() OVERRIDE FINAL;
-
- virtual void expandToEncompassFlowThreadContentsIfNeeded() OVERRIDE FINAL;
-
- virtual const char* renderName() const = 0;
-
- virtual bool isRenderRegionSet() const OVERRIDE FINAL { return true; }
-};
-
-} // namespace WebCore
-
-#endif // RenderRegionSet_h
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.cpp
index 059cd205f57..89970827847 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.cpp
@@ -24,14 +24,14 @@
#include "config.h"
#include "core/rendering/RenderReplaced.h"
-#include "RuntimeEnabledFeatures.h"
#include "core/rendering/GraphicsContextAnnotator.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderBlock.h"
#include "core/rendering/RenderImage.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
+#include "platform/LengthFunctions.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/GraphicsContext.h"
using namespace std;
@@ -81,8 +81,7 @@ void RenderReplaced::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout());
setHeight(minimumReplacedHeight());
@@ -91,7 +90,7 @@ void RenderReplaced::layout()
m_overflow.clear();
addVisualEffectOverflow();
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
invalidateBackgroundObscurationStatus();
repainter.repaintAfterLayout();
@@ -103,7 +102,7 @@ void RenderReplaced::intrinsicSizeChanged()
int scaledWidth = static_cast<int>(cDefaultWidth * style()->effectiveZoom());
int scaledHeight = static_cast<int>(cDefaultHeight * style()->effectiveZoom());
m_intrinsicSize = IntSize(scaledWidth, scaledHeight);
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -196,19 +195,17 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, const LayoutPoint& paintO
// Early exit if the element touches the edges.
LayoutUnit top = adjustedPaintOffset.y() + visualOverflowRect().y();
LayoutUnit bottom = adjustedPaintOffset.y() + visualOverflowRect().maxY();
- if (isSelected() && m_inlineBoxWrapper) {
- LayoutUnit selTop = paintOffset.y() + m_inlineBoxWrapper->root()->selectionTop();
- LayoutUnit selBottom = paintOffset.y() + selTop + m_inlineBoxWrapper->root()->selectionHeight();
+ if (isSelected() && inlineBoxWrapper()) {
+ LayoutUnit selTop = paintOffset.y() + inlineBoxWrapper()->root().selectionTop();
+ LayoutUnit selBottom = paintOffset.y() + selTop + inlineBoxWrapper()->root().selectionHeight();
top = min(selTop, top);
bottom = max(selBottom, bottom);
}
- LayoutRect localRepaintRect = paintInfo.rect;
- localRepaintRect.inflate(maximalOutlineSize(paintInfo.phase));
- if (adjustedPaintOffset.x() + visualOverflowRect().x() >= localRepaintRect.maxX() || adjustedPaintOffset.x() + visualOverflowRect().maxX() <= localRepaintRect.x())
+ if (adjustedPaintOffset.x() + visualOverflowRect().x() >= paintInfo.rect.maxX() || adjustedPaintOffset.x() + visualOverflowRect().maxX() <= paintInfo.rect.x())
return false;
- if (top >= localRepaintRect.maxY() || bottom <= localRepaintRect.y())
+ if (top >= paintInfo.rect.maxY() || bottom <= paintInfo.rect.y())
return false;
return true;
@@ -224,24 +221,15 @@ static inline RenderBlock* firstContainingBlockWithLogicalWidth(const RenderRepl
return 0;
for (; !containingBlock->isRenderView() && !containingBlock->isBody(); containingBlock = containingBlock->containingBlock()) {
- if (containingBlock->style()->logicalWidth().isSpecified())
+ if (containingBlock->style()->logicalWidth().isSpecified()
+ && containingBlock->style()->logicalMinWidth().isSpecified()
+ && (containingBlock->style()->logicalMaxWidth().isSpecified() || containingBlock->style()->logicalMaxWidth().isUndefined()))
return containingBlock;
}
return 0;
}
-bool RenderReplaced::hasReplacedLogicalWidth() const
-{
- if (style()->logicalWidth().isSpecified())
- return true;
-
- if (style()->logicalWidth().isAuto())
- return false;
-
- return firstContainingBlockWithLogicalWidth(this);
-}
-
bool RenderReplaced::hasReplacedLogicalHeight() const
{
if (style()->logicalHeight().isAuto())
@@ -272,28 +260,21 @@ static inline bool rendererHasAspectRatio(const RenderObject* renderer)
return renderer->isImage() || renderer->isCanvas() || renderer->isVideo();
}
-void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio) const
{
FloatSize intrinsicSize;
if (contentRenderer) {
- contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
- if (intrinsicRatio)
- ASSERT(!isPercentageIntrinsicSize);
+ contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
// Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
- if (!isPercentageIntrinsicSize) {
- intrinsicSize.scale(style()->effectiveZoom());
- if (isRenderImage())
- intrinsicSize.scale(toRenderImage(this)->imageDevicePixelRatio());
- }
-
- if (rendererHasAspectRatio(this) && isPercentageIntrinsicSize)
- intrinsicRatio = 1;
+ intrinsicSize.scale(style()->effectiveZoom());
+ if (isRenderImage())
+ intrinsicSize.scale(toRenderImage(this)->imageDevicePixelRatio());
// Update our intrinsic size to match what the content renderer has computed, so that when we
// constrain the size below, the correct intrinsic size will be obtained for comparison against
// min and max widths.
- if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty())
+ if (intrinsicRatio && !intrinsicSize.isEmpty())
m_intrinsicSize = LayoutSize(intrinsicSize);
if (!isHorizontalWritingMode()) {
@@ -302,12 +283,9 @@ void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* conten
intrinsicSize = intrinsicSize.transposedSize();
}
} else {
- computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
- if (intrinsicRatio) {
- ASSERT(!isPercentageIntrinsicSize);
- if (!intrinsicSize.isEmpty())
- m_intrinsicSize = LayoutSize(isHorizontalWritingMode() ? intrinsicSize : intrinsicSize.transposedSize());
- }
+ computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
+ if (intrinsicRatio && !intrinsicSize.isEmpty())
+ m_intrinsicSize = LayoutSize(isHorizontalWritingMode() ? intrinsicSize : intrinsicSize.transposedSize());
}
// Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the
@@ -317,7 +295,7 @@ void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* conten
// FIXME: In the long term, it might be better to just return this code more to the way it used to be before this
// function was added, since all it has done is make the code more unclear.
constrainedSize = intrinsicSize;
- if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty() && style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
+ if (intrinsicRatio && !intrinsicSize.isEmpty() && 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!
constrainedSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height());
@@ -358,19 +336,18 @@ LayoutRect RenderReplaced::replacedContentRect(const LayoutSize* overriddenIntri
ASSERT_NOT_REACHED();
}
- LayoutUnit xOffset = minimumValueForLength(style()->objectPosition().x(), contentRect.width() - finalRect.width(), view());
- LayoutUnit yOffset = minimumValueForLength(style()->objectPosition().y(), contentRect.height() - finalRect.height(), view());
+ LayoutUnit xOffset = minimumValueForLength(style()->objectPosition().x(), contentRect.width() - finalRect.width());
+ LayoutUnit yOffset = minimumValueForLength(style()->objectPosition().y(), contentRect.height() - finalRect.height());
finalRect.move(xOffset, yOffset);
return finalRect;
}
-void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) 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());
+ intrinsicSize = FloatSize(intrinsicLogicalWidth().toFloat(), intrinsicLogicalHeight().toFloat());
// Figure out if we need to compute an intrinsic ratio.
if (intrinsicSize.isEmpty() || !rendererHasAspectRatio(this))
@@ -387,25 +364,24 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(ShouldComputePreferred sh
RenderBox* contentRenderer = embeddedContentBox();
// 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
- bool isPercentageIntrinsicSize = false;
double intrinsicRatio = 0;
FloatSize constrainedSize;
- computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio, isPercentageIntrinsicSize);
+ computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio);
if (style()->logicalWidth().isAuto()) {
- bool heightIsAuto = style()->logicalHeight().isAuto();
- bool hasIntrinsicWidth = !isPercentageIntrinsicSize && constrainedSize.width() > 0;
+ bool computedHeightIsAuto = hasAutoHeightOrContainingBlockWithAutoHeight();
+ bool hasIntrinsicWidth = constrainedSize.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 (computedHeightIsAuto && hasIntrinsicWidth)
return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred);
- bool hasIntrinsicHeight = !isPercentageIntrinsicSize && constrainedSize.height() > 0;
- if (intrinsicRatio || isPercentageIntrinsicSize) {
+ bool hasIntrinsicHeight = constrainedSize.height() > 0;
+ if (intrinsicRatio) {
// 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)) {
+ if (intrinsicRatio && ((computedHeightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !computedHeightIsAuto)) {
LayoutUnit logicalHeight = computeReplacedLogicalHeight();
return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight * intrinsicRatio)), shouldComputePreferred);
}
@@ -413,21 +389,30 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(ShouldComputePreferred sh
// 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
// 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then
// the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow.
- if (heightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight) {
+ if (computedHeightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight) {
+ if (shouldComputePreferred == ComputePreferred)
+ return 0;
// The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow:
// 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
LayoutUnit logicalWidth;
- if (RenderBlock* blockWithWidth = firstContainingBlockWithLogicalWidth(this))
+ // FIXME: This walking up the containgBlock chain to find the first one with a specified width is bonkers.
+ // If nothing else, it requires making sure that computeReplacedLogicalWidthRespectingMinMaxWidth cannot
+ // depend on the width of the replaced element or we infinite loop. Right now we do that in
+ // firstContainingBlockWithLogicalWidth by checking that width/min-width/max-width are all specified.
+ //
+ // Firefox 27 seems to only do this if the <svg> has a viewbox.
+ if (RenderBlock* blockWithWidth = firstContainingBlockWithLogicalWidth(this)) {
logicalWidth = blockWithWidth->computeReplacedLogicalWidthRespectingMinMaxWidth(blockWithWidth->computeReplacedLogicalWidthUsing(blockWithWidth->style()->logicalWidth()), shouldComputePreferred);
- else
+ } else {
+ // FIXME: If shouldComputePreferred == ComputePreferred, then we're reading this during preferred width
+ // computation, at which point this is reading stale data from a previous layout.
logicalWidth = containingBlock()->availableLogicalWidth();
+ }
// This solves above equation for 'width' (== logicalWidth).
LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth);
LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth);
logicalWidth = max<LayoutUnit>(0, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
- if (isPercentageIntrinsicSize)
- logicalWidth = logicalWidth * constrainedSize.width() / 100;
return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, shouldComputePreferred);
}
}
@@ -455,13 +440,12 @@ LayoutUnit RenderReplaced::computeReplacedLogicalHeight() const
RenderBox* contentRenderer = embeddedContentBox();
// 10.6.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
- bool isPercentageIntrinsicSize = false;
double intrinsicRatio = 0;
FloatSize constrainedSize;
- computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio, isPercentageIntrinsicSize);
+ computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio);
bool widthIsAuto = style()->logicalWidth().isAuto();
- bool hasIntrinsicHeight = !isPercentageIntrinsicSize && constrainedSize.height() > 0;
+ bool hasIntrinsicHeight = constrainedSize.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)
@@ -498,7 +482,7 @@ void RenderReplaced::computePreferredLogicalWidths()
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeReplacedLogicalWidth(ComputePreferred);
RenderStyle* styleToUse = style();
- if (styleToUse->logicalWidth().isPercent() || styleToUse->logicalMaxWidth().isPercent() || hasRelativeIntrinsicLogicalWidth())
+ if (styleToUse->logicalWidth().isPercent() || styleToUse->logicalMaxWidth().isPercent())
m_minPreferredLogicalWidth = 0;
if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
@@ -522,7 +506,7 @@ PositionWithAffinity RenderReplaced::positionForPoint(const LayoutPoint& point)
{
// FIXME: This code is buggy if the replaced element is relative positioned.
InlineBox* box = inlineBoxWrapper();
- RootInlineBox* rootBox = box ? box->root() : 0;
+ RootInlineBox* rootBox = box ? &box->root() : 0;
LayoutUnit top = rootBox ? rootBox->selectionTop() : logicalTop();
LayoutUnit bottom = rootBox ? rootBox->selectionBottom() : logicalBottom();
@@ -545,7 +529,7 @@ PositionWithAffinity RenderReplaced::positionForPoint(const LayoutPoint& point)
return RenderBox::positionForPoint(point);
}
-LayoutRect RenderReplaced::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
+LayoutRect RenderReplaced::selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool clipToVisibleContent)
{
ASSERT(!needsLayout());
@@ -554,9 +538,9 @@ LayoutRect RenderReplaced::selectionRectForRepaint(const RenderLayerModelObject*
LayoutRect rect = localSelectionRect();
if (clipToVisibleContent)
- computeRectForRepaint(repaintContainer, rect);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect);
else
- rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
+ rect = localToContainerQuad(FloatRect(rect), paintInvalidationContainer).enclosingBoundingBox();
return rect;
}
@@ -566,15 +550,15 @@ LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
if (checkWhetherSelected && !isSelected())
return LayoutRect();
- if (!m_inlineBoxWrapper)
+ if (!inlineBoxWrapper())
// We're a block-level replaced element. Just return our own dimensions.
return LayoutRect(LayoutPoint(), size());
- RootInlineBox* root = m_inlineBoxWrapper->root();
- LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
- if (root->block()->style()->isHorizontalWritingMode())
- return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
- return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
+ RootInlineBox& root = inlineBoxWrapper()->root();
+ LayoutUnit newLogicalTop = root.block().style()->isFlippedBlocksWritingMode() ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() : root.selectionTop() - inlineBoxWrapper()->logicalTop();
+ if (root.block().style()->isHorizontalWritingMode())
+ return LayoutRect(0, newLogicalTop, width(), root.selectionHeight());
+ return LayoutRect(newLogicalTop, 0, root.selectionHeight(), height());
}
void RenderReplaced::setSelectionState(SelectionState state)
@@ -582,9 +566,16 @@ void RenderReplaced::setSelectionState(SelectionState state)
// The selection state for our containing block hierarchy is updated by the base class call.
RenderBox::setSelectionState(state);
- if (m_inlineBoxWrapper && canUpdateSelectionOnRootLineBoxes())
- if (RootInlineBox* root = m_inlineBoxWrapper->root())
- root->setHasSelectedChildren(isSelected());
+ if (!inlineBoxWrapper())
+ return;
+
+ // We only include the space below the baseline in our layer's cached repaint rect if the
+ // image is selected. Since the selection state has changed update the rect.
+ if (hasLayer())
+ layer()->repainter().computeRepaintRects();
+
+ if (canUpdateSelectionOnRootLineBoxes())
+ inlineBoxWrapper()->root().setHasSelectedChildren(isSelected());
}
bool RenderReplaced::isSelected() const
@@ -600,7 +591,7 @@ bool RenderReplaced::isSelected() const
if (s == SelectionStart)
return selectionStart == 0;
- int end = node()->hasChildNodes() ? node()->childNodeCount() : 1;
+ int end = node()->hasChildren() ? node()->countChildren() : 1;
if (s == SelectionEnd)
return selectionEnd == end;
if (s == SelectionBoth)
@@ -609,28 +600,23 @@ bool RenderReplaced::isSelected() const
ASSERT(0);
return false;
}
-
-LayoutRect RenderReplaced::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderReplaced::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
return LayoutRect();
// The selectionRect can project outside of the overflowRect, so take their union
// for repainting to avoid selection painting glitches.
- LayoutRect r = unionRect(localSelectionRect(false), visualOverflowRect());
+ LayoutRect r = isSelected() ? localSelectionRect() : visualOverflowRect();
RenderView* v = view();
- if (v) {
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && v) {
// FIXME: layoutDelta needs to be applied in parts before/after transforms and
// repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
r.move(v->layoutDelta());
}
- if (style()) {
- if (v)
- r.inflate(style()->outlineSize());
- }
- computeRectForRepaint(repaintContainer, r);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, r);
return r;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.h b/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.h
index e5db970baa1..fa20c6b9a7e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderReplaced.h
@@ -33,57 +33,57 @@ public:
virtual ~RenderReplaced();
virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const OVERRIDE;
- virtual LayoutUnit computeReplacedLogicalHeight() const;
+ virtual LayoutUnit computeReplacedLogicalHeight() const OVERRIDE;
- bool hasReplacedLogicalWidth() const;
bool hasReplacedLogicalHeight() const;
+ LayoutRect replacedContentRect(const LayoutSize* overriddenIntrinsicSize = 0) const;
virtual bool needsPreferredWidthsRecalculation() const OVERRIDE;
protected:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
- virtual void layout();
+ virtual void layout() OVERRIDE;
virtual LayoutSize intrinsicSize() const OVERRIDE FINAL { return m_intrinsicSize; }
- LayoutRect replacedContentRect(const LayoutSize* overriddenIntrinsicSize = 0) const;
- virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+ virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const OVERRIDE;
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE FINAL;
+ virtual LayoutUnit intrinsicContentLogicalHeight() const { return intrinsicLogicalHeight(); }
+
virtual LayoutUnit minimumReplacedHeight() const { return LayoutUnit(); }
virtual void setSelectionState(SelectionState) OVERRIDE FINAL;
bool isSelected() const;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
void setIntrinsicSize(const LayoutSize& intrinsicSize) { m_intrinsicSize = intrinsicSize; }
virtual void intrinsicSizeChanged();
- virtual bool hasRelativeIntrinsicLogicalWidth() const { return false; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
bool shouldPaint(PaintInfo&, const LayoutPoint&);
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).
+ virtual RenderBox* embeddedContentBox() const { return 0; }
private:
- virtual RenderBox* embeddedContentBox() const { return 0; }
- virtual const char* renderName() const { return "RenderReplaced"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderReplaced"; }
- virtual bool canHaveChildren() const { return false; }
+ virtual bool canHaveChildren() const OVERRIDE { return false; }
virtual void computePreferredLogicalWidths() OVERRIDE FINAL;
virtual void paintReplaced(PaintInfo&, const LayoutPoint&) { }
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
- virtual bool canBeSelectionLeaf() const { return true; }
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return true; }
- virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) OVERRIDE FINAL;
- void computeAspectRatioInformationForRenderBox(RenderBox*, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+ virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool clipToVisibleContent = true) OVERRIDE FINAL;
+ void computeAspectRatioInformationForRenderBox(RenderBox*, FloatSize& constrainedSize, double& intrinsicRatio) const;
mutable LayoutSize m_intrinsicSize;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.cpp
index d7885c27909..ad083b27ae9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.cpp
@@ -30,7 +30,6 @@
#include "core/rendering/RenderReplica.h"
#include "core/rendering/GraphicsContextAnnotator.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
namespace WebCore {
@@ -58,9 +57,9 @@ RenderReplica::~RenderReplica()
void RenderReplica::layout()
{
- LayoutRectRecorder recorder(*this);
setFrameRect(parentBox()->borderBoxRect());
- updateLayerTransform();
+ addVisualOverflow(parentBox()->visualOverflowRect());
+ updateLayerTransformAfterLayout();
clearNeedsLayout();
}
@@ -84,7 +83,7 @@ void RenderReplica::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
// Turn around and paint the parent layer. Use temporary clipRects, so that the layer doesn't end up caching clip rects
// computing using the wrong rootLayer
RenderLayer* rootPaintingLayer = layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor();
- LayerPaintingInfo paintingInfo(rootPaintingLayer, paintInfo.rect, PaintBehaviorNormal, LayoutSize(), 0, paintInfo.renderRegion);
+ LayerPaintingInfo paintingInfo(rootPaintingLayer, paintInfo.rect, PaintBehaviorNormal, LayoutSize(), 0);
PaintLayerFlags flags = PaintLayerHaveTransparency | PaintLayerAppliedTransform | PaintLayerTemporaryClipRects | PaintLayerPaintingReflection;
layer()->parent()->paintLayer(paintInfo.context, paintingInfo, flags);
} else if (paintInfo.phase == PaintPhaseMask)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.h b/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.h
index 43bee56f207..84bbc6fab5f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderReplica.h
@@ -39,19 +39,19 @@ public:
virtual ~RenderReplica();
- virtual const char* renderName() const { return "RenderReplica"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderReplica"; }
- virtual bool requiresLayer() const { return true; }
+ virtual LayerType layerTypeRequired() const OVERRIDE { return NormalLayer; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
private:
RenderReplica();
- virtual bool isReplica() const { return true; }
- virtual void computePreferredLogicalWidths();
+ virtual bool isReplica() const OVERRIDE { return true; }
+ virtual void computePreferredLogicalWidths() OVERRIDE;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.cpp
index 8a9ef79b624..5383683eebd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.cpp
@@ -58,27 +58,27 @@ static inline bool isRubyBeforeBlock(const RenderObject* object)
{
return isAnonymousRubyInlineBlock(object)
&& !object->previousSibling()
- && object->firstChild()
- && object->firstChild()->style()->styleType() == BEFORE;
+ && toRenderBlock(object)->firstChild()
+ && toRenderBlock(object)->firstChild()->style()->styleType() == BEFORE;
}
static inline bool isRubyAfterBlock(const RenderObject* object)
{
return isAnonymousRubyInlineBlock(object)
&& !object->nextSibling()
- && object->firstChild()
- && object->firstChild()->style()->styleType() == AFTER;
+ && toRenderBlock(object)->firstChild()
+ && toRenderBlock(object)->firstChild()->style()->styleType() == AFTER;
}
static inline RenderBlock* rubyBeforeBlock(const RenderObject* ruby)
{
- RenderObject* child = ruby->firstChild();
+ RenderObject* child = ruby->slowFirstChild();
return isRubyBeforeBlock(child) ? toRenderBlock(child) : 0;
}
static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby)
{
- RenderObject* child = ruby->lastChild();
+ RenderObject* child = ruby->slowLastChild();
return isRubyAfterBlock(child) ? toRenderBlock(child) : 0;
}
@@ -92,7 +92,7 @@ static RenderBlockFlow* createAnonymousRubyInlineBlock(RenderObject* ruby)
static RenderRubyRun* lastRubyRun(const RenderObject* ruby)
{
- RenderObject* child = ruby->lastChild();
+ RenderObject* child = ruby->slowLastChild();
if (child && !child->isRubyRun())
child = child->previousSibling();
ASSERT(!child || child->isRubyRun() || child->isBeforeContent() || child == rubyBeforeBlock(ruby));
@@ -225,7 +225,7 @@ RenderRubyAsBlock::~RenderRubyAsBlock()
void RenderRubyAsBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- RenderBlock::styleDidChange(diff, oldStyle);
+ RenderBlockFlow::styleDidChange(diff, oldStyle);
propagateStyleToAnonymousChildren();
}
@@ -235,13 +235,13 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
if (child->isBeforeContent()) {
if (child->isInline()) {
// Add generated inline content normally
- RenderBlock::addChild(child, firstChild());
+ RenderBlockFlow::addChild(child, firstChild());
} else {
// Wrap non-inline content with an anonymous inline-block.
RenderBlock* beforeBlock = rubyBeforeBlock(this);
if (!beforeBlock) {
beforeBlock = createAnonymousRubyInlineBlock(this);
- RenderBlock::addChild(beforeBlock, firstChild());
+ RenderBlockFlow::addChild(beforeBlock, firstChild());
}
beforeBlock->addChild(child);
}
@@ -250,13 +250,13 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
if (child->isAfterContent()) {
if (child->isInline()) {
// Add generated inline content normally
- RenderBlock::addChild(child);
+ RenderBlockFlow::addChild(child);
} else {
// Wrap non-inline content with an anonymous inline-block.
RenderBlock* afterBlock = rubyAfterBlock(this);
if (!afterBlock) {
afterBlock = createAnonymousRubyInlineBlock(this);
- RenderBlock::addChild(afterBlock);
+ RenderBlockFlow::addChild(afterBlock);
}
afterBlock->addChild(child);
}
@@ -265,7 +265,7 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
// If the child is a ruby run, just add it normally.
if (child->isRubyRun()) {
- RenderBlock::addChild(child, beforeChild);
+ RenderBlockFlow::addChild(child, beforeChild);
return;
}
@@ -289,7 +289,7 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
RenderRubyRun* lastRun = lastRubyRun(this);
if (!lastRun || lastRun->hasRubyText()) {
lastRun = RenderRubyRun::staticCreateRubyRun(this);
- RenderBlock::addChild(lastRun, beforeChild);
+ RenderBlockFlow::addChild(lastRun, beforeChild);
}
lastRun->addChild(child);
}
@@ -300,7 +300,7 @@ void RenderRubyAsBlock::removeChild(RenderObject* child)
// just use the normal remove method.
if (child->parent() == this) {
ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
- RenderBlock::removeChild(child);
+ RenderBlockFlow::removeChild(child);
return;
}
// If the child's parent is an anoymous block (must be generated :before/:after content)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.h b/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.h
index d9da35b9f3b..cd0a7fc6db0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRuby.h
@@ -56,18 +56,16 @@ public:
RenderRubyAsInline(Element*);
virtual ~RenderRubyAsInline();
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject* child);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject* child) OVERRIDE;
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
private:
- virtual bool isRuby() const { return true; }
- virtual const char* renderName() const { return "RenderRuby (inline)"; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual bool createsAnonymousWrapper() const { return true; }
- virtual void removeLeftoverAnonymousBlock(RenderBlock*) { ASSERT_NOT_REACHED(); }
+ virtual bool isRuby() const OVERRIDE { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderRuby (inline)"; }
+ virtual bool createsAnonymousWrapper() const OVERRIDE { return true; }
};
// <ruby> when used as 'display:block' or 'display:inline-block'
@@ -76,18 +74,17 @@ public:
RenderRubyAsBlock(Element*);
virtual ~RenderRubyAsBlock();
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject* child);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject* child) OVERRIDE;
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
private:
- virtual bool isRuby() const { return true; }
- virtual const char* renderName() const { return "RenderRuby (block)"; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual bool createsAnonymousWrapper() const { return true; }
- virtual void removeLeftoverAnonymousBlock(RenderBlock*) { ASSERT_NOT_REACHED(); }
+ virtual bool isRuby() const OVERRIDE { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderRuby (block)"; }
+ virtual bool createsAnonymousWrapper() const OVERRIDE { return true; }
+ virtual void removeLeftoverAnonymousBlock(RenderBlock*) OVERRIDE { ASSERT_NOT_REACHED(); }
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.cpp
index e32478ed14b..1ceeec05486 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.cpp
@@ -73,8 +73,8 @@ void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeCh
else
moveBlockChildren(toBase, beforeChild);
- setNeedsLayoutAndPrefWidthsRecalc();
- toBase->setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
+ toBase->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
@@ -130,20 +130,12 @@ void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* bef
moveChildrenTo(toBase, firstChild(), beforeChild);
}
-RenderRubyRun* RenderRubyBase::rubyRun() const
-{
- ASSERT(parent());
- ASSERT(parent()->isRubyRun());
-
- return toRenderRubyRun(parent());
-}
-
ETextAlign RenderRubyBase::textAlignmentForLine(bool /* endsWithSoftBreak */) const
{
return JUSTIFY;
}
-void RenderRubyBase::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
+void RenderRubyBase::adjustInlineDirectionLineBounds(unsigned expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
{
int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth();
if (maxPreferredLogicalWidth >= logicalWidth)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.h b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.h
index 197aebba507..98748be1157 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyBase.h
@@ -43,26 +43,22 @@ public:
static RenderRubyBase* createAnonymous(Document*);
- virtual const char* renderName() const { return "RenderRubyBase (anonymous)"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderRubyBase (anonymous)"; }
- virtual bool isRubyBase() const { return true; }
+ virtual bool isRubyBase() const OVERRIDE { return true; }
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
private:
RenderRubyBase();
- virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
- virtual void adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const;
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const OVERRIDE;
+ virtual void adjustInlineDirectionLineBounds(unsigned expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const OVERRIDE;
void moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
void moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
void moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
- RenderRubyRun* rubyRun() const;
-
// Allow RenderRubyRun to manipulate the children within ruby bases.
friend class RenderRubyRun;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.cpp
index fe58c872243..09c0146e75a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.cpp
@@ -32,7 +32,6 @@
#include "core/rendering/RenderRubyRun.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderRubyBase.h"
#include "core/rendering/RenderRubyText.h"
#include "core/rendering/RenderText.h"
@@ -66,11 +65,6 @@ bool RenderRubyRun::hasRubyBase() const
return lastChild() && lastChild()->isRubyBase();
}
-bool RenderRubyRun::isEmpty() const
-{
- return !hasRubyText() && !hasRubyBase();
-}
-
RenderRubyText* RenderRubyRun::rubyText() const
{
RenderObject* child = firstChild();
@@ -91,7 +85,7 @@ RenderRubyBase* RenderRubyRun::rubyBaseSafe()
RenderRubyBase* base = rubyBase();
if (!base) {
base = createRubyBase();
- RenderBlock::addChild(base);
+ RenderBlockFlow::addChild(base);
}
return base;
}
@@ -119,7 +113,7 @@ void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
// RenderRuby has already ascertained that we can add the child here.
ASSERT(!hasRubyText());
// prepend ruby texts as first child
- RenderBlock::addChild(child, firstChild());
+ RenderBlockFlow::addChild(child, firstChild());
} else if (beforeChild->isRubyText()) {
// New text is inserted just before another.
// In this case the new text takes the place of the old one, and
@@ -133,8 +127,8 @@ void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
// Note: Doing it in this order and not using RenderRubyRun's methods,
// in order to avoid automatic removal of the ruby run in case there is no
// other child besides the old ruby text.
- RenderBlock::addChild(child, beforeChild);
- RenderBlock::removeChild(beforeChild);
+ RenderBlockFlow::addChild(child, beforeChild);
+ RenderBlockFlow::removeChild(beforeChild);
newRun->addChild(beforeChild);
} else if (hasRubyBase()) {
// Insertion before a ruby base object.
@@ -176,20 +170,19 @@ void RenderRubyRun::removeChild(RenderObject* child)
}
}
- RenderBlock::removeChild(child);
+ RenderBlockFlow::removeChild(child);
if (!beingDestroyed() && !documentBeingDestroyed()) {
// Check if our base (if any) is now empty. If so, destroy it.
RenderBlock* base = rubyBase();
if (base && !base->firstChild()) {
- RenderBlock::removeChild(base);
+ RenderBlockFlow::removeChild(base);
base->deleteLineBoxTree();
base->destroy();
}
// If any of the above leaves the run empty, destroy it as well.
- if (isEmpty()) {
- parent()->removeChild(this);
+ if (!hasRubyText() && !hasRubyBase()) {
deleteLineBoxTree();
destroy();
}
@@ -229,8 +222,7 @@ RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren, S
void RenderRubyRun::layout()
{
- LayoutRectRecorder recorder(*this);
- RenderBlock::layout();
+ RenderBlockFlow::layout();
RenderRubyText* rt = rubyText();
if (!rt)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.h b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.h
index 2005bc1322b..118533ae2b2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyRun.h
@@ -47,20 +47,19 @@ public:
bool hasRubyText() const;
bool hasRubyBase() const;
- bool isEmpty() const;
RenderRubyText* rubyText() const;
RenderRubyBase* rubyBase() const;
RenderRubyBase* rubyBaseSafe(); // creates the base if it doesn't already exist
- virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&);
- virtual void layout();
+ virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) OVERRIDE;
+ virtual void layout() OVERRIDE;
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject* child);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void removeChild(RenderObject* child) OVERRIDE;
- virtual RenderBlock* firstLineBlock() const;
- virtual void updateFirstLetter();
+ virtual RenderBlock* firstLineBlock() const OVERRIDE;
+ virtual void updateFirstLetter() OVERRIDE;
void getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const;
@@ -72,11 +71,10 @@ protected:
private:
RenderRubyRun();
- virtual bool isRubyRun() const { return true; }
- virtual const char* renderName() const { return "RenderRubyRun (anonymous)"; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual bool createsAnonymousWrapper() const { return true; }
- virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+ virtual bool isRubyRun() const OVERRIDE { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderRubyRun (anonymous)"; }
+ virtual bool createsAnonymousWrapper() const OVERRIDE { return true; }
+ virtual void removeLeftoverAnonymousBlock(RenderBlock*) OVERRIDE { }
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderRubyRun, isRubyRun());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.cpp
index 3e5a60f0dfb..5e469787347 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.cpp
@@ -62,12 +62,12 @@ ETextAlign RenderRubyText::textAlignmentForLine(bool endsWithSoftBreak) const
return JUSTIFY;
}
-void RenderRubyText::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
+void RenderRubyText::adjustInlineDirectionLineBounds(unsigned expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
{
ETextAlign textAlign = style()->textAlign();
// FIXME: This check is bogus since user can set the initial value.
if (textAlign != RenderStyle::initialTextAlign())
- return RenderBlock::adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, logicalWidth);
+ return RenderBlockFlow::adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, logicalWidth);
int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth();
if (maxPreferredLogicalWidth >= logicalWidth)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.h b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.h
index b1cb992c5eb..1e2b636acdc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderRubyText.h
@@ -40,19 +40,17 @@ public:
RenderRubyText(Element*);
virtual ~RenderRubyText();
- virtual const char* renderName() const { return "RenderRubyText"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderRubyText"; }
- virtual bool isRubyText() const { return true; }
+ virtual bool isRubyText() const OVERRIDE { return true; }
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
private:
- virtual bool avoidsFloats() const;
+ virtual bool avoidsFloats() const OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
- virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
- virtual void adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const;
+ virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const OVERRIDE;
+ virtual void adjustInlineDirectionLineBounds(unsigned expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const OVERRIDE;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.cpp
index a3aaeacba69..4ea0ba701ef 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.cpp
@@ -27,20 +27,21 @@
#include "core/rendering/RenderScrollbar.h"
#include "core/css/PseudoStyleRequest.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/RenderPart.h"
#include "core/rendering/RenderScrollbarPart.h"
#include "core/rendering/RenderScrollbarTheme.h"
+#include "platform/graphics/GraphicsContext.h"
namespace WebCore {
-PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, Frame* owningFrame)
+PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, LocalFrame* owningFrame)
{
return adoptRef(new RenderScrollbar(scrollableArea, orientation, ownerNode, owningFrame));
}
-RenderScrollbar::RenderScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, Frame* owningFrame)
+RenderScrollbar::RenderScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, LocalFrame* owningFrame)
: Scrollbar(scrollableArea, orientation, RegularScrollbar, RenderScrollbarTheme::renderScrollbarTheme())
, m_owner(ownerNode)
, m_owningFrame(owningFrame)
@@ -148,7 +149,7 @@ void RenderScrollbar::setPressedPart(ScrollbarPart part)
PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, PseudoId pseudoId)
{
if (!owningRenderer())
- return 0;
+ return nullptr;
RefPtr<RenderStyle> result = owningRenderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId, this, partType), owningRenderer()->style());
// Scrollbars for root frames should always have background color
@@ -156,7 +157,7 @@ PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart p
// This is because WebKit assumes scrollbar to be always painted and missing background
// causes visual artifact like non-repainted dirty region.
if (result && m_owningFrame && m_owningFrame->view() && !m_owningFrame->view()->isTransparent() && !result->hasBackground())
- result->setBackgroundColor(Color::white);
+ result->setBackgroundColor(StyleColor(Color::white));
return result;
}
@@ -223,9 +224,9 @@ void RenderScrollbar::updateScrollbarPart(ScrollbarPart partType, bool destroy)
if (partType == NoPart)
return;
- RefPtr<RenderStyle> partStyle = !destroy ? getScrollbarPseudoStyle(partType, pseudoForScrollbarPart(partType)) : PassRefPtr<RenderStyle>(0);
+ RefPtr<RenderStyle> partStyle = !destroy ? getScrollbarPseudoStyle(partType, pseudoForScrollbarPart(partType)) : PassRefPtr<RenderStyle>(nullptr);
- bool needRenderer = !destroy && partStyle && partStyle->display() != NONE && partStyle->visibility() == VISIBLE;
+ bool needRenderer = !destroy && partStyle && partStyle->display() != NONE;
if (needRenderer && partStyle->display() != BLOCK) {
// See if we are a button that should not be visible according to OS settings.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.h b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.h
index fcb60151a20..7d29c397224 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbar.h
@@ -32,19 +32,19 @@
namespace WebCore {
-class Frame;
+class LocalFrame;
class Node;
class RenderBox;
class RenderScrollbarPart;
class RenderStyle;
-class RenderScrollbar : public Scrollbar {
+class RenderScrollbar FINAL : public Scrollbar {
protected:
- RenderScrollbar(ScrollableArea*, ScrollbarOrientation, Node*, Frame*);
+ RenderScrollbar(ScrollableArea*, ScrollbarOrientation, Node*, LocalFrame*);
public:
friend class Scrollbar;
- static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollableArea*, ScrollbarOrientation, Node*, Frame* owningFrame = 0);
+ static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollableArea*, ScrollbarOrientation, Node*, LocalFrame* owningFrame = 0);
virtual ~RenderScrollbar();
RenderBox* owningRenderer() const;
@@ -57,20 +57,20 @@ public:
int minimumThumbLength();
- virtual bool isOverlayScrollbar() const { return false; }
+ virtual bool isOverlayScrollbar() const OVERRIDE { return false; }
private:
virtual void setParent(Widget*) OVERRIDE;
- virtual void setEnabled(bool);
+ virtual void setEnabled(bool) OVERRIDE;
- virtual void paint(GraphicsContext*, const IntRect& damageRect);
+ virtual void paint(GraphicsContext*, const IntRect& damageRect) OVERRIDE;
- virtual void setHoveredPart(ScrollbarPart);
- virtual void setPressedPart(ScrollbarPart);
+ virtual void setHoveredPart(ScrollbarPart) OVERRIDE;
+ virtual void setPressedPart(ScrollbarPart) OVERRIDE;
- virtual void styleChanged();
+ virtual void styleChanged() OVERRIDE;
- virtual bool isCustomScrollbar() const { return true; }
+ virtual bool isCustomScrollbar() const OVERRIDE { return true; }
void updateScrollbarParts(bool destroy = false);
@@ -81,9 +81,9 @@ private:
// so we keep a reference to the Node which caused this custom scrollbar creation.
// This will not create a reference cycle as the Widget tree is owned by our containing
// FrameView which this Node pointer can in no way keep alive. See webkit bug 80610.
- RefPtr<Node> m_owner;
+ RefPtrWillBePersistent<Node> m_owner;
- Frame* m_owningFrame;
+ LocalFrame* m_owningFrame;
HashMap<unsigned, RenderScrollbarPart*> m_parts;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.cpp
index 13a35ebb832..927079a1fdf 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.cpp
@@ -26,11 +26,11 @@
#include "config.h"
#include "core/rendering/RenderScrollbarPart.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderScrollbar.h"
#include "core/rendering/RenderScrollbarTheme.h"
#include "core/rendering/RenderView.h"
+#include "platform/LengthFunctions.h"
using namespace std;
@@ -56,7 +56,6 @@ RenderScrollbarPart* RenderScrollbarPart::createAnonymous(Document* document, Re
void RenderScrollbarPart::layout()
{
- LayoutRectRecorder recorder(*this);
setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
if (m_scrollbar->orientation() == HorizontalScrollbar)
layoutHorizontalPart();
@@ -88,10 +87,10 @@ void RenderScrollbarPart::layoutVerticalPart()
}
}
-static int calcScrollbarThicknessUsing(SizeType sizeType, const Length& length, int containingLength, RenderView* renderView)
+static int calcScrollbarThicknessUsing(SizeType sizeType, const Length& length, int containingLength)
{
if (!length.isIntrinsicOrAuto() || (sizeType == MinSize && length.isAuto()))
- return minimumValueForLength(length, containingLength, renderView);
+ return minimumValueForLength(length, containingLength);
return ScrollbarTheme::theme()->scrollbarThickness();
}
@@ -99,36 +98,34 @@ void RenderScrollbarPart::computeScrollbarWidth()
{
if (!m_scrollbar->owningRenderer())
return;
- RenderView* renderView = view();
// FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
// FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->style()->borderLeftWidth() - m_scrollbar->owningRenderer()->style()->borderRightWidth();
- int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->width(), visibleSize, renderView);
- int minWidth = calcScrollbarThicknessUsing(MinSize, style()->minWidth(), visibleSize, renderView);
- int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(MaxSize, style()->maxWidth(), visibleSize, renderView);
+ int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->width(), visibleSize);
+ int minWidth = calcScrollbarThicknessUsing(MinSize, style()->minWidth(), visibleSize);
+ int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(MaxSize, style()->maxWidth(), visibleSize);
setWidth(max(minWidth, min(maxWidth, w)));
// Buttons and track pieces can all have margins along the axis of the scrollbar.
- m_marginBox.setLeft(minimumValueForLength(style()->marginLeft(), visibleSize, renderView));
- m_marginBox.setRight(minimumValueForLength(style()->marginRight(), visibleSize, renderView));
+ m_marginBox.setLeft(minimumValueForLength(style()->marginLeft(), visibleSize));
+ m_marginBox.setRight(minimumValueForLength(style()->marginRight(), visibleSize));
}
void RenderScrollbarPart::computeScrollbarHeight()
{
if (!m_scrollbar->owningRenderer())
return;
- RenderView* renderView = view();
// FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
// FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
int visibleSize = m_scrollbar->owningRenderer()->height() - m_scrollbar->owningRenderer()->style()->borderTopWidth() - m_scrollbar->owningRenderer()->style()->borderBottomWidth();
- int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->height(), visibleSize, renderView);
- int minHeight = calcScrollbarThicknessUsing(MinSize, style()->minHeight(), visibleSize, renderView);
- int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(MaxSize, style()->maxHeight(), visibleSize, renderView);
+ int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->height(), visibleSize);
+ int minHeight = calcScrollbarThicknessUsing(MinSize, style()->minHeight(), visibleSize);
+ int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(MaxSize, style()->maxHeight(), visibleSize);
setHeight(max(minHeight, min(maxHeight, h)));
// Buttons and track pieces can all have margins along the axis of the scrollbar.
- m_marginBox.setTop(minimumValueForLength(style()->marginTop(), visibleSize, renderView));
- m_marginBox.setBottom(minimumValueForLength(style()->marginBottom(), visibleSize, renderView));
+ m_marginBox.setTop(minimumValueForLength(style()->marginTop(), visibleSize));
+ m_marginBox.setBottom(minimumValueForLength(style()->marginBottom(), visibleSize));
}
void RenderScrollbarPart::computePreferredLogicalWidths()
@@ -141,7 +138,7 @@ void RenderScrollbarPart::computePreferredLogicalWidths()
clearPreferredLogicalWidthsDirty();
}
-void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
RenderBlock::styleWillChange(diff, newStyle);
setInline(false);
@@ -154,7 +151,7 @@ void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle
clearPositionedState();
setFloating(false);
setHasOverflowClip(false);
- if (oldStyle && m_scrollbar && m_part != NoPart && diff >= StyleDifferenceRepaint)
+ if (oldStyle && m_scrollbar && m_part != NoPart && (diff.needsRepaint() || diff.needsLayout()))
m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.h b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.h
index a1f24654f4b..f289ce6f431 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarPart.h
@@ -39,11 +39,11 @@ public:
virtual ~RenderScrollbarPart();
- virtual const char* renderName() const { return "RenderScrollbarPart"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderScrollbarPart"; }
- virtual bool requiresLayer() const { return false; }
+ virtual LayerType layerTypeRequired() const OVERRIDE { return NoLayer; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
void paintIntoRect(GraphicsContext*, const LayoutPoint&, const LayoutRect&);
@@ -53,20 +53,31 @@ public:
virtual LayoutUnit marginLeft() const OVERRIDE { ASSERT(isIntegerValue(m_marginBox.left())); return m_marginBox.left(); }
virtual LayoutUnit marginRight() const OVERRIDE { ASSERT(isIntegerValue(m_marginBox.right())); return m_marginBox.right(); }
- virtual bool isRenderScrollbarPart() const { return true; }
+ virtual bool isRenderScrollbarPart() const OVERRIDE { return true; }
RenderObject* rendererOwningScrollbar() const;
protected:
- virtual void styleWillChange(StyleDifference diff, const RenderStyle* newStyle);
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
private:
RenderScrollbarPart(RenderScrollbar*, ScrollbarPart);
- virtual void computePreferredLogicalWidths();
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+
+ // Have all padding getters return 0. The important point here is to avoid resolving percents
+ // against the containing block, since scroll bar corners don't always have one (so it would
+ // crash). Scroll bar corners are not actually laid out, and they don't have child content, so
+ // what we return here doesn't really matter.
+ virtual LayoutUnit paddingTop() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingBottom() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingLeft() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingRight() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingBefore() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingAfter() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingStart() const OVERRIDE { return LayoutUnit(); }
+ virtual LayoutUnit paddingEnd() const OVERRIDE { return LayoutUnit(); }
void layoutHorizontalPart();
void layoutVerticalPart();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.cpp
index 63f1a1e23d5..dad81e83bec 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "core/rendering/RenderScrollbar.h"
#include "core/rendering/RenderScrollbarTheme.h"
+#include "platform/graphics/GraphicsContext.h"
#include "platform/scroll/ScrollbarThemeClient.h"
#include "wtf/StdLibExtras.h"
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.h b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.h
index 0b5b56e8145..56431e48b5f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderScrollbarTheme.h
@@ -31,9 +31,8 @@
namespace WebCore {
class PlatformMouseEvent;
-class Scrollbar;
-class RenderScrollbarTheme : public ScrollbarTheme {
+class RenderScrollbarTheme FINAL : public ScrollbarTheme {
public:
virtual ~RenderScrollbarTheme() { }
@@ -41,11 +40,10 @@ public:
virtual ScrollbarButtonsPlacement buttonsPlacement() const OVERRIDE { return ScrollbarTheme::theme()->buttonsPlacement(); }
- virtual bool supportsControlTints() const OVERRIDE { return true; }
-
virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect) OVERRIDE;
virtual bool shouldCenterOnThumb(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& event) OVERRIDE { return ScrollbarTheme::theme()->shouldCenterOnThumb(scrollbar, event); }
+ virtual bool shouldSnapBackToDragOrigin(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& event) OVERRIDE { return ScrollbarTheme::theme()->shouldSnapBackToDragOrigin(scrollbar, event); }
virtual double initialAutoscrollTimerDelay() OVERRIDE { return ScrollbarTheme::theme()->initialAutoscrollTimerDelay(); }
virtual double autoscrollTimerDelay() OVERRIDE { return ScrollbarTheme::theme()->autoscrollTimerDelay(); }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderSelectionInfo.h b/chromium/third_party/WebKit/Source/core/rendering/RenderSelectionInfo.h
index d3ec42d5720..6cdb43649f4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderSelectionInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderSelectionInfo.h
@@ -42,18 +42,18 @@ public:
RenderSelectionInfoBase(RenderObject* o)
: m_object(o)
- , m_repaintContainer(o->containerForRepaint())
+ , m_repaintContainer(o->containerForPaintInvalidation())
, m_state(o->selectionState())
{
}
RenderObject* object() const { return m_object; }
- RenderLayerModelObject* repaintContainer() const { return m_repaintContainer; }
+ const RenderLayerModelObject* repaintContainer() const { return m_repaintContainer; }
RenderObject::SelectionState state() const { return m_state; }
protected:
RenderObject* m_object;
- RenderLayerModelObject* m_repaintContainer;
+ const RenderLayerModelObject* m_repaintContainer;
RenderObject::SelectionState m_state;
};
@@ -62,13 +62,20 @@ class RenderSelectionInfo : public RenderSelectionInfoBase {
public:
RenderSelectionInfo(RenderObject* o, bool clipToVisibleContent)
: RenderSelectionInfoBase(o)
- , m_rect(o->canUpdateSelectionOnRootLineBoxes() ? o->selectionRectForRepaint(m_repaintContainer, clipToVisibleContent) : LayoutRect())
{
+ if (o->canUpdateSelectionOnRootLineBoxes()) {
+ m_rect = o->selectionRectForPaintInvalidation(m_repaintContainer, clipToVisibleContent);
+ // FIXME: groupedMapping() leaks the squashing abstraction. See RenderBlockSelectionInfo for more details.
+ if (m_repaintContainer && m_repaintContainer->groupedMapping())
+ RenderLayer::mapRectToRepaintBacking(m_repaintContainer, m_repaintContainer, m_rect);
+ } else {
+ m_rect = LayoutRect();
+ }
}
void repaint()
{
- m_object->repaintUsingContainer(m_repaintContainer, enclosingIntRect(m_rect));
+ m_object->invalidatePaintUsingContainer(m_repaintContainer, enclosingIntRect(m_rect), InvalidationSelection);
}
LayoutRect rect() const { return m_rect; }
@@ -83,13 +90,22 @@ class RenderBlockSelectionInfo : public RenderSelectionInfoBase {
public:
RenderBlockSelectionInfo(RenderBlock* b)
: RenderSelectionInfoBase(b)
- , m_rects(b->canUpdateSelectionOnRootLineBoxes() ? block()->selectionGapRectsForRepaint(m_repaintContainer) : GapRects())
{
+ if (b->canUpdateSelectionOnRootLineBoxes())
+ m_rects = block()->selectionGapRectsForRepaint(m_repaintContainer);
+ else
+ m_rects = GapRects();
}
void repaint()
{
- m_object->repaintUsingContainer(m_repaintContainer, enclosingIntRect(m_rects));
+ LayoutRect repaintRect = enclosingIntRect(m_rects);
+ // FIXME: this is leaking the squashing abstraction. However, removing the groupedMapping() condiitional causes
+ // RenderBox::mapRectToRepaintBacking to get called, which makes rect adjustments even if you pass the same
+ // repaintContainer as the render object. Find out why it does that and fix.
+ if (m_repaintContainer && m_repaintContainer->groupedMapping())
+ RenderLayer::mapRectToRepaintBacking(m_repaintContainer, m_repaintContainer, repaintRect);
+ m_object->invalidatePaintUsingContainer(m_repaintContainer, enclosingIntRect(repaintRect), InvalidationSelection);
}
RenderBlock* block() const { return toRenderBlock(m_object); }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.cpp
index 73e4d67bdda..0dff3af336e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.cpp
@@ -25,7 +25,6 @@
#include "core/html/HTMLInputElement.h"
#include "core/html/shadow/ShadowElementNames.h"
#include "core/html/shadow/SliderThumbElement.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "wtf/MathExtras.h"
using std::min;
@@ -63,20 +62,21 @@ void RenderSlider::computePreferredLogicalWidths()
{
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
+ RenderStyle* styleToUse = style();
- if (style()->width().isFixed() && style()->width().value() > 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+ if (styleToUse->width().isFixed() && styleToUse->width().value() > 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->width().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+ if (styleToUse->minWidth().isFixed() && styleToUse->minWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->minWidth().value()));
}
- if (style()->maxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+ if (styleToUse->maxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->maxWidth().value()));
}
LayoutUnit toAdd = borderAndPaddingWidth();
@@ -93,7 +93,6 @@ inline SliderThumbElement* RenderSlider::sliderThumbElement() const
void RenderSlider::layout()
{
- LayoutRectRecorder recorder(*this);
// FIXME: Find a way to cascade appearance.
// http://webkit.org/b/62535
RenderBox* thumbBox = sliderThumbElement()->renderBox();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.h b/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.h
index a627e2c0489..9d1fc60434b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderSlider.h
@@ -26,7 +26,6 @@
namespace WebCore {
class HTMLInputElement;
-class MouseEvent;
class SliderThumbElement;
class RenderSlider FINAL : public RenderFlexibleBox {
@@ -39,13 +38,13 @@ public:
bool inDragMode() const;
private:
- virtual const char* renderName() const { return "RenderSlider"; }
- virtual bool isSlider() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSlider"; }
+ virtual bool isSlider() const OVERRIDE { return true; }
- virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+ virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE;
- virtual void layout();
+ virtual void layout() OVERRIDE;
SliderThumbElement* sliderThumbElement() const;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTable.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTable.cpp
index 5ca0c17e93e..ea196ecff95 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTable.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTable.cpp
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
* This library is free software; you can redistribute it and/or
@@ -26,15 +26,15 @@
#include "config.h"
#include "core/rendering/RenderTable.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
-#include "core/html/HTMLTableElement.h"
#include "core/frame/FrameView.h"
+#include "core/html/HTMLTableElement.h"
#include "core/rendering/AutoTableLayout.h"
+#include "core/rendering/FastTextAutosizer.h"
#include "core/rendering/FixedTableLayout.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderTableCaption.h"
@@ -63,6 +63,7 @@ RenderTable::RenderTable(Element* element)
, m_needsSectionRecalc(false)
, m_columnLogicalWidthChanged(false)
, m_columnRenderersValid(false)
+ , m_hasCellColspanThatDeterminesTableWidth(false)
, m_hSpacing(0)
, m_vSpacing(0)
, m_borderStart(0)
@@ -82,20 +83,20 @@ void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
RenderBlock::styleDidChange(diff, oldStyle);
propagateStyleToAnonymousChildren();
- ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
+ bool oldFixedTableLayout = oldStyle ? oldStyle->isFixedTableLayout() : false;
// In the collapsed border model, there is no cell spacing.
m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
m_columnPos[0] = m_hSpacing;
- if (!m_tableLayout || style()->tableLayout() != oldTableLayout) {
+ if (!m_tableLayout || style()->isFixedTableLayout() != oldFixedTableLayout) {
if (m_tableLayout)
m_tableLayout->willChangeTableLayout();
// According to the CSS2 spec, you only use fixed table layout if an
// explicit width is specified on the table. Auto width implies auto table layout.
- if (style()->tableLayout() == TFIXED && !style()->logicalWidth().isAuto())
+ if (style()->isFixedTableLayout())
m_tableLayout = adoptPtr(new FixedTableLayout(this));
else
m_tableLayout = adoptPtr(new AutoTableLayout(this));
@@ -117,6 +118,14 @@ static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, Rend
ptr = 0;
}
+static inline bool needsTableSection(RenderObject* object)
+{
+ // Return true if 'object' can't exist in an anonymous table without being
+ // wrapped in a table section box.
+ EDisplay display = object->style()->display();
+ return display != TABLE_CAPTION && display != TABLE_COLUMN_GROUP && display != TABLE_COLUMN;
+}
+
void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
{
bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
@@ -156,9 +165,7 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
default:
ASSERT_NOT_REACHED();
}
- } else if (child->isTableCell() || child->isTableRow())
- wrapInAnonymousSection = true;
- else
+ } else
wrapInAnonymousSection = true;
if (child->isTableSection())
@@ -186,16 +193,16 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
}
RenderObject* lastBox = beforeChild;
- while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP)
+ while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && needsTableSection(lastBox))
lastBox = lastBox->parent();
if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
if (beforeChild == lastBox)
- beforeChild = lastBox->firstChild();
+ beforeChild = lastBox->slowFirstChild();
lastBox->addChild(child, beforeChild);
return;
}
- if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
+ if (beforeChild && !beforeChild->isTableSection() && needsTableSection(beforeChild))
beforeChild = 0;
RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
@@ -253,7 +260,6 @@ void RenderTable::updateLogicalWidth()
}
RenderBlock* cb = containingBlock();
- RenderView* renderView = view();
LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent();
bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
@@ -264,16 +270,14 @@ void RenderTable::updateLogicalWidth()
setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
else {
// Subtract out any fixed margins from our available width for auto width tables.
- LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
- LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
+ LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth);
+ LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth);
LayoutUnit marginTotal = marginStart + marginEnd;
// Subtract out our margins to get the available content width.
LayoutUnit availableContentLogicalWidth = max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
- if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
- // FIXME: Work with regions someday.
- availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb), 0);
- }
+ if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock)
+ availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb));
// Ensure we aren't bigger than our available width.
setLogicalWidth(min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
@@ -298,23 +302,10 @@ void RenderTable::updateLogicalWidth()
}
// Finally, with our true width determined, compute our margins for real.
- setMarginStart(0);
- setMarginEnd(0);
- if (!hasPerpendicularContainingBlock) {
- LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
- if (avoidsFloats() && cb->containsFloats())
- containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0); // FIXME: Work with regions someday.
- ComputedMarginValues marginValues;
- bool hasInvertedDirection = cb->style()->isLeftToRightDirection() == style()->isLeftToRightDirection();
- computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth(),
- hasInvertedDirection ? marginValues.m_start : marginValues.m_end,
- hasInvertedDirection ? marginValues.m_end : marginValues.m_start);
- setMarginStart(marginValues.m_start);
- setMarginEnd(marginValues.m_end);
- } else {
- setMarginStart(minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView));
- setMarginEnd(minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView));
- }
+ ComputedMarginValues marginValues;
+ computeMarginsForDirection(InlineDirection, cb, availableLogicalWidth, logicalWidth(), marginValues.m_start, marginValues.m_end, style()->marginStart(), style()->marginEnd());
+ setMarginStart(marginValues.m_start);
+ setMarginEnd(marginValues.m_end);
// We should NEVER shrink the table below the min-content logical width, or else the table can't accomodate
// its own content which doesn't match CSS nor what authors expect.
@@ -331,11 +322,11 @@ LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& st
// HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
LayoutUnit borders = 0;
- bool isCSSTable = !node() || !isHTMLTableElement(node());
+ bool isCSSTable = !isHTMLTableElement(node());
if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style()->boxSizing() == CONTENT_BOX)
borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
- return minimumValueForLength(styleLogicalWidth, availableWidth, view()) + borders;
+ return minimumValueForLength(styleLogicalWidth, availableWidth) + borders;
}
LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
@@ -348,14 +339,12 @@ LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length&
// HTML tables size as though CSS height includes border/padding, CSS tables do not.
LayoutUnit borders = LayoutUnit();
// FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
- if ((node() && isHTMLTableElement(node())) || style()->boxSizing() == BORDER_BOX) {
+ if (isHTMLTableElement(node()) || style()->boxSizing() == BORDER_BOX) {
borders = borderAndPadding;
}
computedLogicalHeight = styleLogicalHeight.value() - borders;
} else if (styleLogicalHeight.isPercent())
computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight);
- else if (styleLogicalHeight.isViewportPercentage())
- computedLogicalHeight = minimumValueForLength(styleLogicalHeight, 0, view());
else if (styleLogicalHeight.isIntrinsic())
computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(styleLogicalHeight, logicalHeight() - borderAndPadding, borderAndPadding);
else
@@ -375,9 +364,14 @@ void RenderTable::layoutCaption(RenderTableCaption* caption)
caption->layoutIfNeeded();
}
// Apply the margins to the location now that they are definitely available from layout
- caption->setLogicalLocation(LayoutPoint(caption->marginStart(), collapsedMarginBeforeForChild(caption) + logicalHeight()));
+ LayoutUnit captionLogicalTop = collapsedMarginBeforeForChild(caption) + logicalHeight();
+ if (view()->layoutState()->isPaginated()) {
+ captionLogicalTop += caption->paginationStrut();
+ caption->setPaginationStrut(0);
+ }
+ caption->setLogicalLocation(LayoutPoint(caption->marginStart(), captionLogicalTop));
- if (!selfNeedsLayout() && caption->checkForRepaintDuringLayout())
+ if (!selfNeedsLayout() && caption->checkForPaintInvalidationDuringLayout())
caption->repaintDuringLayoutIfMoved(captionRect);
setLogicalHeight(logicalHeight() + caption->logicalHeight() + collapsedMarginBeforeForChild(caption) + collapsedMarginAfterForChild(caption));
@@ -409,172 +403,179 @@ void RenderTable::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
-
if (simplifiedLayout())
return;
+ // Note: RenderTable is handled differently than other RenderBlocks and the LayoutScope
+ // must be created before the table begins laying out.
+ FastTextAutosizer::LayoutScope fastTextAutosizerLayoutScope(this);
+
recalcSectionsIfNeeded();
// FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
// to call this before we call borderStart/borderEnd to avoid getting a stale value.
recalcBordersInRowDirection();
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
-
- setLogicalHeight(0);
-
- LayoutUnit oldLogicalWidth = logicalWidth();
- updateLogicalWidth();
-
- SubtreeLayoutScope layouter(this);
-
- if (logicalWidth() != oldLogicalWidth) {
- for (unsigned i = 0; i < m_captions.size(); i++)
- layouter.setNeedsLayout(m_captions[i]);
- }
- // FIXME: The optimisation below doesn't work since the internal table
- // layout could have changed. we need to add a flag to the table
- // layout that tells us if something has changed in the min max
- // calculations to do it correctly.
-// if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
- m_tableLayout->layout();
-
- LayoutUnit totalSectionLogicalHeight = 0;
- LayoutUnit oldTableLogicalTop = 0;
- for (unsigned i = 0; i < m_captions.size(); i++)
- oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout());
+ SubtreeLayoutScope layouter(*this);
- bool collapsing = collapseBorders();
-
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
- if (m_columnLogicalWidthChanged)
- layouter.setChildNeedsLayout(section);
- section->layoutIfNeeded();
- totalSectionLogicalHeight += section->calcRowLogicalHeight();
- if (collapsing)
- section->recalcOuterBorder();
- ASSERT(!section->needsLayout());
- } else if (child->isRenderTableCol()) {
- child->layoutIfNeeded();
- ASSERT(!child->needsLayout());
- } else {
- // FIXME: We should never have other type of children (they should be wrapped in an
- // anonymous table section) but our code is too crazy and this can happen in practice.
- // Until this is fixed, let's make sure we don't leave non laid out children in the tree.
- child->layoutIfNeeded();
- }
- }
// If any table section moved vertically, we will just repaint everything from that
// section down (it is quite unlikely that any of the following sections
// did not shift).
bool sectionMoved = false;
LayoutUnit movedSectionLogicalTop = 0;
+ {
+ LayoutState state(*this, locationOffset());
- // FIXME: Collapse caption margin.
- if (!m_captions.isEmpty()) {
- for (unsigned i = 0; i < m_captions.size(); i++) {
- if (m_captions[i]->style()->captionSide() == CAPBOTTOM)
- continue;
- layoutCaption(m_captions[i]);
- }
- if (logicalHeight() != oldTableLogicalTop) {
- sectionMoved = true;
- movedSectionLogicalTop = min(logicalHeight(), oldTableLogicalTop);
+ setLogicalHeight(0);
+
+ LayoutUnit oldLogicalWidth = logicalWidth();
+ updateLogicalWidth();
+
+ if (logicalWidth() != oldLogicalWidth) {
+ for (unsigned i = 0; i < m_captions.size(); i++)
+ layouter.setNeedsLayout(m_captions[i]);
}
- }
+ // FIXME: The optimisation below doesn't work since the internal table
+ // layout could have changed. We need to add a flag to the table
+ // layout that tells us if something has changed in the min max
+ // calculations to do it correctly.
+ // if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
+ m_tableLayout->layout();
+
+ LayoutUnit totalSectionLogicalHeight = 0;
+ LayoutUnit oldTableLogicalTop = 0;
+ for (unsigned i = 0; i < m_captions.size(); i++)
+ oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
- LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
- LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
+ bool collapsing = collapseBorders();
- setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isTableSection()) {
+ RenderTableSection* section = toRenderTableSection(child);
+ if (m_columnLogicalWidthChanged)
+ layouter.setChildNeedsLayout(section);
+ section->layoutIfNeeded();
+ totalSectionLogicalHeight += section->calcRowLogicalHeight();
+ if (collapsing)
+ section->recalcOuterBorder();
+ ASSERT(!section->needsLayout());
+ } else if (child->isRenderTableCol()) {
+ child->layoutIfNeeded();
+ ASSERT(!child->needsLayout());
+ } else {
+ // FIXME: We should never have other type of children (they should be wrapped in an
+ // anonymous table section) but our code is too crazy and this can happen in practice.
+ // Until this is fixed, let's make sure we don't leave non laid out children in the tree.
+ child->layoutIfNeeded();
+ }
+ }
+
+ // FIXME: Collapse caption margin.
+ if (!m_captions.isEmpty()) {
+ for (unsigned i = 0; i < m_captions.size(); i++) {
+ if (m_captions[i]->style()->captionSide() == CAPBOTTOM)
+ continue;
+ layoutCaption(m_captions[i]);
+ }
+ if (logicalHeight() != oldTableLogicalTop) {
+ sectionMoved = true;
+ movedSectionLogicalTop = min(logicalHeight(), oldTableLogicalTop);
+ }
+ }
- if (!isOutOfFlowPositioned())
- updateLogicalHeight();
+ LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
+ LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
- LayoutUnit computedLogicalHeight = 0;
+ setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
- Length logicalHeightLength = style()->logicalHeight();
- if (logicalHeightLength.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
- computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
+ if (!isOutOfFlowPositioned())
+ updateLogicalHeight();
- Length logicalMaxHeightLength = style()->logicalMaxHeight();
- if (logicalMaxHeightLength.isIntrinsic() || (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative())) {
- LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
- computedLogicalHeight = min(computedLogicalHeight, computedMaxLogicalHeight);
- }
+ LayoutUnit computedLogicalHeight = 0;
- Length logicalMinHeightLength = style()->logicalMinHeight();
- if (logicalMinHeightLength.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
- LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
- computedLogicalHeight = max(computedLogicalHeight, computedMinLogicalHeight);
- }
+ Length logicalHeightLength = style()->logicalHeight();
+ if (logicalHeightLength.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
+ computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
- distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
+ Length logicalMaxHeightLength = style()->logicalMaxHeight();
+ if (logicalMaxHeightLength.isIntrinsic() || (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative())) {
+ LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
+ computedLogicalHeight = min(computedLogicalHeight, computedMaxLogicalHeight);
+ }
- for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
- section->layoutRows();
+ Length logicalMinHeightLength = style()->logicalMinHeight();
+ if (logicalMinHeightLength.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
+ LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
+ computedLogicalHeight = max(computedLogicalHeight, computedMinLogicalHeight);
+ }
- if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document().inQuirksMode()) {
- // Completely empty tables (with no sections or anything) should at least honor specified height
- // in strict mode.
- setLogicalHeight(logicalHeight() + computedLogicalHeight);
- }
+ distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
- LayoutUnit sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
- if (!collapsing)
- sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
+ for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
+ section->layoutRows();
- // position the table sections
- RenderTableSection* section = topSection();
- while (section) {
- if (!sectionMoved && section->logicalTop() != logicalHeight()) {
- sectionMoved = true;
- movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
+ if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document().inQuirksMode()) {
+ // Completely empty tables (with no sections or anything) should at least honor specified height
+ // in strict mode.
+ setLogicalHeight(logicalHeight() + computedLogicalHeight);
}
- section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
- setLogicalHeight(logicalHeight() + section->logicalHeight());
- section = sectionBelow(section);
- }
+ LayoutUnit sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
+ if (!collapsing)
+ sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
- setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
+ // position the table sections
+ RenderTableSection* section = topSection();
+ while (section) {
+ if (!sectionMoved && section->logicalTop() != logicalHeight()) {
+ sectionMoved = true;
+ movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
+ }
+ section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
- for (unsigned i = 0; i < m_captions.size(); i++) {
- if (m_captions[i]->style()->captionSide() != CAPBOTTOM)
- continue;
- layoutCaption(m_captions[i]);
- }
+ setLogicalHeight(logicalHeight() + section->logicalHeight());
+ section = sectionBelow(section);
+ }
+
+ setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
+
+ for (unsigned i = 0; i < m_captions.size(); i++) {
+ if (m_captions[i]->style()->captionSide() != CAPBOTTOM)
+ continue;
+ layoutCaption(m_captions[i]);
+ }
- if (isOutOfFlowPositioned())
- updateLogicalHeight();
+ if (isOutOfFlowPositioned())
+ updateLogicalHeight();
- // table can be containing block of positioned elements.
- // FIXME: Only pass true if width or height changed.
- layoutPositionedObjects(true);
+ // table can be containing block of positioned elements.
+ // FIXME: Only pass true if width or height changed.
+ layoutPositionedObjects(true);
- updateLayerTransform();
+ updateLayerTransformAfterLayout();
- // Layout was changed, so probably borders too.
- invalidateCollapsedBorders();
+ // Layout was changed, so probably borders too.
+ invalidateCollapsedBorders();
- computeOverflow(clientLogicalBottom());
+ computeOverflow(clientLogicalBottom());
+ }
- statePusher.pop();
+ // FIXME: This value isn't the intrinsic content logical height, but we need
+ // to update the value as its used by flexbox layout. crbug.com/367324
+ updateIntrinsicContentLogicalHeight(contentLogicalHeight());
if (view()->layoutState()->pageLogicalHeight())
- setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
+ setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(*this, logicalTop()));
bool didFullRepaint = repainter.repaintAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
- if (!didFullRepaint && sectionMoved) {
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()
+ && !didFullRepaint && sectionMoved) {
if (style()->isHorizontalWritingMode())
- repaintRectangle(LayoutRect(visualOverflowRect().x(), movedSectionLogicalTop, visualOverflowRect().width(), visualOverflowRect().maxY() - movedSectionLogicalTop));
+ invalidatePaintRectangle(LayoutRect(visualOverflowRect().x(), movedSectionLogicalTop, visualOverflowRect().width(), visualOverflowRect().maxY() - movedSectionLogicalTop));
else
- repaintRectangle(LayoutRect(movedSectionLogicalTop, visualOverflowRect().y(), visualOverflowRect().maxX() - movedSectionLogicalTop, visualOverflowRect().height()));
+ invalidatePaintRectangle(LayoutRect(movedSectionLogicalTop, visualOverflowRect().y(), visualOverflowRect().maxX() - movedSectionLogicalTop, visualOverflowRect().height()));
}
m_columnLogicalWidthChanged = false;
@@ -591,14 +592,10 @@ void RenderTable::recalcCollapsedBorders()
for (RenderObject* section = firstChild(); section; section = section->nextSibling()) {
if (!section->isTableSection())
continue;
- for (RenderObject* row = section->firstChild(); row; row = row->nextSibling()) {
- if (!row->isTableRow())
- continue;
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (!cell->isTableCell())
- continue;
- ASSERT(toRenderTableCell(cell)->table() == this);
- toRenderTableCell(cell)->collectBorderValues(m_collapsedBorders);
+ for (RenderTableRow* row = toRenderTableSection(section)->firstRow(); row; row = row->nextRow()) {
+ for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
+ ASSERT(cell->table() == this);
+ cell->collectBorderValues(m_collapsedBorders);
}
}
}
@@ -640,10 +637,9 @@ void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
PaintPhase paintPhase = paintInfo.phase;
- if (!isRoot()) {
+ if (!isDocumentElement()) {
LayoutRect overflowBox = visualOverflowRect();
flipForWritingMode(overflowBox);
- overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
overflowBox.moveBy(adjustedPaintOffset);
if (!overflowBox.intersects(paintInfo.rect))
return;
@@ -773,13 +769,13 @@ void RenderTable::computePreferredLogicalWidths()
m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
RenderStyle* styleToUse = style();
- // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
+ // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for min-width.
if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
}
- // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
+ // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for maxWidth.
if (styleToUse->logicalMaxWidth().isFixed()) {
// We don't constrain m_minPreferredLogicalWidth as the table should be at least the size of its min-content, regardless of 'max-width'.
m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
@@ -827,6 +823,10 @@ void RenderTable::appendColumn(unsigned span)
unsigned newColumnIndex = m_columns.size();
m_columns.append(ColumnStruct(span));
+ // Unless the table has cell(s) with colspan that exceed the number of columns afforded
+ // by the other rows in the table we can use the fast path when mapping columns to effective columns.
+ m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
+
// Propagate the change in our columns representation to the sections that don't need
// cell recalc. If they do, they will be synced up directly with m_columns later.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
@@ -901,6 +901,7 @@ void RenderTable::recalcSections() const
m_foot = 0;
m_firstBody = 0;
m_hasColElements = false;
+ m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
// We need to get valid pointers to caption, head, foot and first body again
RenderObject* nextSibling;
@@ -1331,9 +1332,12 @@ void RenderTable::updateFirstLetter()
int RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
{
ASSERT(linePositionMode == PositionOnContainingLine);
- LayoutUnit baseline = firstLineBoxBaseline();
- if (baseline != -1)
+ int baseline = firstLineBoxBaseline();
+ if (baseline != -1) {
+ if (isInline())
+ return beforeMarginInLineDirection(direction) + baseline;
return baseline;
+ }
return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
}
@@ -1367,9 +1371,9 @@ int RenderTable::firstLineBoxBaseline() const
return -1;
}
-LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy)
{
- LayoutRect rect = RenderBlock::overflowClipRect(location, region, relevancy);
+ LayoutRect rect = RenderBlock::overflowClipRect(location, relevancy);
// If we have a caption, expand the clip to include the caption.
// FIXME: Technically this is wrong, but it's virtually impossible to fix this
@@ -1395,7 +1399,7 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
LayoutPoint adjustedLocation = accumulatedOffset + location();
// Check kids first.
- if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region()))) {
+ if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation))) {
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTable.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTable.h
index ba7ab67b752..811c28668db 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTable.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTable.h
@@ -25,7 +25,7 @@
#ifndef RenderTable_h
#define RenderTable_h
-#include "CSSPropertyNames.h"
+#include "core/CSSPropertyNames.h"
#include "core/rendering/RenderBlock.h"
#include "core/rendering/style/CollapsedBorderValue.h"
#include "wtf/Vector.h"
@@ -52,33 +52,33 @@ public:
bool collapseBorders() const { return style()->borderCollapse(); }
- int borderStart() const { return m_borderStart; }
- int borderEnd() const { return m_borderEnd; }
- int borderBefore() const;
- int borderAfter() const;
+ virtual int borderStart() const OVERRIDE { return m_borderStart; }
+ virtual int borderEnd() const OVERRIDE { return m_borderEnd; }
+ virtual int borderBefore() const OVERRIDE;
+ virtual int borderAfter() const OVERRIDE;
- int borderLeft() const
+ virtual int borderLeft() const OVERRIDE
{
if (style()->isHorizontalWritingMode())
return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
}
- int borderRight() const
+ virtual int borderRight() const OVERRIDE
{
if (style()->isHorizontalWritingMode())
return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
}
- int borderTop() const
+ virtual int borderTop() const OVERRIDE
{
if (style()->isHorizontalWritingMode())
return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
}
- int borderBottom() const
+ virtual int borderBottom() const OVERRIDE
{
if (style()->isHorizontalWritingMode())
return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
@@ -124,7 +124,7 @@ public:
int calcBorderEnd() const;
void recalcBordersInRowDirection();
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
struct ColumnStruct {
explicit ColumnStruct(unsigned initialSpan = 1)
@@ -171,6 +171,9 @@ public:
unsigned colToEffCol(unsigned column) const
{
+ if (!m_hasCellColspanThatDeterminesTableWidth)
+ return column;
+
unsigned effColumn = 0;
unsigned numColumns = numEffCols();
for (unsigned c = 0; effColumn < numColumns && c + m_columns[effColumn].span - 1 < column; ++effColumn)
@@ -180,6 +183,9 @@ public:
unsigned effColToCol(unsigned effCol) const
{
+ if (!m_hasCellColspanThatDeterminesTableWidth)
+ return effCol;
+
unsigned c = 0;
for (unsigned i = 0; i < effCol; i++)
c += m_columns[i].span;
@@ -221,7 +227,7 @@ public:
if (documentBeingDestroyed())
return;
m_needsSectionRecalc = true;
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
}
RenderTableSection* sectionAbove(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
@@ -263,22 +269,21 @@ public:
void removeColumn(const RenderTableCol*);
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void simplifiedNormalFlowLayout();
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual void simplifiedNormalFlowLayout() OVERRIDE;
private:
- virtual const char* renderName() const { return "RenderTable"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderTable"; }
- virtual bool isTable() const { return true; }
+ virtual bool isTable() const OVERRIDE { return true; }
- virtual bool avoidsFloats() const { return true; }
+ virtual bool avoidsFloats() const OVERRIDE { return true; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual void paintObject(PaintInfo&, const LayoutPoint&);
- virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
- virtual void paintMask(PaintInfo&, const LayoutPoint&);
- virtual void layout();
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void paintMask(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void layout() OVERRIDE;
virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
@@ -292,17 +297,17 @@ private:
void updateColumnCache() const;
void invalidateCachedColumns();
- virtual RenderBlock* firstLineBlock() const;
- virtual void updateFirstLetter();
+ virtual RenderBlock* firstLineBlock() const OVERRIDE;
+ virtual void updateFirstLetter() OVERRIDE;
virtual void updateLogicalWidth() OVERRIDE;
LayoutUnit convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth);
LayoutUnit convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight);
- virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
+ virtual LayoutRect overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) OVERRIDE;
- virtual void addOverflowFromChildren();
+ virtual void addOverflowFromChildren() OVERRIDE;
void subtractCaptionRect(LayoutRect&) const;
@@ -332,6 +337,15 @@ private:
bool m_columnLogicalWidthChanged : 1;
mutable bool m_columnRenderersValid: 1;
+ mutable bool m_hasCellColspanThatDeterminesTableWidth : 1;
+ bool hasCellColspanThatDeterminesTableWidth() const
+ {
+ for (unsigned c = 0; c < numEffCols(); c++) {
+ if (m_columns[c].span > 1)
+ return true;
+ }
+ return false;
+ }
short m_hSpacing;
short m_vSpacing;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.cpp
index af677b71de9..24dc5eccb48 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.cpp
@@ -48,7 +48,7 @@ void RenderTableCaption::insertedIntoTree()
void RenderTableCaption::willBeRemovedFromTree()
{
- RenderBlock::willBeRemovedFromTree();
+ RenderBlockFlow::willBeRemovedFromTree();
table()->removeCaption(this);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.h
index 35755a9d03b..d24acf84184 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCaption.h
@@ -35,8 +35,6 @@ public:
private:
virtual bool isTableCaption() const OVERRIDE { return true; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
-
virtual void insertedIntoTree() OVERRIDE;
virtual void willBeRemovedFromTree() OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.cpp
index 9737da43de8..5cf8270ad12 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.cpp
@@ -25,10 +25,9 @@
#include "config.h"
#include "core/rendering/RenderTableCell.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/css/StylePropertySet.h"
#include "core/html/HTMLTableCellElement.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderTableCol.h"
#include "core/rendering/RenderView.h"
@@ -66,7 +65,7 @@ RenderTableCell::RenderTableCell(Element* element)
void RenderTableCell::willBeRemovedFromTree()
{
- RenderBlock::willBeRemovedFromTree();
+ RenderBlockFlow::willBeRemovedFromTree();
section()->setNeedsCellRecalc();
section()->removeCachedCollapsedBorders(this);
@@ -75,16 +74,16 @@ void RenderTableCell::willBeRemovedFromTree()
unsigned RenderTableCell::parseColSpanFromDOM() const
{
ASSERT(node());
- if (node()->hasTagName(tdTag) || node()->hasTagName(thTag))
- return min<unsigned>(toHTMLTableCellElement(node())->colSpan(), maxColumnIndex);
+ if (isHTMLTableCellElement(*node()))
+ return min<unsigned>(toHTMLTableCellElement(*node()).colSpan(), maxColumnIndex);
return 1;
}
unsigned RenderTableCell::parseRowSpanFromDOM() const
{
ASSERT(node());
- if (node()->hasTagName(tdTag) || node()->hasTagName(thTag))
- return min<unsigned>(toHTMLTableCellElement(node())->rowSpan(), maxRowIndex);
+ if (isHTMLTableCellElement(*node()))
+ return min<unsigned>(toHTMLTableCellElement(*node()).rowSpan(), maxRowIndex);
return 1;
}
@@ -99,13 +98,13 @@ void RenderTableCell::updateColAndRowSpanFlags()
void RenderTableCell::colSpanOrRowSpanChanged()
{
ASSERT(node());
- ASSERT(node()->hasTagName(tdTag) || node()->hasTagName(thTag));
+ ASSERT(isHTMLTableCellElement(*node()));
updateColAndRowSpanFlags();
// FIXME: I suspect that we could return early here if !m_hasColSpan && !m_hasRowSpan.
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
if (parent() && section())
section()->setNeedsCellRecalc();
}
@@ -149,7 +148,7 @@ void RenderTableCell::computePreferredLogicalWidths()
// grids. We must refresh those grids before the child cells try to use them.
table()->recalcSectionsIfNeeded();
- RenderBlock::computePreferredLogicalWidths();
+ RenderBlockFlow::computePreferredLogicalWidths();
if (node() && style()->autoWrap()) {
// See if nowrap was set.
Length w = styleOrColLogicalWidth();
@@ -226,8 +225,8 @@ void RenderTableCell::setCellLogicalWidth(int tableLayoutLogicalWidth, SubtreeLa
layouter.setNeedsLayout(this);
- if (!table()->selfNeedsLayout() && checkForRepaintDuringLayout())
- repaint();
+ if (!table()->selfNeedsLayout() && checkForPaintInvalidationDuringLayout())
+ paintInvalidationForWholeRenderer();
setLogicalWidth(tableLayoutLogicalWidth);
setCellWidthChanged(true);
@@ -237,8 +236,6 @@ void RenderTableCell::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
-
updateFirstLetter();
int oldCellBaseline = cellBaselinePosition();
@@ -251,11 +248,15 @@ void RenderTableCell::layout()
if (isBaselineAligned() && section()->rowBaseline(rowIndex()) && cellBaselinePosition() > section()->rowBaseline(rowIndex())) {
int newIntrinsicPaddingBefore = max<LayoutUnit>(0, intrinsicPaddingBefore() - max<LayoutUnit>(0, cellBaselinePosition() - oldCellBaseline));
setIntrinsicPaddingBefore(newIntrinsicPaddingBefore);
- SubtreeLayoutScope layouter(this);
+ SubtreeLayoutScope layouter(*this);
layouter.setNeedsLayout(this);
layoutBlock(cellWidthChanged());
}
+ // FIXME: This value isn't the intrinsic content logical height, but we need
+ // to update the value as its used by flexbox layout. crbug.com/367324
+ updateIntrinsicContentLogicalHeight(contentLogicalHeight());
+
setCellWidthChanged(false);
}
@@ -307,25 +308,25 @@ void RenderTableCell::setOverrideLogicalContentHeightFromRowHeight(LayoutUnit ro
setOverrideLogicalContentHeight(max<LayoutUnit>(0, rowHeight - borderAndPaddingLogicalHeight()));
}
-LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+LayoutSize RenderTableCell::offsetFromContainer(const RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
{
ASSERT(o == container());
- LayoutSize offset = RenderBlock::offsetFromContainer(o, point, offsetDependsOnPoint);
+ LayoutSize offset = RenderBlockFlow::offsetFromContainer(o, point, offsetDependsOnPoint);
if (parent())
offset -= parentBox()->locationOffset();
return offset;
}
-LayoutRect RenderTableCell::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderTableCell::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
// If the table grid is dirty, we cannot get reliable information about adjoining cells,
// so we ignore outside borders. This should not be a problem because it means that
// the table is going to recalculate the grid, relayout and repaint its current rect, which
// includes any outside borders of this cell.
if (!table()->collapseBorders() || table()->needsSectionRecalc())
- return RenderBlock::clippedOverflowRectForRepaint(repaintContainer);
+ return RenderBlockFlow::clippedOverflowRectForPaintInvalidation(paintInvalidationContainer);
bool rtl = !styleForCellFlow()->isLeftToRightDirection();
int outlineSize = style()->outlineSize();
@@ -360,24 +361,26 @@ LayoutRect RenderTableCell::clippedOverflowRectForRepaint(const RenderLayerModel
LayoutPoint location(max<LayoutUnit>(left, -visualOverflowRect().x()), max<LayoutUnit>(top, -visualOverflowRect().y()));
LayoutRect r(-location.x(), -location.y(), location.x() + max(width() + right, visualOverflowRect().maxX()), location.y() + max(height() + bottom, visualOverflowRect().maxY()));
- if (RenderView* v = view()) {
- // FIXME: layoutDelta needs to be applied in parts before/after transforms and
- // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
- r.move(v->layoutDelta());
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ if (RenderView* v = view()) {
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+ r.move(v->layoutDelta());
+ }
}
- computeRectForRepaint(repaintContainer, r);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, r);
return r;
}
-void RenderTableCell::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& r, bool fixed) const
+void RenderTableCell::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& r, bool fixed) const
{
- if (repaintContainer == this)
+ if (paintInvalidationContainer == this)
return;
r.setY(r.y());
RenderView* v = view();
- if ((!v || !v->layoutStateEnabled() || repaintContainer) && parent())
+ if ((!v || !v->canMapUsingLayoutStateForContainer(paintInvalidationContainer)) && parent())
r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in.
- RenderBlock::computeRectForRepaint(repaintContainer, r, fixed);
+ RenderBlockFlow::mapRectToPaintInvalidationBacking(paintInvalidationContainer, r, fixed);
}
LayoutUnit RenderTableCell::cellBaselinePosition() const
@@ -396,7 +399,7 @@ void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* ol
ASSERT(style()->display() == TABLE_CELL);
ASSERT(!row() || row()->rowIndexWasSet());
- RenderBlock::styleDidChange(diff, oldStyle);
+ RenderBlockFlow::styleDidChange(diff, oldStyle);
setHasBoxDecorations(true);
if (parent() && section() && oldStyle && style()->height() != oldStyle->height())
@@ -738,7 +741,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedBeforeBorder(IncludeBorder
if (prevCell->section() == section())
prevRow = parent()->previousSibling();
else
- prevRow = prevCell->section()->lastChild();
+ prevRow = prevCell->section()->lastRow();
if (prevRow) {
result = chooseBorder(CollapsedBorderValue(prevRow->style()->borderAfter(), includeColor ? prevRow->resolveColor(afterColorProperty) : Color(), BROW), result);
@@ -894,44 +897,44 @@ inline CollapsedBorderValue RenderTableCell::cachedCollapsedBottomBorder(const R
int RenderTableCell::borderLeft() const
{
- return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlock::borderLeft();
+ return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlockFlow::borderLeft();
}
int RenderTableCell::borderRight() const
{
- return table()->collapseBorders() ? borderHalfRight(false) : RenderBlock::borderRight();
+ return table()->collapseBorders() ? borderHalfRight(false) : RenderBlockFlow::borderRight();
}
int RenderTableCell::borderTop() const
{
- return table()->collapseBorders() ? borderHalfTop(false) : RenderBlock::borderTop();
+ return table()->collapseBorders() ? borderHalfTop(false) : RenderBlockFlow::borderTop();
}
int RenderTableCell::borderBottom() const
{
- return table()->collapseBorders() ? borderHalfBottom(false) : RenderBlock::borderBottom();
+ return table()->collapseBorders() ? borderHalfBottom(false) : RenderBlockFlow::borderBottom();
}
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=46191, make the collapsed border drawing
// work with different block flow values instead of being hard-coded to top-to-bottom.
int RenderTableCell::borderStart() const
{
- return table()->collapseBorders() ? borderHalfStart(false) : RenderBlock::borderStart();
+ return table()->collapseBorders() ? borderHalfStart(false) : RenderBlockFlow::borderStart();
}
int RenderTableCell::borderEnd() const
{
- return table()->collapseBorders() ? borderHalfEnd(false) : RenderBlock::borderEnd();
+ return table()->collapseBorders() ? borderHalfEnd(false) : RenderBlockFlow::borderEnd();
}
int RenderTableCell::borderBefore() const
{
- return table()->collapseBorders() ? borderHalfBefore(false) : RenderBlock::borderBefore();
+ return table()->collapseBorders() ? borderHalfBefore(false) : RenderBlockFlow::borderBefore();
}
int RenderTableCell::borderAfter() const
{
- return table()->collapseBorders() ? borderHalfAfter(false) : RenderBlock::borderAfter();
+ return table()->collapseBorders() ? borderHalfAfter(false) : RenderBlockFlow::borderAfter();
}
int RenderTableCell::borderHalfLeft(bool outer) const
@@ -1001,7 +1004,7 @@ int RenderTableCell::borderHalfAfter(bool outer) const
void RenderTableCell::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders);
- RenderBlock::paint(paintInfo, paintOffset);
+ RenderBlockFlow::paint(paintInfo, paintOffset);
}
static EBorderStyle collapsedBorderStyle(EBorderStyle style)
@@ -1105,14 +1108,11 @@ void RenderTableCell::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutPo
if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE)
return;
- LayoutRect localRepaintRect = paintInfo.rect;
- localRepaintRect.inflate(maximalOutlineSize(paintInfo.phase));
-
LayoutRect paintRect = LayoutRect(paintOffset + location(), pixelSnappedSize());
- if (paintRect.y() - table()->outerBorderTop() >= localRepaintRect.maxY())
+ if (paintRect.y() - table()->outerBorderTop() >= paintInfo.rect.maxY())
return;
- if (paintRect.maxY() + table()->outerBorderBottom() <= localRepaintRect.y())
+ if (paintRect.maxY() + table()->outerBorderBottom() <= paintInfo.rect.y())
return;
GraphicsContext* graphicsContext = paintInfo.context;
@@ -1159,7 +1159,7 @@ void RenderTableCell::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutPo
for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
if (border->borderValue.isSameIgnoringColor(*table()->currentBorderValue())) {
drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side,
- resolveColor(border->borderValue.color()), border->style, 0, 0, antialias);
+ border->borderValue.color().resolve(style()->visitedDependentColor(CSSPropertyColor)), border->style, 0, 0, antialias);
}
}
}
@@ -1186,7 +1186,7 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, const Lay
Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor);
const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
- if (bgLayer->hasImage() || c.isValid()) {
+ if (bgLayer->hasImage() || c.alpha()) {
// We have to clip here because the background would paint
// on top of the borders otherwise. This only matters for cells and rows.
bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.h
index 9eeb48e4f01..dcffc575763 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCell.h
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2013 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,6 +28,7 @@
#include "core/rendering/RenderBlockFlow.h"
#include "core/rendering/RenderTableRow.h"
#include "core/rendering/RenderTableSection.h"
+#include "platform/LengthFunctions.h"
namespace WebCore {
@@ -76,6 +77,9 @@ public:
RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
+ RenderTableCell* previousCell() const;
+ RenderTableCell* nextCell() const;
+
unsigned rowIndex() const
{
// This function shouldn't be called on a detached cell.
@@ -97,7 +101,7 @@ public:
{
// FIXME: This function does too much work, and is very hot during table layout!
int adjustedLogicalHeight = pixelSnappedLogicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
- int styleLogicalHeight = valueForLength(style()->logicalHeight(), 0, view());
+ int styleLogicalHeight = valueForLength(style()->logicalHeight(), 0);
// In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
// Call computedCSSPadding* directly to avoid including implicitPadding.
if (!document().inQuirksMode() && style()->boxSizing() != BORDER_BOX)
@@ -108,23 +112,21 @@ public:
void setCellLogicalWidth(int constrainedLogicalWidth, SubtreeLayoutScope&);
- virtual int borderLeft() const;
- virtual int borderRight() const;
- virtual int borderTop() const;
- virtual int borderBottom() const;
- virtual int borderStart() const;
- virtual int borderEnd() const;
- virtual int borderBefore() const;
- virtual int borderAfter() const;
+ virtual int borderLeft() const OVERRIDE;
+ virtual int borderRight() const OVERRIDE;
+ virtual int borderTop() const OVERRIDE;
+ virtual int borderBottom() const OVERRIDE;
+ virtual int borderStart() const OVERRIDE;
+ virtual int borderEnd() const OVERRIDE;
+ virtual int borderBefore() const OVERRIDE;
+ virtual int borderAfter() const OVERRIDE;
void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
static void sortBorderValues(RenderTable::CollapsedBorderValues&);
- virtual void layout();
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual void layout() OVERRIDE;
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
void paintCollapsedBorders(PaintInfo&, const LayoutPoint&);
void paintBackgroundsBehindCell(PaintInfo&, const LayoutPoint&, RenderObject* backgroundObject);
@@ -155,7 +157,7 @@ public:
void setOverrideLogicalContentHeightFromRowHeight(LayoutUnit);
- virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged);
+ virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged) OVERRIDE;
bool cellWidthChanged() const { return m_cellWidthChanged; }
void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
@@ -216,28 +218,28 @@ public:
}
#endif
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual void computePreferredLogicalWidths();
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual void computePreferredLogicalWidths() OVERRIDE;
virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE;
private:
- virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
+ virtual const char* renderName() const OVERRIDE { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
- virtual bool isTableCell() const { return true; }
+ virtual bool isTableCell() const OVERRIDE { return true; }
virtual void willBeRemovedFromTree() OVERRIDE;
virtual void updateLogicalWidth() OVERRIDE;
- virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
- virtual void paintMask(PaintInfo&, const LayoutPoint&);
+ virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void paintMask(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE;
- virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+ virtual LayoutSize offsetFromContainer(const RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const OVERRIDE;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
int borderHalfLeft(bool outer) const;
int borderHalfRight(bool outer) const;
@@ -278,6 +280,9 @@ private:
unsigned parseRowSpanFromDOM() const;
unsigned parseColSpanFromDOM() const;
+ void nextSibling() const WTF_DELETED_FUNCTION;
+ void previousSibling() const WTF_DELETED_FUNCTION;
+
// Note MSVC will only pack members if they have identical types, hence we use unsigned instead of bool here.
unsigned m_column : 29;
unsigned m_cellWidthChanged : 1;
@@ -289,6 +294,28 @@ private:
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTableCell, isTableCell());
+inline RenderTableCell* RenderTableCell::previousCell() const
+{
+ return toRenderTableCell(RenderObject::previousSibling());
+}
+
+inline RenderTableCell* RenderTableCell::nextCell() const
+{
+ return toRenderTableCell(RenderObject::nextSibling());
+}
+
+inline RenderTableCell* RenderTableRow::firstCell() const
+{
+ ASSERT(children() == virtualChildren());
+ return toRenderTableCell(children()->firstChild());
+}
+
+inline RenderTableCell* RenderTableRow::lastCell() const
+{
+ ASSERT(children() == virtualChildren());
+ return toRenderTableCell(children()->lastChild());
+}
+
} // namespace WebCore
#endif // RenderTableCell_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.cpp
index 26c5935f97f..b27a30d75aa 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "core/rendering/RenderTableCol.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/html/HTMLTableColElement.h"
#include "core/rendering/RenderTable.h"
#include "core/rendering/RenderTableCell.h"
@@ -60,13 +60,13 @@ void RenderTableCol::updateFromElement()
{
unsigned oldSpan = m_span;
Node* n = node();
- if (n && (n->hasTagName(colTag) || n->hasTagName(colgroupTag))) {
- HTMLTableColElement* tc = toHTMLTableColElement(n);
- m_span = tc->span();
+ if (isHTMLTableColElement(n)) {
+ HTMLTableColElement& tc = toHTMLTableColElement(*n);
+ m_span = tc.span();
} else
m_span = !(style() && style()->display() == TABLE_COLUMN_GROUP);
if (m_span != oldSpan && style() && parent())
- setNeedsLayoutAndPrefWidthsRecalc();
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderTableCol::insertedIntoTree()
@@ -94,23 +94,23 @@ bool RenderTableCol::canHaveChildren() const
return isTableColumnGroup();
}
-LayoutRect RenderTableCol::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderTableCol::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
// For now, just repaint the whole table.
// FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
// might have propagated a background color or borders into.
- // FIXME: check for repaintContainer each time here?
+ // FIXME: check for paintInvalidationContainer each time here?
RenderTable* parentTable = table();
if (!parentTable)
return LayoutRect();
- return parentTable->clippedOverflowRectForRepaint(repaintContainer);
+ return parentTable->clippedOverflowRectForPaintInvalidation(paintInvalidationContainer);
}
void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
{
// FIXME: Repaint only the rect the image paints in.
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderTableCol::clearPreferredLogicalWidthsDirtyBits()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.h
index a28f36085bb..acb7d01e89c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableCol.h
@@ -40,6 +40,10 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderTableCol, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
@@ -77,25 +81,25 @@ public:
const BorderValue& borderAdjoiningCellAfter(const RenderTableCell*) const;
private:
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ virtual RenderObjectChildList* virtualChildren() OVERRIDE { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const OVERRIDE { return children(); }
- virtual const char* renderName() const { return "RenderTableCol"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderTableCol"; }
virtual bool isRenderTableCol() const OVERRIDE { return true; }
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
virtual void computePreferredLogicalWidths() OVERRIDE { ASSERT_NOT_REACHED(); }
virtual void insertedIntoTree() OVERRIDE;
virtual void willBeRemovedFromTree() OVERRIDE;
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
- virtual bool canHaveChildren() const;
- virtual bool requiresLayer() const { return false; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+ virtual bool canHaveChildren() const OVERRIDE;
+ virtual LayerType layerTypeRequired() const OVERRIDE { return NoLayer; }
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
RenderTable* table() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.cpp
index 528ae08d38c..f1f7ef78242 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.cpp
@@ -1,10 +1,10 @@
-/**
+/*
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,12 +25,11 @@
#include "config.h"
#include "core/rendering/RenderTableRow.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/fetch/ImageResource.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderView.h"
@@ -80,7 +79,7 @@ void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* old
if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
table->invalidateCollapsedBorders();
- if (table && oldStyle && diff == StyleDifferenceLayout && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
+ if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
// If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
// This only happens when borders are collapsed, since they end up affecting the border sides of the cell
// itself.
@@ -112,11 +111,12 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
if (!child->isTableCell()) {
RenderObject* last = beforeChild;
if (!last)
- last = lastChild();
+ last = lastCell();
if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
- if (beforeChild == last)
- beforeChild = last->firstChild();
- last->addChild(child, beforeChild);
+ RenderTableCell* lastCell = toRenderTableCell(last);
+ if (beforeChild == lastCell)
+ beforeChild = lastCell->firstChild();
+ lastCell->addChild(child, beforeChild);
return;
}
@@ -152,7 +152,7 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
ASSERT(!beforeChild || beforeChild->isTableCell());
RenderBox::addChild(cell, beforeChild);
- if (beforeChild || nextSibling())
+ if (beforeChild || nextRow())
section()->setNeedsCellRecalc();
}
@@ -160,74 +160,55 @@ void RenderTableRow::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
-
// Table rows do not add translation.
- LayoutStateMaintainer statePusher(view(), this, LayoutSize(), style()->isFlippedBlocksWritingMode());
-
- bool paginated = view()->layoutState()->isPaginated();
-
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableCell()) {
- SubtreeLayoutScope layouter(child);
- RenderTableCell* cell = toRenderTableCell(child);
- if (!cell->needsLayout() && paginated && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
- layouter.setChildNeedsLayout(cell);
-
- if (child->needsLayout()) {
- cell->computeAndSetBlockDirectionMargins(table());
- cell->layout();
- }
+ LayoutState state(*this, LayoutSize());
+
+ for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
+ SubtreeLayoutScope layouter(*cell);
+ if (!cell->needsLayout())
+ cell->markForPaginationRelayoutIfNeeded(layouter);
+ if (cell->needsLayout()) {
+ cell->computeAndSetBlockDirectionMargins(table());
+ cell->layout();
}
}
- // We only ever need to repaint if our cells didn't, which menas that they didn't need
+ m_overflow.clear();
+ addVisualEffectOverflow();
+
+ // We only ever need to issue paint invalidations if our cells didn't, which means that they didn't need
// layout, so we know that our bounds didn't change. This code is just making up for
- // the fact that we did not repaint in setStyle() because we had a layout hint.
- // We cannot call repaint() because our clippedOverflowRectForRepaint() is taken from the
- // parent table, and being mid-layout, that is invalid. Instead, we repaint our cells.
- if (selfNeedsLayout() && checkForRepaintDuringLayout()) {
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableCell())
- child->repaint();
+ // the fact that we did not invalidate paints in setStyle() because we had a layout hint.
+ // We cannot call repaint() because our clippedOverflowRectForPaintInvalidation() is taken from the
+ // parent table, and being mid-layout, that is invalid. Instead, we issue paint invalidations for our cells.
+ if (selfNeedsLayout() && checkForPaintInvalidation()) {
+ for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ // FIXME: Is this needed with Repaint After Layout?
+ cell->setShouldDoFullPaintInvalidationAfterLayout(true);
+ } else {
+ cell->paintInvalidationForWholeRenderer();
+ }
}
}
- statePusher.pop();
// RenderTableSection::layoutRows will set our logical height and width later, so it calls updateLayerTransform().
clearNeedsLayout();
}
-LayoutRect RenderTableRow::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
-{
- ASSERT(parent());
-
- if (repaintContainer == this)
- return RenderBox::clippedOverflowRectForRepaint(repaintContainer);
-
- // For now, just repaint the whole table.
- // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
- // might have propagated a background color into.
- // FIXME: do repaintContainer checks here
- if (RenderTable* parentTable = table())
- return parentTable->clippedOverflowRectForRepaint(repaintContainer);
-
- return LayoutRect();
-}
-
// Hit Testing
bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
// Table rows cannot ever be hit tested. Effectively they do not exist.
// Just forward to our children always.
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+ for (RenderTableCell* cell = lastCell(); cell; cell = cell->previousCell()) {
// FIXME: We have to skip over inline flows, since they can show up inside table rows
// at the moment (a demoted inline <form> for example). If we ever implement a
// table-specific hit-test method (which we should do for performance reasons anyway),
// then we can remove this check.
- if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer()) {
- LayoutPoint cellPoint = flipForWritingModeForChild(toRenderTableCell(child), accumulatedOffset);
- if (child->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
+ if (!cell->hasSelfPaintingLayer()) {
+ LayoutPoint cellPoint = flipForWritingModeForChild(cell, accumulatedOffset);
+ if (cell->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
return true;
}
@@ -251,23 +232,19 @@ void RenderTableRow::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
paintOutlineForRowIfNeeded(paintInfo, paintOffset);
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableCell()) {
- // Paint the row background behind the cell.
- if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackground) {
- RenderTableCell* cell = toRenderTableCell(child);
- cell->paintBackgroundsBehindCell(paintInfo, paintOffset, this);
- }
- if (!toRenderBox(child)->hasSelfPaintingLayer())
- child->paint(paintInfo, paintOffset);
- }
+ for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
+ // Paint the row background behind the cell.
+ if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackground)
+ cell->paintBackgroundsBehindCell(paintInfo, paintOffset, this);
+ if (!cell->hasSelfPaintingLayer())
+ cell->paint(paintInfo, paintOffset);
}
}
void RenderTableRow::imageChanged(WrappedImagePtr, const IntRect*)
{
// FIXME: Examine cells and repaint only the rect the image paints in.
- repaint();
+ paintInvalidationForWholeRenderer();
}
RenderTableRow* RenderTableRow::createAnonymous(Document* document)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.h
index 735f903c627..8dc3550ed97 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableRow.h
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2013 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -36,8 +36,11 @@ class RenderTableRow FINAL : public RenderBox {
public:
explicit RenderTableRow(Element*);
- RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
- RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ RenderTableCell* firstCell() const;
+ RenderTableCell* lastCell() const;
+
+ RenderTableRow* previousRow() const;
+ RenderTableRow* nextRow() const;
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
@@ -88,28 +91,40 @@ public:
const BorderValue& borderAdjoiningStartCell(const RenderTableCell*) const;
const BorderValue& borderAdjoiningEndCell(const RenderTableCell*) const;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
private:
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ virtual RenderObjectChildList* virtualChildren() OVERRIDE { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const OVERRIDE { return children(); }
- virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
+ virtual const char* renderName() const OVERRIDE { return (isAnonymous() || isPseudoElement()) ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
- virtual bool isTableRow() const { return true; }
+ virtual bool isTableRow() const OVERRIDE { return true; }
virtual void willBeRemovedFromTree() OVERRIDE;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void layout();
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual void layout() OVERRIDE;
+
+ virtual LayerType layerTypeRequired() const OVERRIDE
+ {
+ if (hasTransform() || hasHiddenBackface() || hasClipPath() || createsGroup() || isStickyPositioned() || style()->shouldCompositeForCurrentAnimations())
+ return NormalLayer;
+
+ if (hasOverflowClip())
+ return OverflowClipLayer;
- virtual bool requiresLayer() const OVERRIDE { return hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasClipPath() || createsGroup(); }
+ return NoLayer;
+ }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+
+ void nextSibling() const WTF_DELETED_FUNCTION;
+ void previousSibling() const WTF_DELETED_FUNCTION;
RenderObjectChildList m_children;
unsigned m_rowIndex : 31;
@@ -117,6 +132,28 @@ private:
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTableRow, isTableRow());
+inline RenderTableRow* RenderTableRow::previousRow() const
+{
+ return toRenderTableRow(RenderObject::previousSibling());
+}
+
+inline RenderTableRow* RenderTableRow::nextRow() const
+{
+ return toRenderTableRow(RenderObject::nextSibling());
+}
+
+inline RenderTableRow* RenderTableSection::firstRow() const
+{
+ ASSERT(children() == virtualChildren());
+ return toRenderTableRow(children()->firstChild());
+}
+
+inline RenderTableRow* RenderTableSection::lastRow() const
+{
+ ASSERT(children() == virtualChildren());
+ return toRenderTableRow(children()->lastChild());
+}
+
} // namespace WebCore
#endif // RenderTableRow_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.cpp
index ab6d4da9c60..d7dfc425eee 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.cpp
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
* This library is free software; you can redistribute it and/or
@@ -26,12 +26,9 @@
#include "config.h"
#include "core/rendering/RenderTableSection.h"
-// FIXME: Remove 'RuntimeEnabledFeatures.h' when http://crbug.com/78724 is closed.
-#include "RuntimeEnabledFeatures.h"
#include <limits>
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderTableCol.h"
@@ -127,10 +124,10 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
if (!child->isTableRow()) {
RenderObject* last = beforeChild;
if (!last)
- last = lastChild();
+ last = lastRow();
if (last && last->isAnonymous() && !last->isBeforeOrAfterContent()) {
if (beforeChild == last)
- beforeChild = last->firstChild();
+ beforeChild = last->slowFirstChild();
last->addChild(child, beforeChild);
return;
}
@@ -289,7 +286,7 @@ void RenderTableSection::populateSpanningRowsHeightFromCell(RenderTableCell* cel
spanningRowsHeight.rowHeight[row] = m_rowPos[actualRow + 1] - m_rowPos[actualRow] - borderSpacingForRow(actualRow);
if (!spanningRowsHeight.rowHeight[row])
- spanningRowsHeight.rowWithOnlySpanningCells |= rowHasOnlySpanningCells(actualRow);
+ spanningRowsHeight.isAnyRowWithOnlySpanningCells |= rowHasOnlySpanningCells(actualRow);
spanningRowsHeight.totalRowsHeight += spanningRowsHeight.rowHeight[row];
spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing -= borderSpacingForRow(actualRow);
@@ -328,6 +325,17 @@ void RenderTableSection::distributeExtraRowSpanHeightToPercentRows(RenderTableCe
}
}
+// Sometimes the multiplication of the 2 values below will overflow an integer.
+// So we convert the parameters to 'long long' instead of 'int' to avoid the
+// problem in this function.
+static void updatePositionIncreasedWithRowHeight(long long extraHeight, long long rowHeight, long long totalHeight, int& accumulatedPositionIncrease, int& remainder)
+{
+ COMPILE_ASSERT(sizeof(long long int) > sizeof(int), int_should_be_less_than_longlong);
+
+ accumulatedPositionIncrease += (extraHeight * rowHeight) / totalHeight;
+ remainder += (extraHeight * rowHeight) % totalHeight;
+}
+
void RenderTableSection::distributeExtraRowSpanHeightToAutoRows(RenderTableCell* cell, int totalAutoRowsHeight, int& extraRowSpanningHeight, Vector<int>& rowsHeight)
{
if (!extraRowSpanningHeight || !totalAutoRowsHeight)
@@ -342,8 +350,7 @@ void RenderTableSection::distributeExtraRowSpanHeightToAutoRows(RenderTableCell*
// So extra height distributed in auto spanning rows based on their weight in spanning cell.
for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) {
if (m_grid[row].logicalHeight.isAuto()) {
- accumulatedPositionIncrease += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) / totalAutoRowsHeight;
- remainder += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) % totalAutoRowsHeight;
+ updatePositionIncreasedWithRowHeight(extraRowSpanningHeight, rowsHeight[row - rowIndex], totalAutoRowsHeight, accumulatedPositionIncrease, remainder);
// While whole extra spanning height is distributing in auto spanning rows, rational parts remains
// in every integer division. So accumulating all remainder part in integer division and when total remainder
@@ -376,8 +383,7 @@ void RenderTableSection::distributeExtraRowSpanHeightToRemainingRows(RenderTable
// So extra height distribution in remaining spanning rows based on their weight in spanning cell.
for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) {
if (!m_grid[row].logicalHeight.isPercent()) {
- accumulatedPositionIncrease += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) / totalRemainingRowsHeight;
- remainder += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) % totalRemainingRowsHeight;
+ updatePositionIncreasedWithRowHeight(extraRowSpanningHeight, rowsHeight[row - rowIndex], totalRemainingRowsHeight, accumulatedPositionIncrease, remainder);
// While whole extra spanning height is distributing in remaining spanning rows, rational parts remains
// in every integer division. So accumulating all remainder part in integer division and when total remainder
@@ -542,14 +548,31 @@ void RenderTableSection::distributeRowSpanHeightToRows(SpanningRenderTableCells&
populateSpanningRowsHeightFromCell(cell, spanningRowsHeight);
- if (spanningRowsHeight.rowWithOnlySpanningCells)
+ // Here we are handling only row(s) who have only rowspanning cells and do not have any empty cell.
+ if (spanningRowsHeight.isAnyRowWithOnlySpanningCells)
updateRowsHeightHavingOnlySpanningCells(cell, spanningRowsHeight);
- if (!spanningRowsHeight.totalRowsHeight || spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing <= spanningRowsHeight.totalRowsHeight) {
+ // This code handle row(s) that have rowspanning cell(s) and at least one empty cell.
+ // Such rows are not handled below and end up having a height of 0. That would mean
+ // content overlapping if one of their cells has any content. To avoid the problem, we
+ // add all the remaining spanning cells' height to the last spanned row.
+ // This means that we could grow a row past its 'height' or break percentage spreading
+ // however this is better than overlapping content.
+ // FIXME: Is there a better algorithm?
+ if (!spanningRowsHeight.totalRowsHeight) {
+ if (spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing)
+ m_rowPos[spanningCellEndIndex] += spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing + borderSpacingForRow(spanningCellEndIndex - 1);
+
+ extraHeightToPropagate = m_rowPos[spanningCellEndIndex] - originalBeforePosition;
+ continue;
+ }
+
+ if (spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing <= spanningRowsHeight.totalRowsHeight) {
extraHeightToPropagate = m_rowPos[rowIndex + rowSpan] - originalBeforePosition;
continue;
}
+ // Below we are handling only row(s) who have at least one visible cell without rowspan value.
int totalPercent = 0;
int totalAutoRowsHeight = 0;
int totalRemainingRowsHeight = spanningRowsHeight.totalRowsHeight;
@@ -612,15 +635,15 @@ void RenderTableSection::updateBaselineForCell(RenderTableCell* cell, unsigned r
int RenderTableSection::calcRowLogicalHeight()
{
#ifndef NDEBUG
- SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
+ SetLayoutNeededForbiddenScope layoutForbiddenScope(*this);
#endif
ASSERT(!needsLayout());
RenderTableCell* cell;
- RenderView* viewRenderer = view();
- LayoutStateMaintainer statePusher(viewRenderer);
+ // FIXME: This shouldn't use the same constructor as RenderView.
+ LayoutState state(*this);
m_rowPos.resize(m_grid.size() + 1);
@@ -640,7 +663,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] + minimumValueForLength(m_grid[r].logicalHeight, 0, viewRenderer).round(), 0);
+ m_rowPos[r + 1] = max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0).round(), 0);
Row& row = m_grid[r].row;
unsigned totalCols = row.size();
@@ -653,58 +676,35 @@ int RenderTableSection::calcRowLogicalHeight()
if (current.inColSpan && cell->rowSpan() == 1)
continue;
- if (RuntimeEnabledFeatures::rowSpanLogicalHeightSpreadingEnabled()) {
- if (cell->rowSpan() > 1) {
- // For row spanning cells, we only handle them for the first row they span. This ensures we take their baseline into account.
- if (lastRowSpanCell != cell && cell->rowIndex() == r) {
+ if (cell->rowSpan() > 1) {
+ // For row spanning cells, we only handle them for the first row they span. This ensures we take their baseline into account.
+ if (lastRowSpanCell != cell && cell->rowIndex() == r) {
#ifndef NDEBUG
- ASSERT(!uniqueCells.contains(cell));
- uniqueCells.add(cell);
+ ASSERT(!uniqueCells.contains(cell));
+ uniqueCells.add(cell);
#endif
- rowSpanCells.append(cell);
- lastRowSpanCell = cell;
+ rowSpanCells.append(cell);
+ lastRowSpanCell = cell;
- // Find out the baseline. The baseline is set on the first row in a rowSpan.
- updateBaselineForCell(cell, r, baselineDescent);
- }
- continue;
+ // Find out the baseline. The baseline is set on the first row in a rowSpan.
+ updateBaselineForCell(cell, r, baselineDescent);
}
-
- ASSERT(cell->rowSpan() == 1);
- } else {
- // FIXME: We add all the logical row of a rowspan to the last rows
- // until crbug.com/78724 is fixed and the runtime flag removed.
- // This avoids propagating temporary regressions while we fix the bug.
- if ((cell->rowIndex() + cell->rowSpan() - 1) != r)
- continue;
+ continue;
}
+ ASSERT(cell->rowSpan() == 1);
+
if (cell->hasOverrideHeight()) {
- if (!statePusher.didPush()) {
- // Technically, we should also push state for the row, but since
- // rows don't push a coordinate transform, that's not necessary.
- statePusher.push(this, locationOffset());
- }
cell->clearIntrinsicPadding();
cell->clearOverrideSize();
cell->forceChildLayout();
}
- if (RuntimeEnabledFeatures::rowSpanLogicalHeightSpreadingEnabled()) {
- m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r] + cell->logicalHeightForRowSizing());
-
- // Find out the baseline.
- updateBaselineForCell(cell, r, baselineDescent);
- } else {
- // For row spanning cells, |r| is the last row in the span.
- unsigned cellStartRow = cell->rowIndex();
+ m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r] + cell->logicalHeightForRowSizing());
- m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[cellStartRow] + cell->logicalHeightForRowSizing());
-
- // Find out the baseline.
- updateBaselineForCell(cell, cellStartRow, baselineDescent);
- }
+ // Find out the baseline.
+ updateBaselineForCell(cell, r, baselineDescent);
}
}
@@ -713,15 +713,11 @@ int RenderTableSection::calcRowLogicalHeight()
m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
}
- if (!rowSpanCells.isEmpty()) {
- ASSERT(RuntimeEnabledFeatures::rowSpanLogicalHeightSpreadingEnabled());
+ if (!rowSpanCells.isEmpty())
distributeRowSpanHeightToRows(rowSpanCells);
- }
ASSERT(!needsLayout());
- statePusher.pop();
-
return m_rowPos[m_grid.size()];
}
@@ -731,17 +727,15 @@ void RenderTableSection::layout()
ASSERT(!needsCellRecalc());
ASSERT(!table()->needsSectionRecalc());
- LayoutRectRecorder recorder(*this);
-
// addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
// can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
m_grid.shrinkToFit();
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+ LayoutState state(*this, locationOffset());
const Vector<int>& columnPos = table()->columnPositions();
- SubtreeLayoutScope layouter(this);
+ SubtreeLayoutScope layouter(*this);
for (unsigned r = 0; r < m_grid.size(); ++r) {
Row& row = m_grid[r].row;
unsigned cols = row.size();
@@ -764,11 +758,13 @@ void RenderTableSection::layout()
cell->setCellLogicalWidth(tableLayoutLogicalWidth, layouter);
}
- if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer)
+ if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
+ if (!rowRenderer->needsLayout())
+ rowRenderer->markForPaginationRelayoutIfNeeded(layouter);
rowRenderer->layoutIfNeeded();
+ }
}
- statePusher.pop();
clearNeedsLayout();
}
@@ -874,11 +870,13 @@ static bool shouldFlexCellChild(RenderObject* cellDescendant)
void RenderTableSection::layoutRows()
{
#ifndef NDEBUG
- SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
+ SetLayoutNeededForbiddenScope layoutForbiddenScope(*this);
#endif
ASSERT(!needsLayout());
+ // FIXME: Changing the height without a layout can change the overflow so it seems wrong.
+
unsigned totalRows = m_grid.size();
// Set the width of our section now. The rows will also be this width.
@@ -890,7 +888,7 @@ void RenderTableSection::layoutRows()
int vspacing = table()->vBorderSpacing();
unsigned nEffCols = table()->numEffCols();
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+ LayoutState state(*this, locationOffset());
for (unsigned r = 0; r < totalRows; r++) {
// Set the row's x/y position and width/height.
@@ -898,7 +896,9 @@ void RenderTableSection::layoutRows()
rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
rowRenderer->setLogicalWidth(logicalWidth());
rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
- rowRenderer->updateLayerTransform();
+ rowRenderer->updateLayerTransformAfterLayout();
+ rowRenderer->clearAllOverflows();
+ rowRenderer->addVisualEffectOverflow();
}
int rowHeightIncreaseForPagination = 0;
@@ -966,15 +966,15 @@ void RenderTableSection::layoutRows()
}
}
- SubtreeLayoutScope layouter(cell);
+ SubtreeLayoutScope layouter(*cell);
cell->computeIntrinsicPadding(rHeight, layouter);
LayoutRect oldCellRect = cell->frameRect();
setLogicalPositionForCell(cell, c);
- if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
- layouter.setChildNeedsLayout(cell);
+ if (!cell->needsLayout())
+ cell->markForPaginationRelayoutIfNeeded(layouter);
cell->layoutIfNeeded();
@@ -983,20 +983,27 @@ void RenderTableSection::layoutRows()
// 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)
- rowHeightIncreaseForPagination = max<int>(rowHeightIncreaseForPagination, cell->logicalHeight() - rHeight);
+ LayoutUnit oldLogicalHeight = cell->logicalHeight();
+ if (oldLogicalHeight > rHeight)
+ rowHeightIncreaseForPagination = max<int>(rowHeightIncreaseForPagination, oldLogicalHeight - rHeight);
cell->setLogicalHeight(rHeight);
+ cell->computeOverflow(oldLogicalHeight, false);
}
LayoutSize childOffset(cell->location() - oldCellRect.location());
if (childOffset.width() || childOffset.height()) {
- view()->addLayoutDelta(childOffset);
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(childOffset);
// If the child moved, we have to repaint it as well as any floating/positioned
- // descendants. An exception is if we need a layout. In this case, we know we're going to
+ // descendants. An exception is if we need a layout. In this case, we know we're going to
// repaint ourselves (and the child) anyway.
- if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
- cell->repaintDuringLayoutIfMoved(oldCellRect);
+ if (!table()->selfNeedsLayout() && cell->checkForPaintInvalidation()) {
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ cell->setMayNeedPaintInvalidation(true);
+ else
+ cell->repaintDuringLayoutIfMoved(oldCellRect);
+ }
}
}
if (rowHeightIncreaseForPagination) {
@@ -1004,8 +1011,11 @@ void RenderTableSection::layoutRows()
m_rowPos[rowIndex] += rowHeightIncreaseForPagination;
for (unsigned c = 0; c < nEffCols; ++c) {
Vector<RenderTableCell*, 1>& cells = cellAt(r, c).cells;
- for (size_t i = 0; i < cells.size(); ++i)
- cells[i]->setLogicalHeight(cells[i]->logicalHeight() + rowHeightIncreaseForPagination);
+ for (size_t i = 0; i < cells.size(); ++i) {
+ LayoutUnit oldLogicalHeight = cells[i]->logicalHeight();
+ cells[i]->setLogicalHeight(oldLogicalHeight + rowHeightIncreaseForPagination);
+ cells[i]->computeOverflow(oldLogicalHeight, false);
+ }
}
}
}
@@ -1015,8 +1025,6 @@ void RenderTableSection::layoutRows()
setLogicalHeight(m_rowPos[totalRows]);
computeOverflowFromCells(totalRows, nEffCols);
-
- statePusher.pop();
}
void RenderTableSection::computeOverflowFromCells()
@@ -1062,7 +1070,7 @@ void RenderTableSection::computeOverflowFromCells(unsigned totalRows, unsigned n
ASSERT(hasOverflowingCell == this->hasOverflowingCell());
}
-int RenderTableSection::calcOuterBorderBefore() const
+int RenderTableSection::calcBlockDirectionOuterBorder(BlockBorderSide side) const
{
unsigned totalCols = table()->numEffCols();
if (!m_grid.size() || !totalCols)
@@ -1070,13 +1078,13 @@ int RenderTableSection::calcOuterBorderBefore() const
unsigned borderWidth = 0;
- const BorderValue& sb = style()->borderBefore();
+ const BorderValue& sb = side == BorderBefore ? style()->borderBefore() : style()->borderAfter();
if (sb.style() == BHIDDEN)
return -1;
if (sb.style() > BHIDDEN)
borderWidth = sb.width();
- const BorderValue& rb = firstChild()->style()->borderBefore();
+ const BorderValue& rb = side == BorderBefore ? firstRow()->style()->borderBefore() : lastRow()->style()->borderAfter();
if (rb.style() == BHIDDEN)
return -1;
if (rb.style() > BHIDDEN && rb.width() > borderWidth)
@@ -1084,14 +1092,15 @@ int RenderTableSection::calcOuterBorderBefore() const
bool allHidden = true;
for (unsigned c = 0; c < totalCols; c++) {
- const CellStruct& current = cellAt(0, c);
+ const CellStruct& current = cellAt(side == BorderBefore ? 0 : m_grid.size() - 1, c);
if (current.inColSpan || !current.hasCells())
continue;
- const BorderValue& cb = current.primaryCell()->style()->borderBefore(); // FIXME: Make this work with perpendicular and flipped cells.
+ const RenderStyle* primaryCellStyle = current.primaryCell()->style();
+ const BorderValue& cb = side == BorderBefore ? primaryCellStyle->borderBefore() : primaryCellStyle->borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
// FIXME: Don't repeat for the same col group
RenderTableCol* colGroup = table()->colElement(c);
if (colGroup) {
- const BorderValue& gb = colGroup->style()->borderBefore();
+ const BorderValue& gb = side == BorderBefore ? colGroup->style()->borderBefore() : colGroup->style()->borderAfter();
if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
continue;
allHidden = false;
@@ -1110,76 +1119,28 @@ int RenderTableSection::calcOuterBorderBefore() const
if (allHidden)
return -1;
+ if (side == BorderAfter)
+ borderWidth++; // Distribute rounding error
return borderWidth / 2;
}
-int RenderTableSection::calcOuterBorderAfter() const
+int RenderTableSection::calcInlineDirectionOuterBorder(InlineBorderSide side) const
{
unsigned totalCols = table()->numEffCols();
if (!m_grid.size() || !totalCols)
return 0;
+ unsigned colIndex = side == BorderStart ? 0 : totalCols - 1;
unsigned borderWidth = 0;
- const BorderValue& sb = style()->borderAfter();
+ const BorderValue& sb = side == BorderStart ? style()->borderStart() : style()->borderEnd();
if (sb.style() == BHIDDEN)
return -1;
if (sb.style() > BHIDDEN)
borderWidth = sb.width();
- const BorderValue& rb = lastChild()->style()->borderAfter();
- if (rb.style() == BHIDDEN)
- return -1;
- if (rb.style() > BHIDDEN && rb.width() > borderWidth)
- borderWidth = rb.width();
-
- bool allHidden = true;
- for (unsigned c = 0; c < totalCols; c++) {
- const CellStruct& current = cellAt(m_grid.size() - 1, c);
- if (current.inColSpan || !current.hasCells())
- continue;
- const BorderValue& cb = current.primaryCell()->style()->borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
- // FIXME: Don't repeat for the same col group
- RenderTableCol* colGroup = table()->colElement(c);
- if (colGroup) {
- const BorderValue& gb = colGroup->style()->borderAfter();
- if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
- continue;
- allHidden = false;
- if (gb.style() > BHIDDEN && gb.width() > borderWidth)
- borderWidth = gb.width();
- if (cb.style() > BHIDDEN && cb.width() > borderWidth)
- borderWidth = cb.width();
- } else {
- if (cb.style() == BHIDDEN)
- continue;
- allHidden = false;
- if (cb.style() > BHIDDEN && cb.width() > borderWidth)
- borderWidth = cb.width();
- }
- }
- if (allHidden)
- return -1;
-
- return (borderWidth + 1) / 2;
-}
-
-int RenderTableSection::calcOuterBorderStart() const
-{
- unsigned totalCols = table()->numEffCols();
- if (!m_grid.size() || !totalCols)
- return 0;
-
- unsigned borderWidth = 0;
-
- const BorderValue& sb = style()->borderStart();
- if (sb.style() == BHIDDEN)
- return -1;
- if (sb.style() > BHIDDEN)
- borderWidth = sb.width();
-
- if (RenderTableCol* colGroup = table()->colElement(0)) {
- const BorderValue& gb = colGroup->style()->borderStart();
+ if (RenderTableCol* colGroup = table()->colElement(colIndex)) {
+ const BorderValue& gb = side == BorderStart ? colGroup->style()->borderStart() : colGroup->style()->borderEnd();
if (gb.style() == BHIDDEN)
return -1;
if (gb.style() > BHIDDEN && gb.width() > borderWidth)
@@ -1188,12 +1149,14 @@ int RenderTableSection::calcOuterBorderStart() const
bool allHidden = true;
for (unsigned r = 0; r < m_grid.size(); r++) {
- const CellStruct& current = cellAt(r, 0);
+ const CellStruct& current = cellAt(r, colIndex);
if (!current.hasCells())
continue;
// FIXME: Don't repeat for the same cell
- const BorderValue& cb = current.primaryCell()->style()->borderStart(); // FIXME: Make this work with perpendicular and flipped cells.
- const BorderValue& rb = current.primaryCell()->parent()->style()->borderStart();
+ const RenderStyle* primaryCellStyle = current.primaryCell()->style();
+ const RenderStyle* primaryCellParentStyle = current.primaryCell()->parent()->style();
+ const BorderValue& cb = side == BorderStart ? primaryCellStyle->borderStart() : primaryCellStyle->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
+ const BorderValue& rb = side == BorderStart ? primaryCellParentStyle->borderStart() : primaryCellParentStyle->borderEnd();
if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
continue;
allHidden = false;
@@ -1205,59 +1168,17 @@ int RenderTableSection::calcOuterBorderStart() const
if (allHidden)
return -1;
- return (borderWidth + (table()->style()->isLeftToRightDirection() ? 0 : 1)) / 2;
-}
-
-int RenderTableSection::calcOuterBorderEnd() const
-{
- unsigned totalCols = table()->numEffCols();
- if (!m_grid.size() || !totalCols)
- return 0;
-
- unsigned borderWidth = 0;
-
- const BorderValue& sb = style()->borderEnd();
- if (sb.style() == BHIDDEN)
- return -1;
- if (sb.style() > BHIDDEN)
- borderWidth = sb.width();
-
- if (RenderTableCol* colGroup = table()->colElement(totalCols - 1)) {
- const BorderValue& gb = colGroup->style()->borderEnd();
- if (gb.style() == BHIDDEN)
- return -1;
- if (gb.style() > BHIDDEN && gb.width() > borderWidth)
- borderWidth = gb.width();
- }
-
- bool allHidden = true;
- for (unsigned r = 0; r < m_grid.size(); r++) {
- const CellStruct& current = cellAt(r, totalCols - 1);
- if (!current.hasCells())
- continue;
- // FIXME: Don't repeat for the same cell
- const BorderValue& cb = current.primaryCell()->style()->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
- const BorderValue& rb = current.primaryCell()->parent()->style()->borderEnd();
- if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
- continue;
- allHidden = false;
- if (cb.style() > BHIDDEN && cb.width() > borderWidth)
- borderWidth = cb.width();
- if (rb.style() > BHIDDEN && rb.width() > borderWidth)
- borderWidth = rb.width();
- }
- if (allHidden)
- return -1;
-
- return (borderWidth + (table()->style()->isLeftToRightDirection() ? 1 : 0)) / 2;
+ if ((side == BorderStart) != table()->style()->isLeftToRightDirection())
+ borderWidth++; // Distribute rounding error
+ return borderWidth / 2;
}
void RenderTableSection::recalcOuterBorder()
{
- m_outerBorderBefore = calcOuterBorderBefore();
- m_outerBorderAfter = calcOuterBorderAfter();
- m_outerBorderStart = calcOuterBorderStart();
- m_outerBorderEnd = calcOuterBorderEnd();
+ m_outerBorderBefore = calcBlockDirectionOuterBorder(BorderBefore);
+ m_outerBorderAfter = calcBlockDirectionOuterBorder(BorderAfter);
+ m_outerBorderStart = calcInlineDirectionOuterBorder(BorderStart);
+ m_outerBorderEnd = calcInlineDirectionOuterBorder(BorderEnd);
}
int RenderTableSection::firstLineBoxBaseline() const
@@ -1286,7 +1207,7 @@ void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOff
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
- ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
+ ASSERT(!needsLayout());
// avoid crashing on bugs that cause us to paint with dirty layout
if (needsLayout())
return;
@@ -1463,11 +1384,8 @@ CellSpan RenderTableSection::spannedColumns(const LayoutRect& flippedRect) const
void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- PaintPhase paintPhase = paintInfo.phase;
-
LayoutRect localRepaintRect = paintInfo.rect;
localRepaintRect.moveBy(-paintOffset);
- localRepaintRect.inflate(maximalOutlineSize(paintPhase));
LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRepaintRect);
@@ -1564,7 +1482,7 @@ void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& pa
void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
{
// FIXME: Examine cells and repaint only the rect the image paints in.
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderTableSection::recalcCells()
@@ -1579,30 +1497,22 @@ void RenderTableSection::recalcCells()
m_cRow = 0;
m_grid.clear();
- for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
- if (row->isTableRow()) {
- unsigned insertionRow = m_cRow;
- m_cRow++;
- m_cCol = 0;
- ensureRows(m_cRow);
-
- RenderTableRow* tableRow = toRenderTableRow(row);
- m_grid[insertionRow].rowRenderer = tableRow;
- tableRow->setRowIndex(insertionRow);
- setRowLogicalHeightToRowStyleLogicalHeight(m_grid[insertionRow]);
+ for (RenderTableRow* row = firstRow(); row; row = row->nextRow()) {
+ unsigned insertionRow = m_cRow;
+ ++m_cRow;
+ m_cCol = 0;
+ ensureRows(m_cRow);
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (!cell->isTableCell())
- continue;
+ m_grid[insertionRow].rowRenderer = row;
+ row->setRowIndex(insertionRow);
+ setRowLogicalHeightToRowStyleLogicalHeight(m_grid[insertionRow]);
- RenderTableCell* tableCell = toRenderTableCell(cell);
- addCell(tableCell, tableRow);
- }
- }
+ for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
+ addCell(cell, row);
}
m_grid.shrinkToFit();
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
}
// FIXME: This function could be made O(1) in certain cases (like for the non-most-constrainive cells' case).
@@ -1613,12 +1523,8 @@ void RenderTableSection::rowLogicalHeightChanged(unsigned rowIndex)
setRowLogicalHeightToRowStyleLogicalHeight(m_grid[rowIndex]);
- for (RenderObject* cell = m_grid[rowIndex].rowRenderer->firstChild(); cell; cell = cell->nextSibling()) {
- if (!cell->isTableCell())
- continue;
-
- updateLogicalHeightForCell(m_grid[rowIndex], toRenderTableCell(cell));
- }
+ for (RenderTableCell* cell = m_grid[rowIndex].rowRenderer->firstCell(); cell; cell = cell->nextCell())
+ updateLogicalHeightForCell(m_grid[rowIndex], cell);
}
void RenderTableSection::setNeedsCellRecalc()
@@ -1685,7 +1591,7 @@ void RenderTableSection::splitColumn(unsigned pos, unsigned first)
Row& r = m_grid[row].row;
r.insert(pos + 1, CellStruct());
if (r[pos].hasCells()) {
- r[pos + 1].cells.append(r[pos].cells);
+ r[pos + 1].cells.appendVector(r[pos].cells);
RenderTableCell* cell = r[pos].primaryCell();
ASSERT(cell);
ASSERT(cell->colSpan() >= (r[pos].inColSpan ? 1u : 0));
@@ -1704,25 +1610,25 @@ void RenderTableSection::splitColumn(unsigned pos, unsigned first)
bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
// If we have no children then we have nothing to do.
- if (!firstChild())
+ if (!firstRow())
return false;
// Table sections cannot ever be hit tested. Effectively they do not exist.
// Just forward to our children always.
LayoutPoint adjustedLocation = accumulatedOffset + location();
- if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region())))
+ if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation)))
return false;
if (hasOverflowingCell()) {
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+ for (RenderTableRow* row = lastRow(); row; row = row->previousRow()) {
// FIXME: We have to skip over inline flows, since they can show up inside table rows
// at the moment (a demoted inline <form> for example). If we ever implement a
// table-specific hit-test method (which we should do for performance reasons anyway),
// then we can remove this check.
- if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer()) {
- LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
- if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
+ if (!row->hasSelfPaintingLayer()) {
+ LayoutPoint childPoint = flipForWritingModeForChild(row, adjustedLocation);
+ if (row->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
return true;
}
@@ -1814,7 +1720,9 @@ void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsign
cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing);
cell->setLogicalLocation(cellLocation);
- view()->addLayoutDelta(oldCellLocation - cell->location());
+
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
+ view()->addLayoutDelta(oldCellLocation - cell->location());
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.h
index 42b51ec6b3e..27410d5b14e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTableSection.h
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2013 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -65,13 +65,13 @@ public:
RenderTableSection(Element*);
virtual ~RenderTableSection();
- RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
- RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ RenderTableRow* firstRow() const;
+ RenderTableRow* lastRow() const;
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
virtual int firstLineBoxBaseline() const OVERRIDE;
@@ -129,14 +129,14 @@ public:
SpanningRowsHeight()
: totalRowsHeight(0)
, spanningCellHeightIgnoringBorderSpacing(0)
- , rowWithOnlySpanningCells(false)
+ , isAnyRowWithOnlySpanningCells(false)
{
}
Vector<int> rowHeight;
int totalRowsHeight;
int spanningCellHeightIgnoringBorderSpacing;
- bool rowWithOnlySpanningCells;
+ bool isAnyRowWithOnlySpanningCells;
};
const BorderValue& borderAdjoiningTableStart() const
@@ -174,10 +174,10 @@ public:
void appendColumn(unsigned pos);
void splitColumn(unsigned pos, unsigned first);
- int calcOuterBorderBefore() const;
- int calcOuterBorderAfter() const;
- int calcOuterBorderStart() const;
- int calcOuterBorderEnd() const;
+ enum BlockBorderSide { BorderBefore, BorderAfter };
+ int calcBlockDirectionOuterBorder(BlockBorderSide) const;
+ enum InlineBorderSide { BorderStart, BorderEnd };
+ int calcInlineDirectionOuterBorder(InlineBorderSide) const;
void recalcOuterBorder();
int outerBorderBefore() const { return m_outerBorderBefore; }
@@ -218,26 +218,25 @@ public:
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
private:
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ virtual RenderObjectChildList* virtualChildren() OVERRIDE { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const OVERRIDE { return children(); }
- virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
+ virtual const char* renderName() const OVERRIDE { return (isAnonymous() || isPseudoElement()) ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
- virtual bool isTableSection() const { return true; }
+ virtual bool isTableSection() const OVERRIDE { return true; }
virtual void willBeRemovedFromTree() OVERRIDE;
- virtual void layout();
-
- virtual void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&);
- virtual void paintObject(PaintInfo&, const LayoutPoint&);
+ virtual void layout() OVERRIDE;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&);
+ virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
int borderSpacingForRow(unsigned row) const { return m_grid[row].rowRenderer ? table()->vBorderSpacing() : 0; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderText.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderText.cpp
index b89ddc756ba..64fa967bd38 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderText.cpp
@@ -28,9 +28,9 @@
#include "core/accessibility/AXObjectCache.h"
#include "core/dom/Text.h"
#include "core/editing/TextIterator.h"
-#include "core/fetch/TextResourceDecoder.h"
#include "core/frame/FrameView.h"
#include "core/frame/Settings.h"
+#include "core/html/parser/TextResourceDecoder.h"
#include "core/rendering/AbstractInlineTextBox.h"
#include "core/rendering/EllipsisBox.h"
#include "core/rendering/InlineTextBox.h"
@@ -39,8 +39,12 @@
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/break_lines.h"
+#include "platform/fonts/Character.h"
+#include "platform/fonts/FontCache.h"
#include "platform/geometry/FloatQuad.h"
+#include "platform/text/BidiResolver.h"
#include "platform/text/TextBreakIterator.h"
+#include "platform/text/TextRunIterator.h"
#include "wtf/text/StringBuffer.h"
#include "wtf/text/StringBuilder.h"
#include "wtf/unicode/CharacterNames.h"
@@ -64,7 +68,7 @@ class SecureTextTimer;
typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
static SecureTextTimerMap* gSecureTextTimers = 0;
-class SecureTextTimer : public TimerBase {
+class SecureTextTimer FINAL : public TimerBase {
public:
SecureTextTimer(RenderText* renderText)
: m_renderText(renderText)
@@ -76,13 +80,13 @@ public:
{
m_lastTypedCharacterOffset = lastTypedCharacterOffset;
if (Settings* settings = m_renderText->document().settings())
- startOneShot(settings->passwordEchoDurationInSeconds());
+ startOneShot(settings->passwordEchoDurationInSeconds(), FROM_HERE);
}
void invalidate() { m_lastTypedCharacterOffset = -1; }
unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; }
private:
- virtual void fired()
+ virtual void fired() OVERRIDE
{
ASSERT(gSecureTextTimers->contains(m_renderText));
m_renderText->setText(m_renderText->text().impl(), true /* forcing setting text as it may be masked later */);
@@ -190,8 +194,8 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
// we already did this for the parent of the text run.
// We do have to schedule layouts, though, since a style change can force us to
// need to relayout.
- if (diff == StyleDifferenceLayout) {
- setNeedsLayoutAndPrefWidthsRecalc();
+ if (diff.needsFullLayout()) {
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
m_knownToHaveNoOverflowAndNoFallbackFonts = false;
}
@@ -201,8 +205,11 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
if (oldTransform != newStyle->textTransform() || oldSecurity != newStyle->textSecurity())
transformText();
+ // This is an optimization that kicks off font load before layout.
+ // In order to make it fast, we only check if the first character of the
+ // text is included in the unicode ranges of the fonts.
if (!text().containsOnlyWhitespace())
- newStyle->font().willUseFontData();
+ newStyle->font().willUseFontData(text().characterStartingAt(0));
}
void RenderText::removeAndDestroyTextBoxes()
@@ -210,7 +217,7 @@ void RenderText::removeAndDestroyTextBoxes()
if (!documentBeingDestroyed()) {
if (firstTextBox()) {
if (isBR()) {
- RootInlineBox* next = firstTextBox()->root()->nextRootBox();
+ RootInlineBox* next = firstTextBox()->root().nextRootBox();
if (next)
next->markDirty();
}
@@ -362,11 +369,11 @@ void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, u
if (useSelectionHeight) {
LayoutRect selectionRect = box->localSelectionRect(start, end);
if (box->isHorizontal()) {
- r.setHeight(selectionRect.height());
- r.setY(selectionRect.y());
+ r.setHeight(selectionRect.height().toFloat());
+ r.setY(selectionRect.y().toFloat());
} else {
- r.setWidth(selectionRect.width());
- r.setX(selectionRect.x());
+ r.setWidth(selectionRect.width().toFloat());
+ r.setX(selectionRect.x().toFloat());
}
}
rects.append(localToAbsoluteQuad(r, 0, wasFixed).enclosingBoundingBox());
@@ -389,7 +396,7 @@ static IntRect ellipsisRectForBox(InlineTextBox* box, unsigned startPos, unsigne
return IntRect();
IntRect rect;
- if (EllipsisBox* ellipsis = box->root()->ellipsisBox()) {
+ if (EllipsisBox* ellipsis = box->root().ellipsisBox()) {
int ellipsisStartPosition = max<int>(startPos - box->start(), 0);
int ellipsisEndPosition = min<int>(endPos - box->start(), box->len());
@@ -445,11 +452,11 @@ void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start,
if (useSelectionHeight) {
LayoutRect selectionRect = box->localSelectionRect(start, end);
if (box->isHorizontal()) {
- r.setHeight(selectionRect.height());
- r.setY(selectionRect.y());
+ r.setHeight(selectionRect.height().toFloat());
+ r.setY(selectionRect.y().toFloat());
} else {
- r.setWidth(selectionRect.width());
- r.setX(selectionRect.x());
+ r.setWidth(selectionRect.width().toFloat());
+ r.setX(selectionRect.x().toFloat());
}
}
quads.append(localToAbsoluteQuad(r, 0, wasFixed));
@@ -461,27 +468,6 @@ void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start,
}
}
-InlineTextBox* RenderText::findNextInlineTextBox(int offset, int& pos) const
-{
- // The text runs point to parts of the RenderText's m_text
- // (they don't include '\n')
- // Find the text run that includes the character at offset
- // and return pos, which is the position of the char in the run.
-
- if (!m_firstTextBox)
- return 0;
-
- InlineTextBox* s = m_firstTextBox;
- int off = s->len();
- while (offset > off && s->nextTextBox()) {
- s = s->nextTextBox();
- off = s->start() + s->len();
- }
- // we are now in the correct text run
- pos = (offset > off ? s->len() : s->len() - (off - offset) );
- return s;
-}
-
enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPositionIsNotAtStart };
static bool lineDirectionPointFitsInBox(int pointLineDirection, InlineTextBox* box, ShouldAffinityBeDownstream& shouldAffinityBeDownstream)
@@ -533,14 +519,13 @@ static PositionWithAffinity createPositionWithAffinityForBox(const InlineBox* bo
affinity = offset > box->caretMinOffset() ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM;
break;
}
- int textStartOffset = box->renderer()->isText() ? toRenderText(box->renderer())->textStartOffset() : 0;
- return box->renderer()->createPositionWithAffinity(offset + textStartOffset, affinity);
+ int textStartOffset = box->renderer().isText() ? toRenderText(box->renderer()).textStartOffset() : 0;
+ return box->renderer().createPositionWithAffinity(offset + textStartOffset, affinity);
}
static PositionWithAffinity createPositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(const InlineTextBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)
{
ASSERT(box);
- ASSERT(box->renderer());
ASSERT(offset >= 0);
if (offset && static_cast<unsigned>(offset) < box->len())
@@ -552,7 +537,7 @@ static PositionWithAffinity createPositionWithAffinityForBoxAfterAdjustingOffset
const InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
if ((prevBox && prevBox->bidiLevel() == box->bidiLevel())
- || box->renderer()->containingBlock()->style()->direction() == box->direction()) // FIXME: left on 12CBA
+ || box->renderer().containingBlock()->style()->direction() == box->direction()) // FIXME: left on 12CBA
return createPositionWithAffinityForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);
if (prevBox && prevBox->bidiLevel() > box->bidiLevel()) {
@@ -582,7 +567,7 @@ static PositionWithAffinity createPositionWithAffinityForBoxAfterAdjustingOffset
const InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
if ((nextBox && nextBox->bidiLevel() == box->bidiLevel())
- || box->renderer()->containingBlock()->style()->direction() == box->direction())
+ || box->renderer().containingBlock()->style()->direction() == box->direction())
return createPositionWithAffinityForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
// offset is on the right edge
@@ -625,17 +610,17 @@ PositionWithAffinity RenderText::positionForPoint(const LayoutPoint& point)
if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak())
box = box->nextTextBox();
- RootInlineBox* rootBox = box->root();
- LayoutUnit top = min(rootBox->selectionTop(), rootBox->lineTop());
+ RootInlineBox& rootBox = box->root();
+ LayoutUnit top = min(rootBox.selectionTop(), rootBox.lineTop());
if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) {
- LayoutUnit bottom = rootBox->selectionBottom();
- if (rootBox->nextRootBox())
- bottom = min(bottom, rootBox->nextRootBox()->lineTop());
+ LayoutUnit bottom = rootBox.selectionBottom();
+ if (rootBox.nextRootBox())
+ bottom = min(bottom, rootBox.nextRootBox()->lineTop());
if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) {
ShouldAffinityBeDownstream shouldAffinityBeDownstream;
if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldAffinityBeDownstream))
- return createPositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream);
+ return createPositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(box, box->offsetForPosition(pointLineDirection.toFloat()), shouldAffinityBeDownstream);
}
}
lastBox = box;
@@ -644,7 +629,7 @@ PositionWithAffinity RenderText::positionForPoint(const LayoutPoint& point)
if (lastBox) {
ShouldAffinityBeDownstream shouldAffinityBeDownstream;
lineDirectionPointFitsInBox(pointLineDirection, lastBox, shouldAffinityBeDownstream);
- return createPositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream);
+ return createPositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(lastBox, lastBox->offsetForPosition(pointLineDirection.toFloat()) + lastBox->start(), shouldAffinityBeDownstream);
}
return createPositionWithAffinity(0, DOWNSTREAM);
}
@@ -660,8 +645,8 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay
InlineTextBox* box = toInlineTextBox(inlineBox);
- int height = box->root()->selectionHeight();
- int top = box->root()->selectionTop();
+ int height = box->root().selectionHeight();
+ int top = box->root().selectionTop();
// Go ahead and round left to snap it to the nearest pixel.
float left = box->positionForOffset(caretOffset);
@@ -673,13 +658,13 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay
left = roundf(left);
- float rootLeft = box->root()->logicalLeft();
- float rootRight = box->root()->logicalRight();
+ float rootLeft = box->root().logicalLeft();
+ float rootRight = box->root().logicalRight();
// FIXME: should we use the width of the root inline box or the
// width of the containing block for this?
if (extraWidthToEndOfLine)
- *extraWidthToEndOfLine = (box->root()->logicalWidth() + rootLeft) - (left + 1);
+ *extraWidthToEndOfLine = (box->root().logicalWidth() + rootLeft) - (left + 1);
RenderBlock* cb = containingBlock();
RenderStyle* cbStyle = cb->style();
@@ -687,7 +672,7 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay
float leftEdge;
float rightEdge;
leftEdge = min<float>(0, rootLeft);
- rightEdge = max<float>(cb->logicalWidth(), rootRight);
+ rightEdge = max<float>(cb->logicalWidth().toFloat(), rootRight);
bool rightAligned = false;
switch (cbStyle->textAlign()) {
@@ -720,7 +705,7 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay
return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, height) : IntRect(top, left, height, caretWidth);
}
-ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
if (style()->hasTextCombine() && isCombineText()) {
const RenderCombineText* combineText = toRenderCombineText(this);
@@ -728,7 +713,7 @@ ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
return combineText->combinedTextWidth(f);
}
- if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
+ if (f.isFixedPitch() && f.fontDescription().variant() == FontVariantNormal && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
float monospaceCharacterWidth = f.spaceWidth();
float w = 0;
bool isSpace;
@@ -755,18 +740,19 @@ ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
isSpace = false;
}
if (isSpace && i > start)
- w += f.wordSpacing();
+ w += f.fontDescription().wordSpacing();
}
return w;
}
- TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, start, len, style());
+ TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, start, len, style(), textDirection);
run.setCharactersLength(textLength() - start);
ASSERT(run.charactersLength() >= run.length());
run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
run.setXPos(xPos);
+ FontCachePurgePreventer fontCachePurgePreventer;
return f.width(run, fallbackFonts, glyphOverflow);
}
@@ -775,7 +761,8 @@ void RenderText::trimmedPrefWidths(float leadWidth,
float& lastLineMinWidth, bool& hasBreakableEnd,
bool& hasBreakableChar, bool& hasBreak,
float& firstLineMaxWidth, float& lastLineMaxWidth,
- float& minWidth, float& maxWidth, bool& stripFrontSpaces)
+ float& minWidth, float& maxWidth, bool& stripFrontSpaces,
+ TextDirection direction)
{
bool collapseWhiteSpace = style()->collapseWhiteSpace();
if (!collapseWhiteSpace)
@@ -815,10 +802,10 @@ void RenderText::trimmedPrefWidths(float leadWidth,
const Font& font = style()->font(); // FIXME: This ignores first-line.
if (stripFrontSpaces) {
const UChar space = ' ';
- float spaceWidth = font.width(RenderBlockFlow::constructTextRun(this, font, &space, 1, style()));
+ float spaceWidth = font.width(RenderBlockFlow::constructTextRun(this, font, &space, 1, style(), direction));
maxWidth -= spaceWidth;
} else {
- maxWidth += font.wordSpacing();
+ maxWidth += font.fontDescription().wordSpacing();
}
}
@@ -839,7 +826,7 @@ void RenderText::trimmedPrefWidths(float leadWidth,
linelen++;
if (linelen) {
- lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + lastLineMaxWidth, 0, 0);
+ lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + lastLineMaxWidth, direction, 0, 0);
if (firstLine) {
firstLine = false;
leadWidth = 0;
@@ -886,10 +873,10 @@ void RenderText::computePreferredLogicalWidths(float leadWidth)
m_knownToHaveNoOverflowAndNoFallbackFonts = true;
}
-static inline float hyphenWidth(RenderText* renderer, const Font& font)
+static inline float hyphenWidth(RenderText* renderer, const Font& font, TextDirection direction)
{
RenderStyle* style = renderer->style();
- return font.width(RenderBlockFlow::constructTextRun(renderer, font, style->hyphenString().string(), style));
+ return font.width(RenderBlockFlow::constructTextRun(renderer, font, style->hyphenString().string(), style, direction));
}
void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
@@ -925,23 +912,47 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
bool firstLine = true;
int nextBreakable = -1;
int lastWordBoundary = 0;
+ float cachedWordTrailingSpaceWidth[2] = { 0, 0 }; // LTR, RTL
- // Non-zero only when kerning is enabled, in which case we measure words with their trailing
- // space, then subtract its width.
- float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(RenderBlockFlow::constructTextRun(this, f, &space, 1, styleToUse)) + wordSpacing : 0;
-
- // If automatic hyphenation is allowed, we keep track of the width of the widest word (or word
- // fragment) encountered so far, and only try hyphenating words that are wider.
- float maxWordWidth = numeric_limits<float>::max();
int firstGlyphLeftOverflow = -1;
bool breakAll = (styleToUse->wordBreak() == BreakAllWordBreak || styleToUse->wordBreak() == BreakWordBreak) && styleToUse->autoWrap();
+ TextRun textRun(text());
+ BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
+
+ BidiCharacterRun* run;
+ TextDirection textDirection = styleToUse->direction();
+ if (isOverride(styleToUse->unicodeBidi())) {
+ run = 0;
+ } else {
+ BidiStatus status(LTR, false);
+ status.last = status.lastStrong = WTF::Unicode::OtherNeutral;
+ bidiResolver.setStatus(status);
+ bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0));
+ bool hardLineBreak = false;
+ bool reorderRuns = false;
+ bidiResolver.createBidiRunsForLine(TextRunIterator(&textRun, textRun.length()), NoVisualOverride, hardLineBreak, reorderRuns);
+ BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
+ run = bidiRuns.firstRun();
+ }
+
for (int i = 0; i < len; i++) {
UChar c = uncheckedCharacterAt(i);
- bool previousCharacterIsSpace = isSpace;
+ if (run) {
+ // Treat adjacent runs with the same resolved directionality
+ // (TextDirection as opposed to WTF::Unicode::Direction) as belonging
+ // to the same run to avoid breaking unnecessarily.
+ while (i > run->stop() || (run->next() && run->next()->direction() == run->direction()))
+ run = run->next();
+ ASSERT(run);
+ ASSERT(i <= run->stop());
+ textDirection = run->direction();
+ }
+
+ bool previousCharacterIsSpace = isSpace;
bool isNewline = false;
if (c == '\n') {
if (styleToUse->preserveNewline()) {
@@ -979,7 +990,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
lastWordBoundary++;
continue;
} else if (c == softHyphen) {
- currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
+ currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow);
if (firstGlyphLeftOverflow < 0)
firstGlyphLeftOverflow = glyphOverflow.left;
lastWordBoundary = i + 1;
@@ -1002,20 +1013,32 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
}
}
+ // Terminate word boundary at bidi run boundary.
+ if (run)
+ j = min(j, run->stop() + 1);
int wordLen = j - i;
if (wordLen) {
bool isSpace = (j < len) && c == ' ';
+
+ // Non-zero only when kerning is enabled, in which case we measure words with their trailing
+ // space, then subtract its width.
+ float wordTrailingSpaceWidth = 0;
+ if (isSpace && (f.fontDescription().typesettingFeatures() & Kerning)) {
+ ASSERT(textDirection >=0 && textDirection <= 1);
+ if (!cachedWordTrailingSpaceWidth[textDirection])
+ cachedWordTrailingSpaceWidth[textDirection] = f.width(RenderBlockFlow::constructTextRun(this, f, &space, 1, styleToUse, textDirection)) + wordSpacing;
+ wordTrailingSpaceWidth = cachedWordTrailingSpaceWidth[textDirection];
+ }
+
float w;
if (wordTrailingSpaceWidth && isSpace)
- w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth;
+ w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth;
else {
- w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
+ w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow);
if (c == softHyphen)
- currMinWidth += hyphenWidth(this, f);
+ currMinWidth += hyphenWidth(this, f, textDirection);
}
- maxWordWidth = max(maxWordWidth, w);
-
if (firstGlyphLeftOverflow < 0)
firstGlyphLeftOverflow = glyphOverflow.left;
currMinWidth += w;
@@ -1023,7 +1046,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
if (lastWordBoundary == i)
currMaxWidth += w;
else
- currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
+ currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow);
lastWordBoundary = j;
}
@@ -1074,7 +1097,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
m_maxWidth = currMaxWidth;
currMaxWidth = 0;
} else {
- TextRun run = RenderBlockFlow::constructTextRun(this, f, this, i, 1, styleToUse);
+ TextRun run = RenderBlockFlow::constructTextRun(this, f, this, i, 1, styleToUse, textDirection);
run.setCharactersLength(len - i);
ASSERT(run.charactersLength() >= run.length());
run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
@@ -1088,6 +1111,8 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
lastWordBoundary++;
}
}
+ if (run)
+ bidiResolver.runs().deleteRuns();
if (firstGlyphLeftOverflow > 0)
glyphOverflow.left = firstGlyphLeftOverflow;
@@ -1172,16 +1197,12 @@ void RenderText::setSelectionState(SelectionState state)
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
if (box->isSelected(startPos, endPos)) {
- RootInlineBox* root = box->root();
- if (root)
- root->setHasSelectedChildren(true);
+ box->root().setHasSelectedChildren(true);
}
}
} else {
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
- RootInlineBox* root = box->root();
- if (root)
- root->setHasSelectedChildren(state == SelectionInside);
+ box->root().setHasSelectedChildren(state == SelectionInside);
}
}
}
@@ -1217,7 +1238,7 @@ void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset,
// Text run is entirely after the affected range.
if (curr->start() > end) {
curr->offsetRun(delta);
- RootInlineBox* root = curr->root();
+ RootInlineBox* root = &curr->root();
if (!firstRootBox) {
firstRootBox = root;
// The affected area was in between two runs. Go ahead and mark the root box of
@@ -1251,7 +1272,7 @@ void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset,
firstRootBox = prev;
} else if (lastTextBox()) {
ASSERT(!lastRootBox);
- firstRootBox = lastTextBox()->root();
+ firstRootBox = &lastTextBox()->root();
firstRootBox->markDirty();
dirtiedLines = true;
}
@@ -1385,7 +1406,11 @@ void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
return;
setTextInternal(text);
- setNeedsLayoutAndPrefWidthsRecalc();
+ // If preferredLogicalWidthsDirty() of an orphan child is true, RenderObjectChildList::
+ // insertChildNode() fails to set true to owner. To avoid that, we call
+ // setNeedsLayoutAndPrefWidthsRecalc() only if this RenderText has parent.
+ if (parent())
+ setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
m_knownToHaveNoOverflowAndNoFallbackFonts = false;
if (AXObjectCache* cache = document().existingAXObjectCache())
@@ -1405,7 +1430,7 @@ void RenderText::dirtyLineBoxes(bool fullLayout)
InlineTextBox* RenderText::createTextBox()
{
- return new InlineTextBox(this);
+ return new InlineTextBox(*this);
}
InlineTextBox* RenderText::createInlineTextBox()
@@ -1429,7 +1454,7 @@ void RenderText::positionLineBox(InlineBox* box)
// FIXME: should not be needed!!!
if (!s->len()) {
// We want the box to be destroyed.
- s->remove();
+ s->remove(DontMarkLineBoxes);
if (m_firstTextBox == s)
m_firstTextBox = s->nextTextBox();
else
@@ -1445,7 +1470,7 @@ void RenderText::positionLineBox(InlineBox* box)
m_containsReversedText |= !s->isLeftToRightDirection();
}
-float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float RenderText::width(unsigned from, unsigned len, float xPos, TextDirection textDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
if (from >= textLength())
return 0;
@@ -1453,10 +1478,10 @@ float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine,
if (from + len > textLength())
len = textLength() - from;
- return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow);
+ return width(from, len, style(firstLine)->font(), xPos, textDirection, fallbackFonts, glyphOverflow);
}
-float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
ASSERT(from + len <= textLength());
if (!textLength())
@@ -1473,12 +1498,14 @@ float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos,
m_knownToHaveNoOverflowAndNoFallbackFonts = true;
}
w = m_maxWidth;
- } else
+ } else {
w = maxLogicalWidth();
- } else
- w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow);
+ }
+ } else {
+ w = widthFromCache(f, from, len, xPos, textDirection, fallbackFonts, glyphOverflow);
+ }
} else {
- TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, from, len, style());
+ TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, from, len, style(), textDirection);
run.setCharactersLength(textLength() - from);
ASSERT(run.charactersLength() >= run.length());
@@ -1542,7 +1569,7 @@ LayoutRect RenderText::linesVisualOverflowBoundingBox() const
return rect;
}
-LayoutRect RenderText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderText::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
RenderObject* rendererToRepaint = containingBlock();
@@ -1551,14 +1578,14 @@ LayoutRect RenderText::clippedOverflowRectForRepaint(const RenderLayerModelObjec
if (enclosingLayerRenderer != rendererToRepaint && !rendererToRepaint->isDescendantOf(enclosingLayerRenderer))
rendererToRepaint = enclosingLayerRenderer;
- // The renderer we chose to repaint may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
- if (repaintContainer && repaintContainer != rendererToRepaint && !rendererToRepaint->isDescendantOf(repaintContainer))
- return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
+ // The renderer we chose to repaint may be an ancestor of paintInvalidationContainer, but we need to do a paintInvalidationContainer-relative repaint.
+ if (paintInvalidationContainer && paintInvalidationContainer != rendererToRepaint && !rendererToRepaint->isDescendantOf(paintInvalidationContainer))
+ return paintInvalidationContainer->clippedOverflowRectForPaintInvalidation(paintInvalidationContainer);
- return rendererToRepaint->clippedOverflowRectForRepaint(repaintContainer);
+ return rendererToRepaint->clippedOverflowRectForPaintInvalidation(paintInvalidationContainer);
}
-LayoutRect RenderText::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
+LayoutRect RenderText::selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool clipToVisibleContent)
{
ASSERT(!needsLayout());
@@ -1593,12 +1620,12 @@ LayoutRect RenderText::selectionRectForRepaint(const RenderLayerModelObject* rep
}
if (clipToVisibleContent)
- computeRectForRepaint(repaintContainer, rect);
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect);
else {
if (cb->hasColumns())
cb->adjustRectForColumns(rect);
- rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
+ rect = localToContainerQuad(FloatRect(rect), paintInvalidationContainer).enclosingBoundingBox();
}
return rect;
@@ -1809,7 +1836,7 @@ bool RenderText::computeCanUseSimpleFontCodePath() const
{
if (isAllASCII() || m_text.is8Bit())
return true;
- return Font::characterRangeCodePath(characters16(), length()) == Font::Simple;
+ return Character::characterRangeCodePath(characters16(), length()) == SimplePath;
}
#ifndef NDEBUG
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderText.h b/chromium/third_party/WebKit/Source/core/rendering/RenderText.h
index 13af4be1c6b..1f3de61ca18 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderText.h
@@ -24,6 +24,8 @@
#define RenderText_h
#include "core/rendering/RenderObject.h"
+#include "platform/LengthFunctions.h"
+#include "platform/text/TextPath.h"
#include "wtf/Forward.h"
#include "wtf/PassRefPtr.h"
@@ -42,7 +44,7 @@ public:
virtual ~RenderText();
#endif
- virtual const char* renderName() const;
+ virtual const char* renderName() const OVERRIDE;
virtual bool isTextFragment() const;
virtual bool isWordBreak() const;
@@ -82,8 +84,8 @@ public:
unsigned textLength() const { return m_text.length(); } // non virtual implementation of length()
void positionLineBox(InlineBox*);
- virtual float width(unsigned from, unsigned len, const Font&, float xPos, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
- virtual float width(unsigned from, unsigned len, float xPos, bool firstLine = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+ virtual float width(unsigned from, unsigned len, const Font&, float xPos, TextDirection, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+ virtual float width(unsigned from, unsigned len, float xPos, TextDirection, bool firstLine = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
float minLogicalWidth() const;
float maxLogicalWidth() const;
@@ -93,7 +95,8 @@ public:
float& lastLineMinWidth, bool& hasBreakableEnd,
bool& hasBreakableChar, bool& hasBreak,
float& firstLineMaxWidth, float& lastLineMaxWidth,
- float& minWidth, float& maxWidth, bool& stripFrontSpaces);
+ float& minWidth, float& maxWidth, bool& stripFrontSpaces,
+ TextDirection);
virtual IntRect linesBoundingBox() const;
LayoutRect linesVisualOverflowBoundingBox() const;
@@ -107,21 +110,21 @@ public:
virtual void transformText();
- virtual bool canBeSelectionLeaf() const { return true; }
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return true; }
virtual void setSelectionState(SelectionState s) OVERRIDE FINAL;
- virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) OVERRIDE;
- virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
+ virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool clipToVisibleContent = true) OVERRIDE;
+ virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) OVERRIDE;
- LayoutUnit marginLeft() const { return minimumValueForLength(style()->marginLeft(), 0, view()); }
- LayoutUnit marginRight() const { return minimumValueForLength(style()->marginRight(), 0, view()); }
+ LayoutUnit marginLeft() const { return minimumValueForLength(style()->marginLeft(), 0); }
+ LayoutUnit marginRight() const { return minimumValueForLength(style()->marginRight(), 0); }
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE FINAL;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE FINAL;
InlineTextBox* firstTextBox() const { return m_firstTextBox; }
InlineTextBox* lastTextBox() const { return m_lastTextBox; }
- virtual int caretMinOffset() const;
- virtual int caretMaxOffset() const;
+ virtual int caretMinOffset() const OVERRIDE;
+ virtual int caretMaxOffset() const OVERRIDE;
unsigned renderedTextLength() const;
virtual int previousOffset(int current) const OVERRIDE FINAL;
@@ -133,8 +136,6 @@ public:
bool isSecure() const { return style()->textSecurity() != TSNONE; }
void momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset);
- InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
-
void checkConsistency() const;
bool isAllCollapsibleWhitespace() const;
@@ -148,10 +149,10 @@ public:
protected:
virtual void computePreferredLogicalWidths(float leadWidth);
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
- virtual void styleWillChange(StyleDifference, const RenderStyle*) OVERRIDE FINAL { }
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle&) OVERRIDE FINAL { }
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
virtual void setTextInternal(PassRefPtr<StringImpl>);
virtual UChar previousCharacter() const;
@@ -176,7 +177,7 @@ private:
void deleteTextBoxes();
bool containsOnlyWhitespace(unsigned from, unsigned len) const;
- float widthFromCache(const Font&, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const;
+ float widthFromCache(const Font&, int start, int len, float xPos, TextDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const;
bool isAllASCII() const { return m_isAllASCII; }
void secureText(UChar mask);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.cpp
index d420fbff074..81369e99415 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.cpp
@@ -47,9 +47,9 @@ HTMLTextFormControlElement* RenderTextControl::textFormControlElement() const
return toHTMLTextFormControlElement(node());
}
-HTMLElement* RenderTextControl::innerTextElement() const
+HTMLElement* RenderTextControl::innerEditorElement() const
{
- return textFormControlElement()->innerTextElement();
+ return textFormControlElement()->innerEditorElement();
}
void RenderTextControl::addChild(RenderObject* newChild, RenderObject* beforeChild)
@@ -57,26 +57,26 @@ void RenderTextControl::addChild(RenderObject* newChild, RenderObject* beforeChi
// FIXME: This is a terrible hack to get the caret over the placeholder text since it'll
// make us paint the placeholder first. (See https://trac.webkit.org/changeset/118733)
Node* node = newChild->node();
- if (node && node->isElementNode() && toElement(node)->pseudo() == "-webkit-input-placeholder")
- RenderBlock::addChild(newChild, firstChild());
+ if (node && node->isElementNode() && toElement(node)->shadowPseudoId() == "-webkit-input-placeholder")
+ RenderBlockFlow::addChild(newChild, firstChild());
else
- RenderBlock::addChild(newChild, beforeChild);
+ RenderBlockFlow::addChild(newChild, beforeChild);
}
void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- RenderBlock::styleDidChange(diff, oldStyle);
- Element* innerText = innerTextElement();
- if (!innerText)
+ RenderBlockFlow::styleDidChange(diff, oldStyle);
+ Element* innerEditor = innerEditorElement();
+ if (!innerEditor)
return;
- RenderBlock* innerTextRenderer = toRenderBlock(innerText->renderer());
- if (innerTextRenderer) {
+ RenderBlock* innerEditorRenderer = toRenderBlock(innerEditor->renderer());
+ if (innerEditorRenderer) {
// We may have set the width and the height in the old style in layout().
// Reset them now to avoid getting a spurious layout hint.
- innerTextRenderer->style()->setHeight(Length());
- innerTextRenderer->style()->setWidth(Length());
- innerTextRenderer->setStyle(createInnerTextStyle(style()));
- innerText->setNeedsStyleRecalc();
+ innerEditorRenderer->style()->setHeight(Length());
+ innerEditorRenderer->style()->setWidth(Length());
+ innerEditorRenderer->setStyle(createInnerEditorStyle(style()));
+ innerEditor->setNeedsStyleRecalc(SubtreeStyleChange);
}
textFormControlElement()->updatePlaceholderVisibility(false);
}
@@ -86,7 +86,7 @@ static inline void updateUserModifyProperty(HTMLTextFormControlElement* node, Re
style->setUserModify(node->isDisabledOrReadOnly() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
}
-void RenderTextControl::adjustInnerTextStyle(RenderStyle* textBlockStyle) const
+void RenderTextControl::adjustInnerEditorStyle(RenderStyle* textBlockStyle) const
{
// The inner block, if present, always has its direction set to LTR,
// so we need to inherit the direction and unicode-bidi style from the element.
@@ -103,21 +103,21 @@ int RenderTextControl::textBlockLogicalHeight() const
int RenderTextControl::textBlockLogicalWidth() const
{
- Element* innerText = innerTextElement();
- ASSERT(innerText);
+ Element* innerEditor = innerEditorElement();
+ ASSERT(innerEditor);
LayoutUnit unitWidth = logicalWidth() - borderAndPaddingLogicalWidth();
- if (innerText->renderer())
- unitWidth -= innerText->renderBox()->paddingStart() + innerText->renderBox()->paddingEnd();
+ if (innerEditor->renderer())
+ unitWidth -= innerEditor->renderBox()->paddingStart() + innerEditor->renderBox()->paddingEnd();
return unitWidth;
}
void RenderTextControl::updateFromElement()
{
- Element* innerText = innerTextElement();
- if (innerText && innerText->renderer())
- updateUserModifyProperty(textFormControlElement(), innerText->renderer()->style());
+ Element* innerEditor = innerEditorElement();
+ if (innerEditor && innerEditor->renderer())
+ updateUserModifyProperty(textFormControlElement(), innerEditor->renderer()->style());
}
int RenderTextControl::scrollbarThickness() const
@@ -128,33 +128,39 @@ int RenderTextControl::scrollbarThickness() const
void RenderTextControl::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
- HTMLElement* innerText = innerTextElement();
- ASSERT(innerText);
- if (RenderBox* innerTextBox = innerText->renderBox()) {
- LayoutUnit nonContentHeight = innerTextBox->borderAndPaddingHeight() + innerTextBox->marginHeight();
- logicalHeight = computeControlLogicalHeight(innerTextBox->lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes), nonContentHeight) + borderAndPaddingHeight();
+ HTMLElement* innerEditor = innerEditorElement();
+ ASSERT(innerEditor);
+ if (RenderBox* innerEditorBox = innerEditor->renderBox()) {
+ LayoutUnit nonContentHeight = innerEditorBox->borderAndPaddingHeight() + innerEditorBox->marginHeight();
+ logicalHeight = computeControlLogicalHeight(innerEditorBox->lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes), nonContentHeight);
// We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap.
- if ((isHorizontalWritingMode() && (style()->overflowX() == OSCROLL || (style()->overflowX() == OAUTO && innerText->renderer()->style()->overflowWrap() == NormalOverflowWrap)))
- || (!isHorizontalWritingMode() && (style()->overflowY() == OSCROLL || (style()->overflowY() == OAUTO && innerText->renderer()->style()->overflowWrap() == NormalOverflowWrap))))
+ if ((isHorizontalWritingMode() && (style()->overflowX() == OSCROLL || (style()->overflowX() == OAUTO && innerEditor->renderer()->style()->overflowWrap() == NormalOverflowWrap)))
+ || (!isHorizontalWritingMode() && (style()->overflowY() == OSCROLL || (style()->overflowY() == OAUTO && innerEditor->renderer()->style()->overflowWrap() == NormalOverflowWrap))))
logicalHeight += scrollbarThickness();
+
+ // FIXME: The logical height of the inner text box should have been added before calling computeLogicalHeight to
+ // avoid this hack.
+ updateIntrinsicContentLogicalHeight(logicalHeight);
+
+ logicalHeight += borderAndPaddingHeight();
}
RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
}
-void RenderTextControl::hitInnerTextElement(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
+void RenderTextControl::hitInnerEditorElement(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
{
- HTMLElement* innerText = innerTextElement();
- if (!innerText->renderer())
+ HTMLElement* innerEditor = innerEditorElement();
+ if (!innerEditor->renderer())
return;
LayoutPoint adjustedLocation = accumulatedOffset + location();
- LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerText->renderBox()->location());
+ LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerEditor->renderBox()->location());
if (hasOverflowClip())
localPoint += scrolledContentOffset();
- result.setInnerNode(innerText);
- result.setInnerNonSharedNode(innerText);
+ result.setInnerNode(innerEditor);
+ result.setInnerNonSharedNode(innerEditor);
result.setLocalPoint(localPoint);
}
@@ -234,16 +240,16 @@ float RenderTextControl::scaleEmToUnits(int x) const
{
// This matches the unitsPerEm value for MS Shell Dlg and Courier New from the "head" font table.
float unitsPerEm = 2048.0f;
- return roundf(style()->font().size() * x / unitsPerEm);
+ return roundf(style()->font().fontDescription().computedSize() * x / unitsPerEm);
}
void RenderTextControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
// Use average character width. Matches IE.
- AtomicString family = style()->font().family().family();
+ AtomicString family = style()->font().fontDescription().family().family();
maxLogicalWidth = preferredContentLogicalWidth(const_cast<RenderTextControl*>(this)->getAvgCharWidth(family));
- if (RenderBox* innerTextRenderBox = innerTextElement()->renderBox())
- maxLogicalWidth += innerTextRenderBox->paddingStart() + innerTextRenderBox->paddingEnd();
+ if (RenderBox* innerEditorRenderBox = innerEditorElement()->renderBox())
+ maxLogicalWidth += innerEditorRenderBox->paddingStart() + innerEditorRenderBox->paddingEnd();
if (!style()->logicalWidth().isPercent())
minLogicalWidth = maxLogicalWidth;
}
@@ -254,20 +260,21 @@ void RenderTextControl::computePreferredLogicalWidths()
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
+ RenderStyle* styleToUse = style();
- if (style()->logicalWidth().isFixed() && style()->logicalWidth().value() >= 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->logicalWidth().value());
+ if (styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() >= 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalWidth().value());
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- if (style()->logicalMinWidth().isFixed() && style()->logicalMinWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMinWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMinWidth().value()));
+ if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
}
- if (style()->logicalMaxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMaxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMaxWidth().value()));
+ if (styleToUse->logicalMaxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
}
LayoutUnit toAdd = borderAndPaddingLogicalWidth();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.h
index 6269af8d7e0..5a0434563aa 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControl.h
@@ -34,20 +34,21 @@ public:
virtual ~RenderTextControl();
HTMLTextFormControlElement* textFormControlElement() const;
- virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
+ virtual PassRefPtr<RenderStyle> createInnerEditorStyle(const RenderStyle* startStyle) const = 0;
protected:
RenderTextControl(HTMLTextFormControlElement*);
- // This convenience function should not be made public because innerTextElement may outlive the render tree.
- HTMLElement* innerTextElement() const;
+ // This convenience function should not be made public because
+ // innerEditorElement may outlive the render tree.
+ HTMLElement* innerEditorElement() const;
int scrollbarThickness() const;
- void adjustInnerTextStyle(RenderStyle* textBlockStyle) const;
+ void adjustInnerEditorStyle(RenderStyle* textBlockStyle) const;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
- void hitInnerTextElement(HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
+ void hitInnerEditorElement(HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
int textBlockLogicalWidth() const;
int textBlockLogicalHeight() const;
@@ -59,9 +60,9 @@ protected:
virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const = 0;
virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const = 0;
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&);
+ virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) OVERRIDE;
// We need to override this function because we don't want overflow:hidden on an <input>
// to affect the baseline calculation. This is necessary because we are an inline-block
@@ -69,20 +70,19 @@ protected:
virtual int inlineBlockBaseline(LineDirectionMode direction) const OVERRIDE { return lastLineBoxBaseline(direction); }
private:
- virtual const char* renderName() const { return "RenderTextControl"; }
- virtual bool isTextControl() const { return true; }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
- virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
- virtual void computePreferredLogicalWidths() OVERRIDE;
- virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
- virtual bool avoidsFloats() const { return true; }
- virtual bool canHaveGeneratedChildren() const OVERRIDE { return false; }
+ virtual const char* renderName() const OVERRIDE { return "RenderTextControl"; }
+ virtual bool isTextControl() const OVERRIDE FINAL { return true; }
+ virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE FINAL;
+ virtual void computePreferredLogicalWidths() OVERRIDE FINAL;
+ virtual void removeLeftoverAnonymousBlock(RenderBlock*) OVERRIDE FINAL { }
+ virtual bool avoidsFloats() const OVERRIDE FINAL { return true; }
+ virtual bool canHaveGeneratedChildren() const OVERRIDE FINAL { return false; }
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE FINAL;
- virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
+ virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE FINAL;
- virtual bool canBeProgramaticallyScrolled() const { return true; }
+ virtual bool canBeProgramaticallyScrolled() const OVERRIDE FINAL { return true; }
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTextControl, isTextControl());
@@ -104,7 +104,6 @@ public:
}
virtual int firstLineBoxBaseline() const OVERRIDE { return RenderBlock::firstLineBoxBaseline(); }
virtual int inlineBlockBaseline(LineDirectionMode direction) const OVERRIDE { return lastLineBoxBaseline(direction); }
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.cpp
index 01fa15a7d4d..eef715fa748 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.cpp
@@ -35,8 +35,6 @@ RenderTextControlMultiLine::RenderTextControlMultiLine(HTMLTextAreaElement* elem
RenderTextControlMultiLine::~RenderTextControlMultiLine()
{
- if (node() && node()->inDocument())
- toHTMLTextAreaElement(node())->rendererWillBeDestroyed();
}
bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
@@ -44,8 +42,8 @@ bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitT
if (!RenderTextControl::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
return false;
- if (result.innerNode() == node() || result.innerNode() == innerTextElement())
- hitInnerTextElement(result, locationInContainer.point(), accumulatedOffset);
+ if (result.innerNode() == node() || result.innerNode() == innerEditorElement())
+ hitInnerEditorElement(result, locationInContainer.point(), accumulatedOffset);
return true;
}
@@ -77,11 +75,11 @@ int RenderTextControlMultiLine::baselinePosition(FontBaseline baselineType, bool
return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
}
-PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const
+PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerEditorStyle(const RenderStyle* startStyle) const
{
RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
textBlockStyle->inheritFrom(startStyle);
- adjustInnerTextStyle(textBlockStyle.get());
+ adjustInnerEditorStyle(textBlockStyle.get());
textBlockStyle->setDisplay(BLOCK);
textBlockStyle->setUnique();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.h
index 3371c2602b0..73132f5372d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlMultiLine.h
@@ -34,19 +34,19 @@ public:
virtual ~RenderTextControlMultiLine();
private:
- virtual bool isTextArea() const { return true; }
+ virtual bool isTextArea() const OVERRIDE { return true; }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual float getAvgCharWidth(AtomicString family);
- virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const;
+ virtual float getAvgCharWidth(AtomicString family) OVERRIDE;
+ virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const OVERRIDE;
virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE;
// We override the two baseline functions because we want our baseline to be the bottom of our margin box.
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE { return -1; }
- virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
- virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&);
+ virtual PassRefPtr<RenderStyle> createInnerEditorStyle(const RenderStyle* startStyle) const OVERRIDE;
+ virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope&) OVERRIDE;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTextControlMultiLine, isTextArea());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.cpp
index 04ecfea2fc8..b896d6c9c0b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.cpp
@@ -24,13 +24,12 @@
#include "config.h"
#include "core/rendering/RenderTextControlSingleLine.h"
-#include "CSSValueKeywords.h"
+#include "core/CSSValueKeywords.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/FrameSelection.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/shadow/ShadowElementNames.h"
-#include "core/frame/Frame.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderTheme.h"
#include "platform/PlatformKeyboardEvent.h"
@@ -45,9 +44,8 @@ using namespace HTMLNames;
RenderTextControlSingleLine::RenderTextControlSingleLine(HTMLInputElement* element)
: RenderTextControl(element)
, m_shouldDrawCapsLockIndicator(false)
- , m_desiredInnerTextLogicalHeight(-1)
+ , m_desiredInnerEditorLogicalHeight(-1)
{
- ASSERT(element->hasTagName(inputTag));
}
RenderTextControlSingleLine::~RenderTextControlSingleLine()
@@ -95,8 +93,7 @@ LayoutUnit RenderTextControlSingleLine::computeLogicalHeightLimit() const
void RenderTextControlSingleLine::layout()
{
- LayoutRectRecorder recorder(*this);
- SubtreeLayoutScope layoutScope(this);
+ SubtreeLayoutScope layoutScope(*this);
// FIXME: We should remove the height-related hacks in layout() and
// styleDidChange(). We need them because
@@ -109,13 +106,16 @@ void RenderTextControlSingleLine::layout()
// and type=search if the text height is taller than the contentHeight()
// because of compability.
- RenderBox* innerTextRenderer = innerTextElement()->renderBox();
+ RenderBox* innerEditorRenderer = innerEditorElement()->renderBox();
RenderBox* viewPortRenderer = editingViewPortElement() ? editingViewPortElement()->renderBox() : 0;
// To ensure consistency between layouts, we need to reset any conditionally overriden height.
- if (innerTextRenderer && !innerTextRenderer->style()->logicalHeight().isAuto()) {
- innerTextRenderer->style()->setLogicalHeight(Length(Auto));
- layoutScope.setNeedsLayout(innerTextRenderer);
+ if (innerEditorRenderer && !innerEditorRenderer->style()->logicalHeight().isAuto()) {
+ innerEditorRenderer->style()->setLogicalHeight(Length(Auto));
+ layoutScope.setNeedsLayout(innerEditorRenderer);
+ HTMLElement* placeholderElement = inputElement()->placeholderElement();
+ if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0)
+ layoutScope.setNeedsLayout(placeholderBox);
}
if (viewPortRenderer && !viewPortRenderer->style()->logicalHeight().isAuto()) {
viewPortRenderer->style()->setLogicalHeight(Length(Auto));
@@ -130,14 +130,14 @@ void RenderTextControlSingleLine::layout()
// Set the text block height
LayoutUnit desiredLogicalHeight = textBlockLogicalHeight();
LayoutUnit logicalHeightLimit = computeLogicalHeightLimit();
- if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) {
- if (desiredLogicalHeight != innerTextRenderer->logicalHeight())
+ if (innerEditorRenderer && innerEditorRenderer->logicalHeight() > logicalHeightLimit) {
+ if (desiredLogicalHeight != innerEditorRenderer->logicalHeight())
layoutScope.setNeedsLayout(this);
- m_desiredInnerTextLogicalHeight = desiredLogicalHeight;
+ m_desiredInnerEditorLogicalHeight = desiredLogicalHeight;
- innerTextRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
- layoutScope.setNeedsLayout(innerTextRenderer);
+ innerEditorRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
+ layoutScope.setNeedsLayout(innerEditorRenderer);
if (viewPortRenderer) {
viewPortRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
layoutScope.setNeedsLayout(viewPortRenderer);
@@ -162,45 +162,36 @@ void RenderTextControlSingleLine::layout()
RenderBlockFlow::layoutBlock(true);
// Center the child block in the block progression direction (vertical centering for horizontal text fields).
- if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight()) {
- LayoutUnit logicalHeightDiff = innerTextRenderer->logicalHeight() - contentLogicalHeight();
- innerTextRenderer->setLogicalTop(innerTextRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2)));
+ if (!container && innerEditorRenderer && innerEditorRenderer->height() != contentLogicalHeight()) {
+ LayoutUnit logicalHeightDiff = innerEditorRenderer->logicalHeight() - contentLogicalHeight();
+ innerEditorRenderer->setLogicalTop(innerEditorRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2)));
} else
centerContainerIfNeeded(containerRenderer);
- // Ignores the paddings for the inner spin button.
- if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
- RenderBox* parentBox = innerSpinBox->parentBox();
- if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection())
- innerSpinBox->setLogicalLocation(LayoutPoint(-paddingLogicalLeft(), -paddingBefore()));
- else
- innerSpinBox->setLogicalLocation(LayoutPoint(parentBox->logicalWidth() - innerSpinBox->logicalWidth() + paddingLogicalRight(), -paddingBefore()));
- innerSpinBox->setLogicalHeight(logicalHeight() - borderBefore() - borderAfter());
- }
-
HTMLElement* placeholderElement = inputElement()->placeholderElement();
if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
- LayoutSize innerTextSize;
- if (innerTextRenderer)
- innerTextSize = innerTextRenderer->size();
- placeholderBox->style()->setWidth(Length(innerTextSize.width() - placeholderBox->borderAndPaddingWidth(), Fixed));
- placeholderBox->style()->setHeight(Length(innerTextSize.height() - placeholderBox->borderAndPaddingHeight(), Fixed));
+ LayoutSize innerEditorSize;
+
+ if (innerEditorRenderer)
+ innerEditorSize = innerEditorRenderer->size();
+ placeholderBox->style()->setWidth(Length(innerEditorSize.width() - placeholderBox->borderAndPaddingWidth(), Fixed));
+ placeholderBox->style()->setHeight(Length(innerEditorSize.height() - placeholderBox->borderAndPaddingHeight(), Fixed));
bool neededLayout = placeholderBox->needsLayout();
bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
placeholderBox->layoutIfNeeded();
LayoutPoint textOffset;
- if (innerTextRenderer)
- textOffset = innerTextRenderer->location();
+ if (innerEditorRenderer)
+ textOffset = innerEditorRenderer->location();
if (editingViewPortElement() && editingViewPortElement()->renderBox())
textOffset += toLayoutSize(editingViewPortElement()->renderBox()->location());
if (containerRenderer)
textOffset += toLayoutSize(containerRenderer->location());
placeholderBox->setLocation(textOffset);
- if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
+ if (!placeholderBoxHadLayout && placeholderBox->checkForPaintInvalidationDuringLayout()) {
// This assumes a shadow tree without floats. If floats are added, the
- // logic should be shared with RenderBlock::layoutBlockChild.
- placeholderBox->repaint();
+ // logic should be shared with RenderBlockFlow::layoutBlockChild.
+ placeholderBox->paintInvalidationForWholeRenderer();
}
// The placeholder gets layout last, after the parent text control and its other children,
// so in order to get the correct overflow from the placeholder we need to recompute it now.
@@ -219,7 +210,7 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
// - we hit the <input> element (e.g. we're over the border or padding), or
// - we hit regions not in any decoration buttons.
Element* container = containerElement();
- if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node() || (container && container == result.innerNode())) {
+ if (result.innerNode()->isDescendantOf(innerEditorElement()) || result.innerNode() == node() || (container && container == result.innerNode())) {
LayoutPoint pointInParent = locationInContainer.point();
if (container && editingViewPortElement()) {
if (editingViewPortElement()->renderBox())
@@ -227,14 +218,14 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
if (container->renderBox())
pointInParent -= toLayoutSize(container->renderBox()->location());
}
- hitInnerTextElement(result, pointInParent, accumulatedOffset);
+ hitInnerEditorElement(result, pointInParent, accumulatedOffset);
}
return true;
}
void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- m_desiredInnerTextLogicalHeight = -1;
+ m_desiredInnerEditorLogicalHeight = -1;
RenderTextControl::styleDidChange(diff, oldStyle);
// We may have set the width and the height in the old style in layout().
@@ -249,9 +240,9 @@ void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const Ren
containerRenderer->style()->setHeight(Length());
containerRenderer->style()->setWidth(Length());
}
- RenderObject* innerTextRenderer = innerTextElement()->renderer();
- if (innerTextRenderer && diff == StyleDifferenceLayout)
- innerTextRenderer->setNeedsLayout();
+ RenderObject* innerEditorRenderer = innerEditorElement()->renderer();
+ if (innerEditorRenderer && diff.needsFullLayout())
+ innerEditorRenderer->setNeedsLayoutAndFullPaintInvalidation();
if (HTMLElement* placeholder = inputElement()->placeholderElement())
placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
setHasOverflowClip(false);
@@ -269,12 +260,12 @@ void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
// 4) The caps lock is on
bool shouldDrawCapsLockIndicator = false;
- if (Frame* frame = document().frame())
+ if (LocalFrame* frame = document().frame())
shouldDrawCapsLockIndicator = inputElement()->isPasswordField() && frame->selection().isFocusedAndActive() && document().focusedElement() == node() && PlatformKeyboardEvent::currentCapsLockState();
if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
- repaint();
+ paintInvalidationForWholeRenderer();
}
}
@@ -316,7 +307,7 @@ LayoutUnit RenderTextControlSingleLine::preferredContentLogicalWidth(float charW
LayoutUnit result = LayoutUnit::fromFloatCeil(charWidth * factor);
float maxCharWidth = 0.f;
- AtomicString family = style()->font().family().family();
+ AtomicString family = style()->font().fontDescription().family().family();
// Since Lucida Grande is the default font, we want this to match the width
// of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
// IE for some encodings (in IE, the default font is encoding specific).
@@ -348,16 +339,11 @@ LayoutUnit RenderTextControlSingleLine::computeControlLogicalHeight(LayoutUnit l
return lineHeight + nonContentHeight;
}
-void RenderTextControlSingleLine::updateFromElement()
-{
- RenderTextControl::updateFromElement();
-}
-
-PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerEditorStyle(const RenderStyle* startStyle) const
{
RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
textBlockStyle->inheritFrom(startStyle);
- adjustInnerTextStyle(textBlockStyle.get());
+ adjustInnerEditorStyle(textBlockStyle.get());
textBlockStyle->setWhiteSpace(PRE);
textBlockStyle->setOverflowWrap(NormalOverflowWrap);
@@ -365,8 +351,8 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const
textBlockStyle->setOverflowY(OHIDDEN);
textBlockStyle->setTextOverflow(textShouldBeTruncated() ? TextOverflowEllipsis : TextOverflowClip);
- if (m_desiredInnerTextLogicalHeight >= 0)
- textBlockStyle->setLogicalHeight(Length(m_desiredInnerTextLogicalHeight, Fixed));
+ if (m_desiredInnerEditorLogicalHeight >= 0)
+ textBlockStyle->setLogicalHeight(Length(m_desiredInnerEditorLogicalHeight, Fixed));
// Do not allow line-height to be smaller than our default.
if (textBlockStyle->fontMetrics().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
textBlockStyle->setLineHeight(RenderStyle::initialLineHeight());
@@ -374,6 +360,9 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const
textBlockStyle->setDisplay(BLOCK);
textBlockStyle->setUnique();
+ if (inputElement()->shouldRevealPassword())
+ textBlockStyle->setTextSecurity(TSNONE);
+
return textBlockStyle.release();
}
@@ -384,51 +373,51 @@ bool RenderTextControlSingleLine::textShouldBeTruncated() const
void RenderTextControlSingleLine::autoscroll(const IntPoint& position)
{
- RenderBox* renderer = innerTextElement()->renderBox();
+ RenderBox* renderer = innerEditorElement()->renderBox();
if (!renderer)
return;
renderer->autoscroll(position);
}
-int RenderTextControlSingleLine::scrollWidth() const
+LayoutUnit RenderTextControlSingleLine::scrollWidth() const
{
- if (innerTextElement())
- return innerTextElement()->scrollWidth();
- return RenderBlock::scrollWidth();
+ if (innerEditorElement())
+ return innerEditorElement()->scrollWidth();
+ return RenderBlockFlow::scrollWidth();
}
-int RenderTextControlSingleLine::scrollHeight() const
+LayoutUnit RenderTextControlSingleLine::scrollHeight() const
{
- if (innerTextElement())
- return innerTextElement()->scrollHeight();
- return RenderBlock::scrollHeight();
+ if (innerEditorElement())
+ return innerEditorElement()->scrollHeight();
+ return RenderBlockFlow::scrollHeight();
}
-int RenderTextControlSingleLine::scrollLeft() const
+LayoutUnit RenderTextControlSingleLine::scrollLeft() const
{
- if (innerTextElement())
- return innerTextElement()->scrollLeft();
- return RenderBlock::scrollLeft();
+ if (innerEditorElement())
+ return innerEditorElement()->scrollLeft();
+ return RenderBlockFlow::scrollLeft();
}
-int RenderTextControlSingleLine::scrollTop() const
+LayoutUnit RenderTextControlSingleLine::scrollTop() const
{
- if (innerTextElement())
- return innerTextElement()->scrollTop();
- return RenderBlock::scrollTop();
+ if (innerEditorElement())
+ return innerEditorElement()->scrollTop();
+ return RenderBlockFlow::scrollTop();
}
-void RenderTextControlSingleLine::setScrollLeft(int newLeft)
+void RenderTextControlSingleLine::setScrollLeft(LayoutUnit newLeft)
{
- if (innerTextElement())
- innerTextElement()->setScrollLeft(newLeft);
+ if (innerEditorElement())
+ innerEditorElement()->setScrollLeft(newLeft);
}
-void RenderTextControlSingleLine::setScrollTop(int newTop)
+void RenderTextControlSingleLine::setScrollTop(LayoutUnit newTop)
{
- if (innerTextElement())
- innerTextElement()->setScrollTop(newTop);
+ if (innerEditorElement())
+ innerEditorElement()->setScrollTop(newTop);
}
HTMLInputElement* RenderTextControlSingleLine::inputElement() const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.h
index 64a07cc74fc..60715c0deb9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextControlSingleLine.h
@@ -34,8 +34,8 @@ class RenderTextControlSingleLine : public RenderTextControl {
public:
RenderTextControlSingleLine(HTMLInputElement*);
virtual ~RenderTextControlSingleLine();
- // FIXME: Move createInnerTextStyle() to TextControlInnerTextElement.
- virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
+ // FIXME: Move createInnerEditorStyle() to TextControlInnerEditorElement.
+ virtual PassRefPtr<RenderStyle> createInnerEditorStyle(const RenderStyle* startStyle) const OVERRIDE FINAL;
void capsLockStateMayHaveChanged();
@@ -45,41 +45,40 @@ protected:
Element* containerElement() const;
Element* editingViewPortElement() const;
HTMLInputElement* inputElement() const;
- virtual void updateFromElement() OVERRIDE;
private:
- virtual bool hasControlClip() const;
- virtual LayoutRect controlClipRect(const LayoutPoint&) const;
- virtual bool isTextField() const { return true; }
+ virtual bool hasControlClip() const OVERRIDE FINAL;
+ virtual LayoutRect controlClipRect(const LayoutPoint&) const OVERRIDE FINAL;
+ virtual bool isTextField() const OVERRIDE FINAL { return true; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual void layout();
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual void layout() OVERRIDE;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
- virtual void autoscroll(const IntPoint&);
+ virtual void autoscroll(const IntPoint&) OVERRIDE FINAL;
// Subclassed to forward to our inner div.
- virtual int scrollLeft() const;
- virtual int scrollTop() const;
- virtual int scrollWidth() const;
- virtual int scrollHeight() const;
- virtual void setScrollLeft(int);
- virtual void setScrollTop(int);
+ virtual LayoutUnit scrollLeft() const OVERRIDE FINAL;
+ virtual LayoutUnit scrollTop() const OVERRIDE FINAL;
+ virtual LayoutUnit scrollWidth() const OVERRIDE FINAL;
+ virtual LayoutUnit scrollHeight() const OVERRIDE FINAL;
+ virtual void setScrollLeft(LayoutUnit) OVERRIDE FINAL;
+ virtual void setScrollTop(LayoutUnit) OVERRIDE FINAL;
int textBlockWidth() const;
- virtual float getAvgCharWidth(AtomicString family);
- virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const;
+ virtual float getAvgCharWidth(AtomicString family) OVERRIDE FINAL;
+ virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const OVERRIDE FINAL;
virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
bool textShouldBeTruncated() const;
HTMLElement* innerSpinButtonElement() const;
bool m_shouldDrawCapsLockIndicator;
- LayoutUnit m_desiredInnerTextLogicalHeight;
+ LayoutUnit m_desiredInnerEditorLogicalHeight;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTextControlSingleLine, isTextField());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.cpp
index 759eb9dd368..f2eb3ff2262 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.cpp
@@ -30,7 +30,7 @@
namespace WebCore {
RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOffset, int length)
- : RenderText(node, str ? str->substring(startOffset, length) : PassRefPtr<StringImpl>(0))
+ : RenderText(node, str ? str->substring(startOffset, length) : PassRefPtr<StringImpl>(nullptr))
, m_start(startOffset)
, m_end(length)
, m_firstLetter(0)
@@ -64,7 +64,7 @@ PassRefPtr<StringImpl> RenderTextFragment::originalText() const
Node* e = node();
RefPtr<StringImpl> result = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString());
if (!result)
- return 0;
+ return nullptr;
return result->substring(start(), end());
}
@@ -92,6 +92,10 @@ void RenderTextFragment::setText(PassRefPtr<StringImpl> text, bool force)
m_start = 0;
m_end = textLength();
if (m_firstLetter) {
+ // FIXME: We should not modify the structure of the render tree during
+ // layout. crbug.com/370458
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
+
ASSERT(!m_contentString);
m_firstLetter->destroy();
m_firstLetter = 0;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.h
index 44bbfe81f6d..de9858c4862 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTextFragment.h
@@ -37,7 +37,7 @@ public:
RenderTextFragment(Node*, StringImpl*);
virtual ~RenderTextFragment();
- virtual bool isTextFragment() const { return true; }
+ virtual bool isTextFragment() const OVERRIDE { return true; }
virtual bool canBeSelectionLeaf() const OVERRIDE { return node() && node()->rendererIsEditable(); }
@@ -45,31 +45,31 @@ public:
unsigned end() const { return m_end; }
virtual unsigned textStartOffset() const OVERRIDE { return start(); }
- RenderObject* firstLetter() const { return m_firstLetter; }
- void setFirstLetter(RenderObject* firstLetter) { m_firstLetter = firstLetter; }
+ RenderBoxModelObject* firstLetter() const { return m_firstLetter; }
+ void setFirstLetter(RenderBoxModelObject* firstLetter) { m_firstLetter = firstLetter; }
RenderText* firstRenderTextInFirstLetter() const;
StringImpl* contentString() const { return m_contentString.get(); }
- virtual PassRefPtr<StringImpl> originalText() const;
+ virtual PassRefPtr<StringImpl> originalText() const OVERRIDE;
virtual void setText(PassRefPtr<StringImpl>, bool force = false) OVERRIDE;
virtual void transformText() OVERRIDE;
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
private:
- virtual void willBeDestroyed();
+ virtual void willBeDestroyed() OVERRIDE;
- virtual UChar previousCharacter() const;
+ virtual UChar previousCharacter() const OVERRIDE;
RenderBlock* blockForAccompanyingFirstLetter() const;
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) OVERRIDE;
unsigned m_start;
unsigned m_end;
RefPtr<StringImpl> m_contentString;
- RenderObject* m_firstLetter;
+ RenderBoxModelObject* m_firstLetter;
};
DEFINE_TYPE_CASTS(RenderTextFragment, RenderObject, object, toRenderText(object)->isTextFragment(), toRenderText(object).isTextFragment());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.cpp
index 90c56f77dbd..3c0e2c6fe12 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.cpp
@@ -22,16 +22,17 @@
#include "config.h"
#include "core/rendering/RenderTheme.h"
-#include "CSSValueKeywords.h"
-#include "HTMLNames.h"
-#include "InputTypeNames.h"
-#include "RuntimeEnabledFeatures.h"
+#include "core/CSSValueKeywords.h"
+#include "core/HTMLNames.h"
+#include "core/InputTypeNames.h"
#include "core/dom/Document.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/editing/FrameSelection.h"
#include "core/fileapi/FileList.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLCollection.h"
#include "core/html/HTMLDataListElement.h"
+#include "core/html/HTMLFormControlElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMeterElement.h"
#include "core/html/HTMLOptionElement.h"
@@ -41,7 +42,6 @@
#include "core/html/shadow/SpinButtonElement.h"
#include "core/html/shadow/TextControlInnerElements.h"
#include "core/page/FocusController.h"
-#include "core/frame/Frame.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "core/rendering/PaintInfo.h"
@@ -50,6 +50,7 @@
#include "core/rendering/style/RenderStyle.h"
#include "platform/FileMetadata.h"
#include "platform/FloatConversion.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/FontSelector.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/text/PlatformLocale.h"
@@ -59,22 +60,12 @@
#include "public/platform/WebRect.h"
#include "wtf/text/StringBuilder.h"
-#if ENABLE(INPUT_SPEECH)
-#include "core/rendering/RenderInputSpeech.h"
-#endif
-
// The methods in this file are shared by all themes on every platform.
namespace WebCore {
using namespace HTMLNames;
-static Color& customFocusRingColor()
-{
- DEFINE_STATIC_LOCAL(Color, color, ());
- return color;
-}
-
static blink::WebFallbackThemeEngine::State getWebFallbackThemeState(const RenderTheme* theme, const RenderObject* o)
{
if (!theme->isEnabled(o))
@@ -88,13 +79,14 @@ static blink::WebFallbackThemeEngine::State getWebFallbackThemeState(const Rende
}
RenderTheme::RenderTheme()
+ : m_hasCustomFocusRingColor(false)
#if USE(NEW_THEME)
- : m_platformTheme(platformTheme())
+ , m_platformTheme(platformTheme())
#endif
{
}
-void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyle& uaStyle)
+void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyle* uaStyle)
{
// Force inline and table display styles to be inline-block (except for table- which is block)
ControlPart part = style->appearance();
@@ -106,7 +98,7 @@ void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyl
else if (style->display() == LIST_ITEM || style->display() == TABLE)
style->setDisplay(BLOCK);
- if (uaStyle.hasAppearance && isControlStyled(style, uaStyle)) {
+ if (uaStyle && uaStyle->hasAppearance && isControlStyled(style, uaStyle)) {
if (part == MenulistPart) {
style->setAppearance(MenulistButtonPart);
part = MenulistButtonPart;
@@ -193,7 +185,7 @@ void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyl
// Now update our font.
if (style->setFontDescription(controlFont))
- style->font().update(0);
+ style->font().update(nullptr);
}
}
default:
@@ -230,10 +222,6 @@ void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyl
return adjustSearchFieldDecorationStyle(style, e);
case SearchFieldResultsDecorationPart:
return adjustSearchFieldResultsDecorationStyle(style, e);
-#if ENABLE(INPUT_SPEECH)
- case InputSpeechButtonPart:
- return adjustInputFieldSpeechButtonStyle(style, e);
-#endif
default:
break;
}
@@ -246,12 +234,9 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRe
// for that control.
if (paintInfo.context->updatingControlTints()) {
if (controlSupportsTints(o))
- o->repaint();
+ o->paintInvalidationForWholeRenderer();
return false;
}
- if (paintInfo.context->paintingDisabled())
- return false;
-
ControlPart part = o->style()->appearance();
if (shouldUseFallbackTheme(o->style()))
@@ -311,22 +296,12 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRe
return paintMediaOverlayPlayButton(o, paintInfo, r);
case MediaMuteButtonPart:
return paintMediaMuteButton(o, paintInfo, r);
- case MediaSeekBackButtonPart:
- return paintMediaSeekBackButton(o, paintInfo, r);
- case MediaSeekForwardButtonPart:
- return paintMediaSeekForwardButton(o, paintInfo, r);
- case MediaRewindButtonPart:
- return paintMediaRewindButton(o, paintInfo, r);
- case MediaReturnToRealtimeButtonPart:
- return paintMediaReturnToRealtimeButton(o, paintInfo, r);
case MediaToggleClosedCaptionsButtonPart:
return paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
case MediaSliderPart:
return paintMediaSliderTrack(o, paintInfo, r);
case MediaSliderThumbPart:
return paintMediaSliderThumb(o, paintInfo, r);
- case MediaVolumeSliderMuteButtonPart:
- return paintMediaMuteButton(o, paintInfo, r);
case MediaVolumeSliderContainerPart:
return paintMediaVolumeSliderContainer(o, paintInfo, r);
case MediaVolumeSliderPart:
@@ -356,10 +331,6 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRe
return paintSearchFieldDecoration(o, paintInfo, r);
case SearchFieldResultsDecorationPart:
return paintSearchFieldResultsDecoration(o, paintInfo, r);
-#if ENABLE(INPUT_SPEECH)
- case InputSpeechButtonPart:
- return paintInputFieldSpeechButton(o, paintInfo, r);
-#endif
default:
break;
}
@@ -369,9 +340,6 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRe
bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- if (paintInfo.context->paintingDisabled())
- return false;
-
// Call the appropriate paint method based off the appearance value.
switch (o->style()->appearance()) {
case TextFieldPart:
@@ -401,9 +369,6 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, c
case SearchFieldCancelButtonPart:
case SearchFieldDecorationPart:
case SearchFieldResultsDecorationPart:
-#if ENABLE(INPUT_SPEECH)
- case InputSpeechButtonPart:
-#endif
default:
break;
}
@@ -413,9 +378,6 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, c
bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- if (paintInfo.context->paintingDisabled())
- return false;
-
// Call the appropriate paint method based off the appearance value.
switch (o->style()->appearance()) {
case MenulistButtonPart:
@@ -443,9 +405,6 @@ bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo,
case SearchFieldCancelButtonPart:
case SearchFieldDecorationPart:
case SearchFieldResultsDecorationPart:
-#if ENABLE(INPUT_SPEECH)
- case InputSpeechButtonPart:
-#endif
default:
break;
}
@@ -455,19 +414,7 @@ bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo,
String RenderTheme::extraDefaultStyleSheet()
{
- if (!RuntimeEnabledFeatures::dataListElementEnabled() && !RuntimeEnabledFeatures::dialogElementEnabled())
- return String();
StringBuilder runtimeCSS;
-
- if (RuntimeEnabledFeatures::dataListElementEnabled()) {
- runtimeCSS.appendLiteral("datalist {display: none ;}");
-
- if (RuntimeEnabledFeatures::inputTypeColorEnabled()) {
- runtimeCSS.appendLiteral("input[type=\"color\"][list] { -webkit-appearance: menulist; width: 88px; height: 23px;}");
- runtimeCSS.appendLiteral("input[type=\"color\"][list]::-webkit-color-swatch-wrapper { padding-left: 8px; padding-right: 24px;}");
- runtimeCSS.appendLiteral("input[type=\"color\"][list]::-webkit-color-swatch { border-color: #000000;}");
- }
- }
if (RuntimeEnabledFeatures::dialogElementEnabled()) {
runtimeCSS.appendLiteral("dialog:not([open]) { display: none; }");
runtimeCSS.appendLiteral("dialog { position: absolute; left: 0; right: 0; width: -webkit-fit-content; height: -webkit-fit-content; margin: auto; border: solid; padding: 1em; background: white; color: black;}");
@@ -502,58 +449,42 @@ String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*du
Color RenderTheme::activeSelectionBackgroundColor() const
{
- if (!m_activeSelectionBackgroundColor.isValid())
- m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
- return m_activeSelectionBackgroundColor;
+ return platformActiveSelectionBackgroundColor().blendWithWhite();
}
Color RenderTheme::inactiveSelectionBackgroundColor() const
{
- if (!m_inactiveSelectionBackgroundColor.isValid())
- m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
- return m_inactiveSelectionBackgroundColor;
+ return platformInactiveSelectionBackgroundColor().blendWithWhite();
}
Color RenderTheme::activeSelectionForegroundColor() const
{
- if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
- m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
- return m_activeSelectionForegroundColor;
+ return platformActiveSelectionForegroundColor();
}
Color RenderTheme::inactiveSelectionForegroundColor() const
{
- if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
- m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
- return m_inactiveSelectionForegroundColor;
+ return platformInactiveSelectionForegroundColor();
}
Color RenderTheme::activeListBoxSelectionBackgroundColor() const
{
- if (!m_activeListBoxSelectionBackgroundColor.isValid())
- m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
- return m_activeListBoxSelectionBackgroundColor;
+ return platformActiveListBoxSelectionBackgroundColor();
}
Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
{
- if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
- m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
- return m_inactiveListBoxSelectionBackgroundColor;
+ return platformInactiveListBoxSelectionBackgroundColor();
}
Color RenderTheme::activeListBoxSelectionForegroundColor() const
{
- if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
- m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
- return m_activeListBoxSelectionForegroundColor;
+ return platformActiveListBoxSelectionForegroundColor();
}
Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
{
- if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
- m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
- return m_inactiveListBoxSelectionForegroundColor;
+ return platformInactiveListBoxSelectionForegroundColor();
}
Color RenderTheme::platformActiveSelectionBackgroundColor() const
@@ -637,8 +568,10 @@ static bool isBackgroundOrBorderStyled(const RenderStyle& style, const CachedUAS
|| style.visitedDependentColor(CSSPropertyBackgroundColor) != uaStyle.backgroundColor;
}
-bool RenderTheme::isControlStyled(const RenderStyle* style, const CachedUAStyle& uaStyle) const
+bool RenderTheme::isControlStyled(const RenderStyle* style, const CachedUAStyle* uaStyle) const
{
+ ASSERT(uaStyle);
+
switch (style->appearance()) {
case PushButtonPart:
case SquareButtonPart:
@@ -649,14 +582,14 @@ bool RenderTheme::isControlStyled(const RenderStyle* style, const CachedUAStyle&
case ContinuousCapacityLevelIndicatorPart:
case DiscreteCapacityLevelIndicatorPart:
case RatingLevelIndicatorPart:
- return isBackgroundOrBorderStyled(*style, uaStyle);
+ return isBackgroundOrBorderStyled(*style, *uaStyle);
case ListboxPart:
case MenulistPart:
case SearchFieldPart:
case TextAreaPart:
case TextFieldPart:
- return isBackgroundOrBorderStyled(*style, uaStyle) || style->boxShadow();
+ return isBackgroundOrBorderStyled(*style, *uaStyle) || style->boxShadow();
case SliderHorizontalPart:
case SliderVerticalPart:
@@ -698,15 +631,15 @@ bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
{
// Default implementation assumes the controls don't respond to changes in :hover state
- if (state == HoverState && !supportsHover(o->style()))
+ if (state == HoverControlState && !supportsHover(o->style()))
return false;
// Assume pressed state is only responded to if the control is enabled.
- if (state == PressedState && !isEnabled(o))
+ if (state == PressedControlState && !isEnabled(o))
return false;
// Repaint the control.
- o->repaint();
+ o->paintInvalidationForWholeRenderer();
return true;
}
@@ -714,27 +647,27 @@ ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
{
ControlStates result = 0;
if (isHovered(o)) {
- result |= HoverState;
+ result |= HoverControlState;
if (isSpinUpButtonPartHovered(o))
- result |= SpinUpState;
+ result |= SpinUpControlState;
}
if (isPressed(o)) {
- result |= PressedState;
+ result |= PressedControlState;
if (isSpinUpButtonPartPressed(o))
- result |= SpinUpState;
+ result |= SpinUpControlState;
}
if (isFocused(o) && o->style()->outlineStyleIsAuto())
- result |= FocusState;
+ result |= FocusControlState;
if (isEnabled(o))
- result |= EnabledState;
+ result |= EnabledControlState;
if (isChecked(o))
- result |= CheckedState;
+ result |= CheckedControlState;
if (isReadOnlyControl(o))
- result |= ReadOnlyState;
+ result |= ReadOnlyControlState;
if (!isActive(o))
- result |= WindowInactiveState;
+ result |= WindowInactiveControlState;
if (isIndeterminate(o))
- result |= IndeterminateState;
+ result |= IndeterminateControlState;
return result;
}
@@ -753,14 +686,14 @@ bool RenderTheme::isActive(const RenderObject* o) const
bool RenderTheme::isChecked(const RenderObject* o) const
{
- if (!o->node() || !o->node()->hasTagName(inputTag))
+ if (!isHTMLInputElement(o->node()))
return false;
return toHTMLInputElement(o->node())->shouldAppearChecked();
}
bool RenderTheme::isIndeterminate(const RenderObject* o) const
{
- if (!o->node() || !o->node()->hasTagName(inputTag))
+ if (!isHTMLInputElement(o->node()))
return false;
return toHTMLInputElement(o->node())->shouldAppearIndeterminate();
}
@@ -781,8 +714,8 @@ bool RenderTheme::isFocused(const RenderObject* o) const
node = node->focusDelegate();
Document& document = node->document();
- Frame* frame = document.frame();
- return node == document.focusedElement() && node->shouldHaveFocusAppearance() && frame && frame->selection().isFocusedAndActive();
+ LocalFrame* frame = document.frame();
+ return node == document.focusedElement() && node->focused() && node->shouldHaveFocusAppearance() && frame && frame->selection().isFocusedAndActive();
}
bool RenderTheme::isPressed(const RenderObject* o) const
@@ -805,9 +738,10 @@ bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
{
Node* node = o->node();
- if (!node || !node->isElementNode())
+ if (!node || !node->isElementNode() || !toElement(node)->isFormControlElement())
return false;
- return toElement(node)->matchesReadOnlyPseudoClass();
+ HTMLFormControlElement* element = toHTMLFormControlElement(node);
+ return element->isReadOnly();
}
bool RenderTheme::isHovered(const RenderObject* o) const
@@ -875,18 +809,6 @@ void RenderTheme::adjustMenuListStyle(RenderStyle*, Element*) const
{
}
-#if ENABLE(INPUT_SPEECH)
-void RenderTheme::adjustInputFieldSpeechButtonStyle(RenderStyle* style, Element* element) const
-{
- RenderInputSpeech::adjustInputFieldSpeechButtonStyle(style, element);
-}
-
-bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
-{
- return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
-}
-#endif
-
IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
{
return bounds.size();
@@ -905,10 +827,13 @@ bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
Node* node = o->node();
- if (!node || !node->hasTagName(inputTag))
+ if (!isHTMLInputElement(node))
return;
HTMLInputElement* input = toHTMLInputElement(node);
+ if (!input->isRangeControl())
+ return;
+
HTMLDataListElement* dataList = input->dataList();
if (!dataList)
return;
@@ -960,13 +885,13 @@ void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo,
tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
tickRegionWidth = trackBounds.height() - thumbSize.width();
}
- RefPtr<HTMLCollection> options = dataList->options();
+ RefPtrWillBeRawPtr<HTMLCollection> options = dataList->options();
GraphicsContextStateSaver stateSaver(*paintInfo.context);
paintInfo.context->setFillColor(o->resolveColor(CSSPropertyColor));
- for (unsigned i = 0; Node* node = options->item(i); i++) {
- ASSERT(node->hasTagName(optionTag));
- HTMLOptionElement* optionElement = toHTMLOptionElement(node);
- String value = optionElement->value();
+ for (unsigned i = 0; Element* element = options->item(i); i++) {
+ ASSERT(isHTMLOptionElement(*element));
+ HTMLOptionElement& optionElement = toHTMLOptionElement(*element);
+ String value = optionElement.value();
if (!input->isValidValue(value))
continue;
double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
@@ -1027,16 +952,6 @@ void RenderTheme::adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*
void RenderTheme::platformColorsDidChange()
{
- m_activeSelectionForegroundColor = Color();
- m_inactiveSelectionForegroundColor = Color();
- m_activeSelectionBackgroundColor = Color();
- m_inactiveSelectionBackgroundColor = Color();
-
- m_activeListBoxSelectionForegroundColor = Color();
- m_inactiveListBoxSelectionForegroundColor = Color();
- m_activeListBoxSelectionBackgroundColor = Color();
- m_inactiveListBoxSelectionForegroundColor = Color();
-
Page::scheduleForcedStyleRecalcForAllPages();
}
@@ -1116,6 +1031,7 @@ Color RenderTheme::systemColor(CSSValueID cssValueId) const
default:
break;
}
+ ASSERT_NOT_REACHED();
return Color();
}
@@ -1136,12 +1052,13 @@ Color RenderTheme::tapHighlightColor()
void RenderTheme::setCustomFocusRingColor(const Color& c)
{
- customFocusRingColor() = c;
+ m_customFocusRingColor = c;
+ m_hasCustomFocusRingColor = true;
}
-Color RenderTheme::focusRingColor()
+Color RenderTheme::focusRingColor() const
{
- return customFocusRingColor().isValid() ? customFocusRingColor() : theme().platformFocusRingColor();
+ return m_hasCustomFocusRingColor ? m_customFocusRingColor : theme().platformFocusRingColor();
}
String RenderTheme::fileListNameForWidth(Locale& locale, const FileList* fileList, const Font& font, int width) const
@@ -1167,20 +1084,6 @@ bool RenderTheme::shouldOpenPickerWithF4Key() const
return false;
}
-bool RenderTheme::supportsDataListUI(const AtomicString& type) const
-{
- return type == InputTypeNames::text || type == InputTypeNames::search || type == InputTypeNames::url
- || type == InputTypeNames::tel || type == InputTypeNames::email || type == InputTypeNames::number
- || type == InputTypeNames::color
- || type == InputTypeNames::date
- || type == InputTypeNames::datetime
- || type == InputTypeNames::datetime_local
- || type == InputTypeNames::month
- || type == InputTypeNames::week
- || type == InputTypeNames::time
- || type == InputTypeNames::range;
-}
-
#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
bool RenderTheme::supportsCalendarPicker(const AtomicString& type) const
{
@@ -1235,6 +1138,8 @@ void RenderTheme::setSizeIfAuto(RenderStyle* style, const IntSize& size)
bool RenderTheme::paintCheckboxUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebFallbackThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.button.checked = isChecked(o);
@@ -1247,7 +1152,7 @@ bool RenderTheme::paintCheckboxUsingFallbackTheme(RenderObject* o, const PaintIn
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
i.context->translate(unzoomedRect.x(), unzoomedRect.y());
- i.context->scale(FloatSize(zoomLevel, zoomLevel));
+ i.context->scale(zoomLevel, zoomLevel);
i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -1277,6 +1182,8 @@ void RenderTheme::adjustCheckboxStyleUsingFallbackTheme(RenderStyle* style, Elem
bool RenderTheme::paintRadioUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebFallbackThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.button.checked = isChecked(o);
@@ -1289,7 +1196,7 @@ bool RenderTheme::paintRadioUsingFallbackTheme(RenderObject* o, const PaintInfo&
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
i.context->translate(unzoomedRect.x(), unzoomedRect.y());
- i.context->scale(FloatSize(zoomLevel, zoomLevel));
+ i.context->scale(zoomLevel, zoomLevel);
i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.h
index 30a1c143153..4e8661e50b8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTheme.h
@@ -37,12 +37,9 @@
namespace WebCore {
-class CSSStyleSheet;
class Element;
class FileList;
class HTMLInputElement;
-class PopupMenu;
-class RenderMenuList;
class RenderMeter;
class RenderProgress;
@@ -65,7 +62,7 @@ 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(RenderStyle*, Element*, const CachedUAStyle&);
+ void adjustStyle(RenderStyle*, Element*, const CachedUAStyle*);
// 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
@@ -97,7 +94,7 @@ public:
virtual bool controlSupportsTints(const RenderObject*) const { return false; }
// Whether or not the control has been styled enough by the author to disable the native appearance.
- virtual bool isControlStyled(const RenderStyle*, const CachedUAStyle&) const;
+ virtual bool isControlStyled(const RenderStyle*, const CachedUAStyle*) const;
// A general method asking if any control tinting is supported at all.
virtual bool supportsControlTints() const { return false; }
@@ -115,9 +112,6 @@ 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;
-
#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
// A method asking if the platform is able to show a calendar picker for a given input type.
virtual bool supportsCalendarPicker(const AtomicString&) const;
@@ -139,11 +133,12 @@ public:
virtual Color platformActiveTextSearchHighlightColor() const;
virtual Color platformInactiveTextSearchHighlightColor() const;
- static Color focusRingColor();
+ Color focusRingColor() const;
virtual Color platformFocusRingColor() const { return Color(0, 0, 0); }
- static void setCustomFocusRingColor(const Color&);
+ void setCustomFocusRingColor(const Color&);
static Color tapHighlightColor();
virtual Color platformTapHighlightColor() const { return RenderTheme::defaultTapHighlightColor; }
+ virtual Color platformDefaultCompositionBackgroundColor() const { return defaultCompositionBackgroundColor; }
virtual void platformColorsDidChange();
virtual double caretBlinkInterval() const { return 0.5; }
@@ -173,9 +168,6 @@ public:
virtual double animationDurationForProgressBar(RenderProgress*) const;
// Media controls
- virtual bool supportsClosedCaptioning() const { return false; }
- virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return false; }
- virtual bool usesVerticalVolumeSlider() const { return true; }
virtual String formatMediaControlsTime(float time) const;
virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
@@ -201,6 +193,8 @@ public:
virtual bool shouldOpenPickerWithF4Key() const;
+ virtual bool supportsSelectionForegroundColors() const { return true; }
+
protected:
// The platform selection color.
virtual Color platformActiveSelectionBackgroundColor() const;
@@ -215,8 +209,6 @@ protected:
// A method asking if the theme is able to draw the focus ring.
virtual bool supportsFocusRing(const RenderStyle*) const;
- virtual bool supportsSelectionForegroundColors() const { return true; }
- virtual bool supportsListBoxSelectionForegroundColors() const { return true; }
#if !USE(NEW_THEME)
// Methods for each appearance value.
@@ -249,11 +241,6 @@ protected:
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
-#if ENABLE(INPUT_SPEECH)
- virtual void adjustInputFieldSpeechButtonStyle(RenderStyle*, Element*) const;
- virtual bool paintInputFieldSpeechButton(RenderObject*, const PaintInfo&, const IntRect&);
-#endif
-
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual void adjustSliderThumbStyle(RenderStyle*, Element*) const;
@@ -275,15 +262,11 @@ protected:
virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaOverlayPlayButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual bool paintMediaSeekBackButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual bool paintMediaSeekForwardButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual bool paintMediaRewindButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaCurrentTime(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
@@ -314,20 +297,15 @@ public:
bool isReadOnlyControl(const RenderObject*) const;
private:
- mutable Color m_activeSelectionBackgroundColor;
- mutable Color m_inactiveSelectionBackgroundColor;
- mutable Color m_activeSelectionForegroundColor;
- mutable Color m_inactiveSelectionForegroundColor;
-
- mutable Color m_activeListBoxSelectionBackgroundColor;
- mutable Color m_inactiveListBoxSelectionBackgroundColor;
- mutable Color m_activeListBoxSelectionForegroundColor;
- mutable Color m_inactiveListBoxSelectionForegroundColor;
+ Color m_customFocusRingColor;
+ bool m_hasCustomFocusRingColor;
// This color is expected to be drawn on a semi-transparent overlay,
// making it more transparent than its alpha value indicates.
static const RGBA32 defaultTapHighlightColor = 0x66000000;
+ static const RGBA32 defaultCompositionBackgroundColor = 0xFFFFDD55;
+
#if USE(NEW_THEME)
Theme* m_platformTheme; // The platform-specific theme.
#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.cpp
index 4cad9a6c0a6..0c4040af05b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.cpp
@@ -26,9 +26,9 @@
#include "config.h"
#include "core/rendering/RenderThemeChromiumAndroid.h"
-#include "CSSValueKeywords.h"
-#include "InputTypeNames.h"
-#include "UserAgentStyleSheets.h"
+#include "core/CSSValueKeywords.h"
+#include "core/InputTypeNames.h"
+#include "core/UserAgentStyleSheets.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderMediaControls.h"
#include "core/rendering/RenderObject.h"
@@ -38,7 +38,7 @@
#include "platform/graphics/Color.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "public/platform/Platform.h"
-#include "public/platform/default/WebThemeEngine.h"
+#include "public/platform/WebThemeEngine.h"
#include "wtf/StdLibExtras.h"
namespace WebCore {
@@ -58,16 +58,6 @@ RenderThemeChromiumAndroid::~RenderThemeChromiumAndroid()
{
}
-Color RenderThemeChromiumAndroid::systemColor(CSSValueID cssValueId) const
-{
- if (isRunningLayoutTest() && cssValueId == CSSValueButtonface) {
- // Match Linux button color in layout tests.
- static const Color linuxButtonGrayColor(0xffdddddd);
- return linuxButtonGrayColor;
- }
- return RenderTheme::systemColor(cssValueId);
-}
-
String RenderThemeChromiumAndroid::extraMediaControlsStyleSheet()
{
return String(mediaControlsAndroidUserAgentStyleSheet, sizeof(mediaControlsAndroidUserAgentStyleSheet));
@@ -91,11 +81,6 @@ void RenderThemeChromiumAndroid::adjustInnerSpinButtonStyle(RenderStyle* style,
}
}
-bool RenderThemeChromiumAndroid::paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
-{
- return RenderMediaControls::paintMediaControlsPart(MediaOverlayPlayButton, object, paintInfo, rect);
-}
-
int RenderThemeChromiumAndroid::menuListArrowPadding() const
{
// We cannot use the scrollbar thickness here, as it's width is 0 on Android.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.h b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.h
index 93abb212e22..9889dc0b5f5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumAndroid.h
@@ -30,19 +30,15 @@
namespace WebCore {
-class RenderThemeChromiumAndroid : public RenderThemeChromiumDefault {
+class RenderThemeChromiumAndroid FINAL : public RenderThemeChromiumDefault {
public:
static PassRefPtr<RenderTheme> create();
virtual String extraDefaultStyleSheet() OVERRIDE;
- virtual Color systemColor(CSSValueID) const OVERRIDE;
-
virtual void adjustInnerSpinButtonStyle(RenderStyle*, Element*) const OVERRIDE;
virtual bool delegatesMenuListRendering() const OVERRIDE { return true; }
- virtual bool paintMediaOverlayPlayButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
-
virtual String extraMediaControlsStyleSheet() OVERRIDE;
virtual Color platformTapHighlightColor() const OVERRIDE
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.cpp
index de62300e085..3f65622e8fc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.cpp
@@ -25,8 +25,8 @@
#include "config.h"
#include "core/rendering/RenderThemeChromiumDefault.h"
-#include "CSSValueKeywords.h"
-#include "UserAgentStyleSheets.h"
+#include "core/CSSValueKeywords.h"
+#include "core/UserAgentStyleSheets.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/RenderProgress.h"
@@ -34,9 +34,9 @@
#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
-#include "public/platform/default/WebThemeEngine.h"
#include "public/platform/Platform.h"
#include "public/platform/WebRect.h"
+#include "public/platform/WebThemeEngine.h"
#include "wtf/StdLibExtras.h"
namespace WebCore {
@@ -220,11 +220,6 @@ void RenderThemeChromiumDefault::adjustSliderThumbSize(RenderStyle* style, Eleme
RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
}
-bool RenderThemeChromiumDefault::supportsControlTints() const
-{
- return true;
-}
-
void RenderThemeChromiumDefault::setCaretBlinkInterval(double interval)
{
m_caretBlinkInterval = interval;
@@ -249,19 +244,22 @@ void RenderThemeChromiumDefault::setSelectionColors(
bool RenderThemeChromiumDefault::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.button.checked = isChecked(o);
extraParams.button.indeterminate = isIndeterminate(o);
float zoomLevel = o->style()->effectiveZoom();
- GraphicsContextStateSaver stateSaver(*i.context);
+ GraphicsContextStateSaver stateSaver(*i.context, false);
IntRect unzoomedRect = rect;
if (zoomLevel != 1) {
+ stateSaver.save();
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
i.context->translate(unzoomedRect.x(), unzoomedRect.y());
- i.context->scale(FloatSize(zoomLevel, zoomLevel));
+ i.context->scale(zoomLevel, zoomLevel);
i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -284,6 +282,8 @@ void RenderThemeChromiumDefault::setCheckboxSize(RenderStyle* style) const
bool RenderThemeChromiumDefault::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.button.checked = isChecked(o);
@@ -307,6 +307,8 @@ void RenderThemeChromiumDefault::setRadioSize(RenderStyle* style) const
bool RenderThemeChromiumDefault::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.button.hasBorder = true;
@@ -324,6 +326,8 @@ bool RenderThemeChromiumDefault::paintTextField(RenderObject* o, const PaintInfo
// so return true to draw CSS border and background.
if (o->style()->hasBorderRadius() || o->style()->hasBackgroundImage())
return true;
+ if (i.context->paintingDisabled())
+ return false;
ControlPart part = o->style()->appearance();
@@ -333,8 +337,7 @@ bool RenderThemeChromiumDefault::paintTextField(RenderObject* o, const PaintInfo
blink::WebCanvas* canvas = i.context->canvas();
- // Fallback to white if the specified color object is invalid.
- Color backgroundColor = o->resolveColor(CSSPropertyBackgroundColor, Color::white);
+ Color backgroundColor = o->resolveColor(CSSPropertyBackgroundColor);
extraParams.textField.backgroundColor = backgroundColor.rgb();
blink::Platform::current()->themeEngine()->paint(canvas, blink::WebThemeEngine::PartTextField, getWebThemeState(this, o), blink::WebRect(rect), &extraParams);
@@ -343,7 +346,7 @@ bool RenderThemeChromiumDefault::paintTextField(RenderObject* o, const PaintInfo
bool RenderThemeChromiumDefault::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- if (!o->isBox())
+ if (!o->isBox() || i.context->paintingDisabled())
return false;
const int right = rect.x() + rect.width();
@@ -388,7 +391,7 @@ bool RenderThemeChromiumDefault::paintMenuList(RenderObject* o, const PaintInfo&
bool RenderThemeChromiumDefault::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
- if (!o->isBox())
+ if (!o->isBox() || i.context->paintingDisabled())
return false;
const int right = rect.x() + rect.width();
@@ -422,6 +425,8 @@ bool RenderThemeChromiumDefault::paintMenuListButton(RenderObject* o, const Pain
bool RenderThemeChromiumDefault::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.slider.vertical = o->style()->appearance() == SliderVerticalPart;
@@ -430,13 +435,14 @@ bool RenderThemeChromiumDefault::paintSliderTrack(RenderObject* o, const PaintIn
// FIXME: Mock theme doesn't handle zoomed sliders.
float zoomLevel = useMockTheme() ? 1 : o->style()->effectiveZoom();
- GraphicsContextStateSaver stateSaver(*i.context);
+ GraphicsContextStateSaver stateSaver(*i.context, false);
IntRect unzoomedRect = rect;
if (zoomLevel != 1) {
+ stateSaver.save();
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
i.context->translate(unzoomedRect.x(), unzoomedRect.y());
- i.context->scale(FloatSize(zoomLevel, zoomLevel));
+ i.context->scale(zoomLevel, zoomLevel);
i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -447,6 +453,8 @@ bool RenderThemeChromiumDefault::paintSliderTrack(RenderObject* o, const PaintIn
bool RenderThemeChromiumDefault::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
extraParams.slider.vertical = o->style()->appearance() == SliderThumbVerticalPart;
@@ -454,13 +462,14 @@ bool RenderThemeChromiumDefault::paintSliderThumb(RenderObject* o, const PaintIn
// FIXME: Mock theme doesn't handle zoomed sliders.
float zoomLevel = useMockTheme() ? 1 : o->style()->effectiveZoom();
- GraphicsContextStateSaver stateSaver(*i.context);
+ GraphicsContextStateSaver stateSaver(*i.context, false);
IntRect unzoomedRect = rect;
if (zoomLevel != 1) {
+ stateSaver.save();
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
i.context->translate(unzoomedRect.x(), unzoomedRect.y());
- i.context->scale(FloatSize(zoomLevel, zoomLevel));
+ i.context->scale(zoomLevel, zoomLevel);
i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -478,9 +487,11 @@ void RenderThemeChromiumDefault::adjustInnerSpinButtonStyle(RenderStyle* style,
bool RenderThemeChromiumDefault::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
{
+ if (i.context->paintingDisabled())
+ return false;
blink::WebThemeEngine::ExtraParams extraParams;
blink::WebCanvas* canvas = i.context->canvas();
- extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpState);
+ extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpControlState);
extraParams.innerSpin.readOnly = isReadOnlyControl(o);
blink::Platform::current()->themeEngine()->paint(canvas, blink::WebThemeEngine::PartInnerSpinButton, getWebThemeState(this, o), blink::WebRect(rect), &extraParams);
@@ -491,6 +502,8 @@ bool RenderThemeChromiumDefault::paintProgressBar(RenderObject* o, const PaintIn
{
if (!o->isProgress())
return true;
+ if (i.context->paintingDisabled())
+ return false;
RenderProgress* renderProgress = toRenderProgress(o);
IntRect valueRect = progressValueRectFor(renderProgress, rect);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.h b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.h
index 74527e0732d..e69546895ea 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumDefault.h
@@ -36,12 +36,12 @@ namespace WebCore {
class RenderThemeChromiumDefault : public RenderThemeChromiumSkia {
public:
static PassRefPtr<RenderTheme> create();
- virtual String extraDefaultStyleSheet();
+ virtual String extraDefaultStyleSheet() OVERRIDE;
- virtual Color systemColor(CSSValueID) const;
+ virtual Color systemColor(CSSValueID) const OVERRIDE;
// A method asking if the control changes its tint when the window has focus or not.
- virtual bool controlSupportsTints(const RenderObject*) const;
+ virtual bool controlSupportsTints(const RenderObject*) const OVERRIDE;
virtual bool supportsFocusRing(const RenderStyle*) const OVERRIDE;
@@ -51,23 +51,23 @@ public:
virtual Color inactiveListBoxSelectionBackgroundColor() const;
virtual Color inactiveListBoxSelectionForegroundColor() const;
- virtual Color platformActiveSelectionBackgroundColor() const;
- virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color platformActiveSelectionForegroundColor() const;
- virtual Color platformInactiveSelectionForegroundColor() const;
+ virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE;
+ virtual Color platformInactiveSelectionBackgroundColor() const OVERRIDE;
+ virtual Color platformActiveSelectionForegroundColor() const OVERRIDE;
+ virtual Color platformInactiveSelectionForegroundColor() const OVERRIDE;
virtual IntSize sliderTickSize() const OVERRIDE;
virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
- virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbSize(RenderStyle*, Element*) const OVERRIDE;
static void setCaretBlinkInterval(double);
- virtual double caretBlinkIntervalInternal() const;
+ virtual double caretBlinkIntervalInternal() const OVERRIDE;
- virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void setCheckboxSize(RenderStyle*) const;
+ virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual void setCheckboxSize(RenderStyle*) const OVERRIDE;
- virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void setRadioSize(RenderStyle*) const;
+ virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual void setRadioSize(RenderStyle*) const OVERRIDE;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
@@ -76,12 +76,12 @@ public:
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual void adjustInnerSpinButtonStyle(RenderStyle*, Element*) const;
- virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustInnerSpinButtonStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool popsMenuBySpaceOrReturn() const OVERRIDE { return true; }
+ virtual bool popsMenuBySpaceOrReturn() const OVERRIDE FINAL { return true; }
- virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
virtual bool shouldOpenPickerWithF4Key() const OVERRIDE;
@@ -93,9 +93,6 @@ protected:
virtual bool shouldUseFallbackTheme(RenderStyle*) const OVERRIDE;
private:
- // A general method asking if any control tinting is supported at all.
- virtual bool supportsControlTints() const;
-
static double m_caretBlinkInterval;
static unsigned m_activeSelectionBackgroundColor;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.cpp
index 527f8558f78..b8083e015fe 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.cpp
@@ -46,9 +46,9 @@ float RenderThemeChromiumFontProvider::s_defaultFontSize = 16.0;
// FIXME: The only case where we know we don't match IE is for ANSI encodings.
// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
// sizes (e.g. 15px). So, for now we just use Arial.
-const String& RenderThemeChromiumFontProvider::defaultGUIFont()
+const AtomicString& RenderThemeChromiumFontProvider::defaultGUIFont()
{
- DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
+ DEFINE_STATIC_LOCAL(const AtomicString, fontFace, ("Arial", AtomicString::ConstructFromLiteral));
return fontFace;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.h b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.h
index 57589c2a397..e31322461b2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProvider.h
@@ -26,11 +26,7 @@
#ifndef RenderThemeChromiumFontProvider_h
#define RenderThemeChromiumFontProvider_h
-#include "CSSValueKeywords.h"
-
-namespace WTF {
-class String;
-}
+#include "core/CSSValueKeywords.h"
namespace WebCore {
@@ -42,7 +38,7 @@ public:
static void setDefaultFontSize(int);
protected:
- static const WTF::String& defaultGUIFont();
+ static const WTF::AtomicString& defaultGUIFont();
static float s_defaultFontSize;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp
index 3d1d0260d0a..35e16714738 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "core/rendering/RenderThemeChromiumFontProvider.h"
-#include "CSSValueKeywords.h"
+#include "core/CSSValueKeywords.h"
#include "platform/fonts/FontDescription.h"
#include "wtf/StdLibExtras.h"
@@ -65,7 +65,7 @@ void RenderThemeChromiumFontProvider::systemFont(CSSValueID valueID, FontDescrip
fontDescription.setIsAbsoluteSize(true);
fontDescription.setGenericFamily(FontDescription::NoFamily);
fontDescription.setWeight(FontWeightNormal);
- fontDescription.setItalic(false);
+ fontDescription.setStyle(FontStyleNormal);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp
index 18305cc31d6..0db04403219 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp
@@ -26,13 +26,12 @@
#include "config.h"
#include "core/rendering/RenderThemeChromiumFontProvider.h"
-#include <windows.h>
-
-#include "CSSValueKeywords.h"
+#include "core/CSSValueKeywords.h"
#include "platform/fonts/FontDescription.h"
#include "platform/win/HWndDC.h"
#include "platform/win/SystemInfo.h"
#include "wtf/text/WTFString.h"
+#include <windows.h>
#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
offsetof(structName, member) + \
@@ -175,7 +174,7 @@ void RenderThemeChromiumFontProvider::systemFont(CSSValueID valueID, FontDescrip
cachedDesc->setGenericFamily(FontDescription::NoFamily);
cachedDesc->setSpecifiedSize(fontSize);
cachedDesc->setWeight(FontWeightNormal);
- cachedDesc->setItalic(false);
+ cachedDesc->setStyle(FontStyleNormal);
}
fontDescription = *cachedDesc;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.h b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.h
index 371ecc6c717..3dc8de4841d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.h
@@ -32,7 +32,7 @@ OBJC_CLASS WebCoreRenderThemeNotificationObserver;
namespace WebCore {
-class RenderThemeChromiumMac : public RenderTheme {
+class RenderThemeChromiumMac FINAL : public RenderTheme {
public:
static PassRefPtr<RenderTheme> create();
@@ -44,10 +44,11 @@ public:
virtual void adjustRepaintRect(const RenderObject*, IntRect&) OVERRIDE;
- virtual bool isControlStyled(const RenderStyle*, const CachedUAStyle&) const OVERRIDE;
+ virtual bool isControlStyled(const RenderStyle*, const CachedUAStyle*) const OVERRIDE;
virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE;
virtual Color platformInactiveSelectionBackgroundColor() const OVERRIDE;
+ virtual Color platformActiveSelectionForegroundColor() const OVERRIDE;
virtual Color platformActiveListBoxSelectionBackgroundColor() const OVERRIDE;
virtual Color platformActiveListBoxSelectionForegroundColor() const OVERRIDE;
virtual Color platformInactiveListBoxSelectionBackgroundColor() const OVERRIDE;
@@ -88,41 +89,39 @@ public:
virtual Color systemColor(CSSValueID) const OVERRIDE;
+ virtual bool supportsSelectionForegroundColors() const OVERRIDE { return false; }
+
protected:
RenderThemeChromiumMac();
virtual ~RenderThemeChromiumMac();
- virtual bool supportsSelectionForegroundColors() const OVERRIDE { return false; }
-
- virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
-
- virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListStyle(RenderStyle*, Element*) const;
+ virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(RenderStyle*, Element*) const;
+ virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual void adjustMenuListStyle(RenderStyle*, Element*) const OVERRIDE;
- virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual void adjustMenuListButtonStyle(RenderStyle*, Element*) const OVERRIDE;
- virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(RenderStyle*, Element*) const;
+ virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual void adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const;
- virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual void adjustSearchFieldStyle(RenderStyle*, Element*) const OVERRIDE;
- virtual void adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const;
- virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual void adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool supportsClosedCaptioning() const { return true; }
+ virtual void adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
private:
virtual String fileListNameForWidth(Locale&, const FileList*, const Font&, int width) const OVERRIDE;
@@ -151,7 +150,6 @@ private:
const IntSize* popupButtonSizes() const;
const int* popupButtonMargins() const;
const int* popupButtonPadding(NSControlSize) const;
- void paintMenuListButtonGradients(RenderObject*, const PaintInfo&, const IntRect&);
const IntSize* menuListSizes() const;
const IntSize* searchFieldSizes() const;
@@ -174,21 +172,20 @@ private:
protected:
virtual void adjustMediaSliderThumbSize(RenderStyle*) const;
- virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual String extraFullScreenStyleSheet();
-
- virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- 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 bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
- virtual bool usesVerticalVolumeSlider() const { return false; }
- virtual String formatMediaControlsTime(float time) const;
- virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
- virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaOverlayPlayButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual String extraFullScreenStyleSheet() OVERRIDE;
+
+ virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual String formatMediaControlsTime(float time) const OVERRIDE;
+ virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const OVERRIDE;
+ virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
// Controls color values returned from platformFocusRingColor(). systemColor() will be used when false.
bool usesTestModeFocusRingColor() const;
@@ -199,7 +196,7 @@ protected:
private:
virtual void updateActiveState(NSCell*, const RenderObject*);
- virtual String extraDefaultStyleSheet();
+ virtual String extraDefaultStyleSheet() OVERRIDE;
virtual bool shouldShowPlaceholderWhenFocused() const OVERRIDE;
mutable RetainPtr<NSPopUpButtonCell> m_popupButton;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm
index 82f39e25601..a25be5a7c89 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm
@@ -34,7 +34,6 @@
#import "core/html/TimeRanges.h"
#import "core/html/shadow/MediaControlElements.h"
#import "core/frame/FrameView.h"
-#import "core/platform/mac/ThemeMac.h"
#import "core/rendering/PaintInfo.h"
#import "core/rendering/RenderLayer.h"
#import "core/rendering/RenderMedia.h"
@@ -50,9 +49,9 @@
#import "platform/graphics/GraphicsContextStateSaver.h"
#import "platform/graphics/Image.h"
#import "platform/graphics/ImageBuffer.h"
-#import "platform/graphics/cg/GraphicsContextCG.h"
#import "platform/mac/ColorMac.h"
#import "platform/mac/LocalCurrentGraphicsContext.h"
+#import "platform/mac/ThemeMac.h"
#import "platform/mac/WebCoreNSCellExtras.h"
#import "platform/text/PlatformLocale.h"
#import "platform/text/StringTruncator.h"
@@ -194,6 +193,11 @@ Color RenderThemeChromiumMac::platformInactiveSelectionBackgroundColor() const
return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
}
+Color RenderThemeChromiumMac::platformActiveSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
Color RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() const
{
NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
@@ -212,8 +216,9 @@ Color RenderThemeChromiumMac::platformInactiveListBoxSelectionForegroundColor()
Color RenderThemeChromiumMac::platformFocusRingColor() const
{
+ static const RGBA32 oldAquaFocusRingColor = 0xFF7DADD9;
if (usesTestModeFocusRingColor())
- return oldAquaFocusRingColor();
+ return oldAquaFocusRingColor;
return systemColor(CSSValueWebkitFocusRingColor);
}
@@ -306,7 +311,7 @@ void RenderThemeChromiumMac::systemFont(CSSValueID cssValueId, FontDescription&
cachedDesc->firstFamily().setFamily([font webCoreFamilyName]);
cachedDesc->setSpecifiedSize([font pointSize]);
cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
- cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
+ cachedDesc->setStyle([fontManager traitsOfFont:font] & NSItalicFontMask ? FontStyleItalic : FontStyleNormal);
}
fontDescription = *cachedDesc;
}
@@ -394,6 +399,7 @@ Color RenderThemeChromiumMac::systemColor(CSSValueID cssValueId) const
}
Color color;
+ bool needsFallback = false;
switch (cssValueId) {
case CSSValueActiveborder:
color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
@@ -406,6 +412,7 @@ Color RenderThemeChromiumMac::systemColor(CSSValueID cssValueId) const
break;
case CSSValueBackground:
// Use theme independent default
+ needsFallback = true;
break;
case CSSValueButtonface:
// We use this value instead of NSColor's controlColor to avoid website incompatibilities.
@@ -491,22 +498,23 @@ Color RenderThemeChromiumMac::systemColor(CSSValueID cssValueId) const
color = convertNSColorToColor([NSColor windowFrameTextColor]);
break;
default:
+ needsFallback = true;
break;
}
- if (!color.isValid())
+ if (needsFallback)
color = RenderTheme::systemColor(cssValueId);
- if (color.isValid())
- m_systemColorCache.set(cssValueId, color.rgb());
+ m_systemColorCache.set(cssValueId, color.rgb());
return color;
}
-bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const CachedUAStyle& uaStyle) const
+bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const CachedUAStyle* uaStyle) const
{
+ ASSERT(uaStyle);
if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
- return style->border() != uaStyle.border || style->boxShadow();
+ return style->border() != uaStyle->border || style->boxShadow();
// FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
// scaled. They can't really draw properly when transformed either. We can't detect the transform case at style
@@ -733,7 +741,7 @@ void RenderThemeChromiumMac::setFontFromControlSize(RenderStyle* style, NSContro
style->setLineHeight(RenderStyle::initialLineHeight());
if (style->setFontDescription(fontDescription))
- style->font().update(0);
+ style->font().update(nullptr);
}
NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* style) const
@@ -903,7 +911,7 @@ bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const PaintInfo& pai
inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->scale(zoomLevel, zoomLevel);
paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
}
@@ -1096,10 +1104,11 @@ bool RenderThemeChromiumMac::paintProgressBar(RenderObject* renderObject, const
if (!renderProgress->style()->isLeftToRightDirection()) {
paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0);
- paintInfo.context->scale(FloatSize(-1, 1));
+ paintInfo.context->scale(-1, 1);
}
- paintInfo.context->drawImageBuffer(imageBuffer.get(), inflatedRect.location());
+ paintInfo.context->drawImageBuffer(imageBuffer.get(),
+ FloatRect(inflatedRect.location(), imageBuffer->size()));
return false;
}
@@ -1115,112 +1124,12 @@ const int styledPopupPaddingLeft = 8;
const int styledPopupPaddingTop = 1;
const int styledPopupPaddingBottom = 2;
-static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
- static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
- static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
- static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- if (r.isEmpty())
- return;
-
- ContextContainer cgContextContainer(paintInfo.context);
- CGContextRef context = cgContextContainer.context();
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- RoundedRect border = o->style()->getRoundedBorderFor(r, o->view());
- int radius = border.radii().topLeft().width();
-
- CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
-
- FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
- struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
- RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), topFunction.get(), false, false));
-
- FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
- struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
- RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), bottomFunction.get(), false, false));
-
- struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
- RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false));
-
- RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
-
- RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.maxX(), r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false));
-
- {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, r);
- paintInfo.context->clipRoundedRect(border);
- context = cgContextContainer.context();
- CGContextDrawShading(context, mainShading.get());
- }
-
- {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, topGradient);
- paintInfo.context->clipRoundedRect(RoundedRect(enclosingIntRect(topGradient), border.radii().topLeft(), border.radii().topRight(), IntSize(), IntSize()));
- context = cgContextContainer.context();
- CGContextDrawShading(context, topShading.get());
- }
-
- if (!bottomGradient.isEmpty()) {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, bottomGradient);
- paintInfo.context->clipRoundedRect(RoundedRect(enclosingIntRect(bottomGradient), IntSize(), IntSize(), border.radii().bottomLeft(), border.radii().bottomRight()));
- context = cgContextContainer.context();
- CGContextDrawShading(context, bottomShading.get());
- }
-
- {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, r);
- paintInfo.context->clipRoundedRect(border);
- context = cgContextContainer.context();
- CGContextDrawShading(context, leftShading.get());
- CGContextDrawShading(context, rightShading.get());
- }
-}
-
bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
r.y() + o->style()->borderTopWidth(),
r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
- // Draw the gradients to give the styled popup menu a button appearance
- paintMenuListButtonGradients(o, paintInfo, bounds);
-
// Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
float centerY = bounds.y() + bounds.height() / 2.0f;
@@ -1252,24 +1161,6 @@ bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const PaintInf
// Draw the bottom arrow
paintInfo.context->drawConvexPolygon(3, arrow2, true);
-
- Color leftSeparatorColor(0, 0, 0, 40);
- Color rightSeparatorColor(255, 255, 255, 40);
-
- // FIXME: Should the separator thickness and space be scaled up by fontScale?
- int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
- int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
-
- // Draw the separator to the left of the arrows
- paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
- paintInfo.context->setStrokeStyle(SolidStroke);
- paintInfo.context->setStrokeColor(leftSeparatorColor);
- paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
- IntPoint(leftEdgeOfSeparator, bounds.maxY()));
-
- paintInfo.context->setStrokeColor(rightSeparatorColor);
- paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
- IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
return false;
}
@@ -1423,7 +1314,7 @@ bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const PaintInfo&
GraphicsContextStateSaver stateSaver(*paintInfo.context);
if (zoomLevel != 1) {
paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->scale(zoomLevel, zoomLevel);
paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -1488,7 +1379,7 @@ bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const PaintInfo&
FloatRect unzoomedRect(r.x(), r.y(), sliderThumbWidth, sliderThumbHeight);
if (zoomLevel != 1.0f) {
paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->scale(zoomLevel, zoomLevel);
paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -1573,7 +1464,7 @@ bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const PaintInfo&
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->scale(zoomLevel, zoomLevel);
paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -1656,6 +1547,8 @@ void RenderThemeChromiumMac::adjustSearchFieldStyle(RenderStyle* style, Element*
bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
+ if (!o->node())
+ return false;
Element* input = o->node()->shadowHost();
if (!input)
input = toElement(o->node());
@@ -1671,7 +1564,7 @@ bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->scale(zoomLevel, zoomLevel);
paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -1754,6 +1647,8 @@ void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(RenderStyle
bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
+ if (!o->node())
+ return false;
Node* input = o->node()->shadowHost();
if (!input)
input = o->node();
@@ -1768,7 +1663,7 @@ bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o,
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->scale(zoomLevel, zoomLevel);
paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
@@ -1940,6 +1835,11 @@ bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const Pa
return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
}
+bool RenderThemeChromiumMac::paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaOverlayPlayButton, object, paintInfo, rect);
+}
+
bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
@@ -1959,7 +1859,8 @@ String RenderThemeChromiumMac::extraFullScreenStyleSheet()
String RenderThemeChromiumMac::extraDefaultStyleSheet()
{
return RenderTheme::extraDefaultStyleSheet() +
- String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet));
+ String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet)) +
+ String(themeMacUserAgentStyleSheet, sizeof(themeMacUserAgentStyleSheet));
}
bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.cpp
index 2a7e3c2b232..f836738a38c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.cpp
@@ -24,7 +24,7 @@
#include "config.h"
#include "core/rendering/RenderThemeChromiumSkia.h"
-#include "UserAgentStyleSheets.h"
+#include "core/UserAgentStyleSheets.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderBox.h"
#include "core/rendering/RenderMediaControls.h"
@@ -91,11 +91,6 @@ bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
return false;
}
-bool RenderThemeChromiumSkia::supportsClosedCaptioning() const
-{
- return true;
-}
-
Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
{
return Color(0x1e, 0x90, 0xff);
@@ -227,6 +222,8 @@ IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRender
bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
{
// Get the renderer of <input> element.
+ if (!cancelButtonObject->node())
+ return false;
Node* input = cancelButtonObject->node()->shadowHost();
RenderObject* baseRenderer = input ? input->renderer() : cancelButtonObject;
if (!baseRenderer->isBox())
@@ -270,6 +267,8 @@ void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(RenderStyl
bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
{
// Get the renderer of <input> element.
+ if (!magnifierObject->node())
+ return false;
Node* input = magnifierObject->node()->shadowHost();
RenderObject* baseRenderer = input ? input->renderer() : magnifierObject;
if (!baseRenderer->isBox())
@@ -327,6 +326,11 @@ bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const P
return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
}
+bool RenderThemeChromiumSkia::paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaOverlayPlayButton, object, paintInfo, rect);
+}
+
bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
@@ -473,7 +477,7 @@ RenderThemeChromiumSkia::DirectionFlippingScope::DirectionFlippingScope(RenderOb
return;
m_paintInfo.context->save();
m_paintInfo.context->translate(2 * rect.x() + rect.width(), 0);
- m_paintInfo.context->scale(FloatSize(-1, 1));
+ m_paintInfo.context->scale(-1, 1);
}
RenderThemeChromiumSkia::DirectionFlippingScope::~DirectionFlippingScope()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.h b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.h
index f3550c7aca0..c47eff77872 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumSkia.h
@@ -39,8 +39,8 @@ public:
RenderThemeChromiumSkia();
virtual ~RenderThemeChromiumSkia();
- virtual String extraDefaultStyleSheet();
- virtual String extraQuirksStyleSheet();
+ virtual String extraDefaultStyleSheet() OVERRIDE;
+ virtual String extraQuirksStyleSheet() OVERRIDE;
virtual Color platformTapHighlightColor() const OVERRIDE
{
@@ -48,57 +48,57 @@ public:
}
// A method asking if the theme's controls actually care about redrawing when hovered.
- virtual bool supportsHover(const RenderStyle*) const;
+ virtual bool supportsHover(const RenderStyle*) const OVERRIDE FINAL;
// A method asking if the theme is able to draw the focus ring.
- virtual bool supportsFocusRing(const RenderStyle*) const;
+ virtual bool supportsFocusRing(const RenderStyle*) const OVERRIDE;
- virtual bool supportsClosedCaptioning() const OVERRIDE;
// The platform selection color.
- virtual Color platformActiveSelectionBackgroundColor() const;
- virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color platformActiveSelectionForegroundColor() const;
- virtual Color platformInactiveSelectionForegroundColor() const;
- virtual Color platformFocusRingColor() const;
+ virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE;
+ virtual Color platformInactiveSelectionBackgroundColor() const OVERRIDE;
+ virtual Color platformActiveSelectionForegroundColor() const OVERRIDE;
+ virtual Color platformInactiveSelectionForegroundColor() const OVERRIDE;
+ virtual Color platformFocusRingColor() const OVERRIDE;
// To change the blink interval, override caretBlinkIntervalInternal instead of this one so that we may share layout test code an intercepts.
- virtual double caretBlinkInterval() const;
+ virtual double caretBlinkInterval() const OVERRIDE;
// System fonts.
- virtual void systemFont(CSSValueID, FontDescription&) const;
+ virtual void systemFont(CSSValueID, FontDescription&) const OVERRIDE;
- virtual int minimumMenuListSize(RenderStyle*) const;
+ virtual int minimumMenuListSize(RenderStyle*) const OVERRIDE;
- virtual void setCheckboxSize(RenderStyle*) const;
+ virtual void setCheckboxSize(RenderStyle*) const OVERRIDE;
- virtual void setRadioSize(RenderStyle*) const;
+ virtual void setRadioSize(RenderStyle*) const OVERRIDE;
- virtual void adjustButtonStyle(RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(RenderStyle*, Element*) const OVERRIDE;
- virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual void adjustSearchFieldStyle(RenderStyle*, Element*) const;
- virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual void adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const;
- virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual void adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const OVERRIDE;
- virtual void adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
- virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual String formatMediaControlsTime(float time) const;
- virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
- virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual void adjustSliderThumbSize(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaOverlayPlayButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+ virtual String formatMediaControlsTime(float time) const OVERRIDE;
+ virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const OVERRIDE;
+ virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
// MenuList refers to an unstyled menulist (meaning a menulist without
// background-color or border set) and MenuListButton refers to a styled
@@ -109,22 +109,18 @@ public:
// 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(RenderStyle*, Element*) const;
- virtual void adjustMenuListButtonStyle(RenderStyle*, Element*) const;
- virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustMenuListStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual void adjustMenuListButtonStyle(RenderStyle*, Element*) const OVERRIDE;
+ virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
- virtual double animationDurationForProgressBar(RenderProgress*) const;
+ virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const OVERRIDE;
+ virtual double animationDurationForProgressBar(RenderProgress*) const OVERRIDE;
// These methods define the padding for the MenuList's inner block.
- virtual int popupInternalPaddingLeft(RenderStyle*) const;
- virtual int popupInternalPaddingRight(RenderStyle*) const;
- virtual int popupInternalPaddingTop(RenderStyle*) const;
- virtual int popupInternalPaddingBottom(RenderStyle*) const;
-
- // Media controls
- virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
- virtual bool usesVerticalVolumeSlider() const { return false; }
+ virtual int popupInternalPaddingLeft(RenderStyle*) const OVERRIDE;
+ virtual int popupInternalPaddingRight(RenderStyle*) const OVERRIDE;
+ virtual int popupInternalPaddingTop(RenderStyle*) const OVERRIDE;
+ virtual int popupInternalPaddingBottom(RenderStyle*) const OVERRIDE;
// Provide a way to pass the default font size from the Settings object
// to the render theme. FIXME: http://b/1129186 A cleaner way would be
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.cpp
deleted file mode 100644
index b1224074607..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.cpp
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * This file is part of the WebKit project.
- *
- * Copyright (C) 2006 Apple Computer, Inc.
- * Copyright (C) 2008, 2009 Google, Inc.
- * Copyright (C) 2009 Kenneth Rohde Christiansen
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#include "config.h"
-#include "core/rendering/RenderThemeChromiumWin.h"
-
-#include <windows.h>
-#include <uxtheme.h>
-#include <vssym32.h>
-
-#include "CSSValueKeywords.h"
-#include "HTMLNames.h"
-#include "core/html/HTMLMediaElement.h"
-#include "core/html/shadow/MediaControlElements.h"
-#include "core/rendering/PaintInfo.h"
-#include "core/rendering/RenderBox.h"
-#include "core/rendering/RenderProgress.h"
-#include "core/rendering/RenderSlider.h"
-#include "platform/LayoutTestSupport.h"
-#include "platform/fonts/FontSelector.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/win/TransparencyWin.h"
-#include "platform/scroll/ScrollbarTheme.h"
-#include "platform/win/SystemInfo.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebColor.h"
-#include "public/platform/WebRect.h"
-#include "public/platform/win/WebThemeEngine.h"
-#include "wtf/CurrentTime.h"
-#include "wtf/StdLibExtras.h"
-
-// FIXME: This dependency should eventually be removed.
-#include <skia/ext/skia_utils_win.h>
-
-namespace WebCore {
-
-// The standard width for the menu list drop-down button when run under
-// layout test mode. Use the value that's currently captured in most baselines.
-static const int kStandardMenuListButtonWidth = 17;
-
-namespace {
-// We must not create multiple ThemePainter instances.
-class ThemePainter {
-public:
- ThemePainter(GraphicsContext* context, const IntRect& r)
- {
-#ifndef NDEBUG
- ASSERT(!s_hasInstance);
- s_hasInstance = true;
-#endif
- TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM());
- m_helper.init(context, getLayerMode(context, transformMode), transformMode, r);
-
- if (!m_helper.context()) {
- // TransparencyWin doesn't have well-defined copy-ctor nor op=()
- // so we re-initialize it instead of assigning a fresh istance.
- // On the reinitialization, we fallback to use NoLayer mode.
- // Note that the original initialization failure can be caused by
- // a failure of an internal buffer allocation and NoLayer mode
- // does not have such buffer allocations.
- m_helper.~TransparencyWin();
- new (&m_helper) TransparencyWin();
- m_helper.init(context, TransparencyWin::NoLayer, transformMode, r);
- }
- }
-
- ~ThemePainter()
- {
- m_helper.composite();
-#ifndef NDEBUG
- s_hasInstance = false;
-#endif
- }
-
- GraphicsContext* context() { return m_helper.context(); }
- const IntRect& drawRect() { return m_helper.drawRect(); }
-
-private:
-
- static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode)
- {
- if (!context->isCertainlyOpaque()) // Might have transparent background.
- return TransparencyWin::WhiteLayer;
- if (context->canvas()->isDrawingToLayer()) // Needs antialiasing help.
- return TransparencyWin::OpaqueCompositeLayer;
- // Nothing interesting.
- return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer;
- }
-
- static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix)
- {
- if (matrix.b() || matrix.c()) // Skew.
- return TransparencyWin::Untransform;
- if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
- return TransparencyWin::ScaleTransform;
- // Nothing interesting.
- return TransparencyWin::KeepTransform;
- }
-
- TransparencyWin m_helper;
-#ifndef NDEBUG
- static bool s_hasInstance;
-#endif
-};
-
-#ifndef NDEBUG
-bool ThemePainter::s_hasInstance = false;
-#endif
-
-} // namespace
-
-// Internal static helper functions. We don't put them in an anonymous
-// namespace so they have easier access to the WebCore namespace.
-
-static bool supportsFocus(ControlPart appearance)
-{
- switch (appearance) {
- case SquareButtonPart:
- case PushButtonPart:
- case ButtonPart:
- case SearchFieldPart:
- case TextFieldPart:
- case TextAreaPart:
- return true;
- }
- return false;
-}
-
-static double querySystemBlinkInterval(double defaultInterval)
-{
- UINT blinkTime = GetCaretBlinkTime();
- if (!blinkTime)
- return defaultInterval;
- if (blinkTime == INFINITE)
- return 0;
- return blinkTime / 1000.0;
-}
-
-PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
-{
- return adoptRef(new RenderThemeChromiumWin);
-}
-
-RenderTheme& RenderTheme::theme()
-{
- DEFINE_STATIC_REF(RenderTheme, renderTheme, (RenderThemeChromiumWin::create()));
- return *renderTheme;
-}
-
-bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
-{
- // Let webkit draw one of its halo rings around any focused element,
- // except push buttons. For buttons we use the windows PBS_DEFAULTED
- // styling to give it a blue border.
- return style->appearance() == ButtonPart
- || style->appearance() == PushButtonPart
- || style->appearance() == SquareButtonPart;
-}
-
-Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
-{
- if (isRunningLayoutTest())
- return Color(0x00, 0x00, 0xff); // Royal blue.
- COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
-}
-
-Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
-{
- if (isRunningLayoutTest())
- return Color(0x99, 0x99, 0x99); // Medium gray.
- COLORREF color = GetSysColor(COLOR_GRAYTEXT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
-}
-
-Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
-{
- if (isRunningLayoutTest())
- return Color(0xff, 0xff, 0xcc); // Pale yellow.
- COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
-}
-
-Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
-{
- return Color::white;
-}
-
-Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
-{
- return Color(0xff, 0x96, 0x32); // Orange.
-}
-
-Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
-{
- return Color(0xff, 0xff, 0x96); // Yellow.
-}
-
-// Map a CSSValue* system color to an index understood by GetSysColor().
-static int cssValueIdToSysColorIndex(int cssValueId)
-{
- switch (cssValueId) {
- case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
- case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
- case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
- case CSSValueBackground: return COLOR_BACKGROUND;
- case CSSValueButtonface: return COLOR_BTNFACE;
- case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
- case CSSValueButtonshadow: return COLOR_BTNSHADOW;
- case CSSValueButtontext: return COLOR_BTNTEXT;
- case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
- case CSSValueGraytext: return COLOR_GRAYTEXT;
- case CSSValueHighlight: return COLOR_HIGHLIGHT;
- case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
- case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
- case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
- case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
- case CSSValueInfobackground: return COLOR_INFOBK;
- case CSSValueInfotext: return COLOR_INFOTEXT;
- case CSSValueMenu: return COLOR_MENU;
- case CSSValueMenutext: return COLOR_MENUTEXT;
- case CSSValueScrollbar: return COLOR_SCROLLBAR;
- case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
- case CSSValueThreedface: return COLOR_3DFACE;
- case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
- case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
- case CSSValueThreedshadow: return COLOR_3DSHADOW;
- case CSSValueWindow: return COLOR_WINDOW;
- case CSSValueWindowframe: return COLOR_WINDOWFRAME;
- case CSSValueWindowtext: return COLOR_WINDOWTEXT;
- default: return -1; // Unsupported CSSValue
- }
-}
-
-Color RenderThemeChromiumWin::systemColor(CSSValueID cssValueId) const
-{
- int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
- if (isRunningLayoutTest() || (sysColorIndex == -1))
- return RenderTheme::systemColor(cssValueId);
-
- COLORREF color = GetSysColor(sysColorIndex);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color));
-}
-
-IntSize RenderThemeChromiumWin::sliderTickSize() const
-{
- return IntSize(1, 3);
-}
-
-int RenderThemeChromiumWin::sliderTickOffsetFromTrackCenter() const
-{
- return 11;
-}
-
-void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style, Element* element) const
-{
- // These sizes match what WinXP draws for various menus.
- const int sliderThumbAlongAxis = 11;
- const int sliderThumbAcrossAxis = 21;
- if (style->appearance() == SliderThumbHorizontalPart) {
- style->setWidth(Length(sliderThumbAlongAxis, Fixed));
- style->setHeight(Length(sliderThumbAcrossAxis, Fixed));
- } else if (style->appearance() == SliderThumbVerticalPart) {
- style->setWidth(Length(sliderThumbAcrossAxis, Fixed));
- style->setHeight(Length(sliderThumbAlongAxis, Fixed));
- } else
- RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
-}
-
-bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- return paintButton(o, i, r);
-}
-bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- return paintButton(o, i, r);
-}
-
-bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- const ThemeData& themeData = getThemeData(o);
-
- ThemePainter painter(i.context, r);
- blink::WebCanvas* canvas = painter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintButton(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect()));
- return false;
-}
-
-bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- return paintTextFieldInternal(o, i, r, true);
-}
-
-bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- const ThemeData& themeData = getThemeData(o);
-
- ThemePainter painter(i.context, r);
- blink::WebCanvas* canvas = painter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect()));
-
- paintSliderTicks(o, i, r);
-
- return false;
-}
-
-bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- const ThemeData& themeData = getThemeData(o);
-
- ThemePainter painter(i.context, r);
- blink::WebCanvas* canvas = painter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect()));
-
- return false;
-}
-
-static int menuListButtonWidth()
-{
- static int width = isRunningLayoutTest() ? kStandardMenuListButtonWidth :
- IntSize(blink::Platform::current()->themeEngine()->getSize(SBP_ARROWBTN)).width();
- return width;
-}
-
-// Used to paint unstyled menulists (i.e. with the default border)
-bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- if (!o->isBox())
- return false;
-
- const RenderBox* box = toRenderBox(o);
- int borderRight = box->borderRight();
- int borderLeft = box->borderLeft();
- int borderTop = box->borderTop();
- int borderBottom = box->borderBottom();
-
- // If all the borders are 0, then tell skia not to paint the border on the
- // textfield. FIXME: http://b/1210017 Figure out how to get Windows to not
- // draw individual borders and then pass that to skia so we can avoid
- // drawing any borders that are set to 0. For non-zero borders, we draw the
- // border, but webkit just draws over it.
- bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom);
-
- paintTextFieldInternal(o, i, r, drawEdges);
- return paintMenuListButton(o, i, r);
-}
-
-bool RenderThemeChromiumWin::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- if (!o->isBox())
- return false;
-
- const RenderBox* box = toRenderBox(o);
- // Take padding and border into account. If the MenuList is smaller than
- // the size of a button, make sure to shrink it appropriately and not put
- // its x position to the left of the menulist.
- const int buttonWidth = menuListButtonWidth();
- int spacingLeft = box->borderLeft() + box->paddingLeft();
- int spacingRight = box->borderRight() + box->paddingRight();
- int spacingTop = box->borderTop() + box->paddingTop();
- int spacingBottom = box->borderBottom() + box->paddingBottom();
-
- int buttonX;
- if (r.maxX() - r.x() < buttonWidth)
- buttonX = r.x();
- else
- buttonX = o->style()->direction() == LTR ? r.maxX() - spacingRight - buttonWidth : r.x() + spacingLeft;
-
- // Compute the rectangle of the button in the destination image.
- IntRect rect(buttonX,
- r.y() + spacingTop,
- std::min(buttonWidth, r.maxX() - r.x()),
- r.height() - (spacingTop + spacingBottom));
-
- // Get the correct theme data for a textfield and paint the menu.
- ThemePainter painter(i.context, rect);
- blink::WebCanvas* canvas = painter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintMenuList(canvas, CP_DROPDOWNBUTTON, determineState(o), determineClassicState(o), blink::WebRect(painter.drawRect()));
- return false;
-}
-
-double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
-{
- // This involves a system call, so we cache the result.
- static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
- return blinkInterval;
-}
-
-unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart)
-{
- unsigned result = TS_NORMAL;
- ControlPart appearance = o->style()->appearance();
- if (!isEnabled(o))
- result = TS_DISABLED;
- else if (isReadOnlyControl(o))
- result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED;
- // Active overrides hover and focused.
- else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
- result = TS_PRESSED;
- else if (supportsFocus(appearance) && isFocused(o))
- result = ETS_FOCUSED;
- else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
- result = TS_HOT;
-
- // CBS_UNCHECKED*: 1-4
- // CBS_CHECKED*: 5-8
- // CBS_MIXED*: 9-12
- if (isIndeterminate(o))
- result += 8;
- else if (isChecked(o))
- result += 4;
- return result;
-}
-
-unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
-{
- unsigned result = TUS_NORMAL;
- if (!isEnabled(o))
- result = TUS_DISABLED;
- else if (supportsFocus(o->style()->appearance()) && isFocused(o))
- result = TUS_FOCUSED;
- else if (isPressed(o))
- result = TUS_PRESSED;
- else if (isHovered(o))
- result = TUS_HOT;
- return result;
-}
-
-unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart)
-{
- unsigned result = 0;
-
- ControlPart part = o->style()->appearance();
-
- // Sliders are always in the normal state.
- if (part == SliderHorizontalPart || part == SliderVerticalPart)
- return result;
-
- // So are readonly text fields.
- if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart))
- return result;
-
- if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
- if (!isEnabled(o))
- result = DFCS_INACTIVE;
- else if (isPressed(o)) // Active supersedes hover
- result = DFCS_PUSHED;
- else if (isHovered(o))
- result = DFCS_HOT;
- } else {
- if (!isEnabled(o) || isReadOnlyControl(o))
- result = DFCS_INACTIVE;
- // Active supersedes hover
- else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
- result = DFCS_PUSHED;
- else if (supportsFocus(part) && isFocused(o)) // So does focused
- result = 0;
- else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
- result = DFCS_HOT;
- // Classic theme can't represent indeterminate states. Use unchecked appearance.
- if (isChecked(o) && !isIndeterminate(o))
- result |= DFCS_CHECKED;
- }
- return result;
-}
-
-ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart)
-{
- ThemeData result;
- switch (o->style()->appearance()) {
- case CheckboxPart:
- result.m_part = BP_CHECKBOX;
- result.m_state = determineState(o);
- result.m_classicState = DFCS_BUTTONCHECK;
- break;
- case RadioPart:
- result.m_part = BP_RADIOBUTTON;
- result.m_state = determineState(o);
- result.m_classicState = DFCS_BUTTONRADIO;
- break;
- case SquareButtonPart:
- case PushButtonPart:
- case ButtonPart:
- result.m_part = BP_PUSHBUTTON;
- result.m_state = determineState(o);
- result.m_classicState = DFCS_BUTTONPUSH;
- break;
- case SliderHorizontalPart:
- result.m_part = TKP_TRACK;
- result.m_state = TRS_NORMAL;
- break;
- case SliderVerticalPart:
- result.m_part = TKP_TRACKVERT;
- result.m_state = TRVS_NORMAL;
- break;
- case SliderThumbHorizontalPart:
- result.m_part = TKP_THUMBBOTTOM;
- result.m_state = determineSliderThumbState(o);
- break;
- case SliderThumbVerticalPart:
- result.m_part = TKP_THUMBVERT;
- result.m_state = determineSliderThumbState(o);
- break;
- case ListboxPart:
- case MenulistPart:
- case MenulistButtonPart:
- case SearchFieldPart:
- case TextFieldPart:
- case TextAreaPart:
- result.m_part = EP_EDITTEXT;
- result.m_state = determineState(o);
- break;
- case InnerSpinButtonPart:
- result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN;
- result.m_state = determineState(o, subPart);
- result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
- break;
- }
-
- result.m_classicState |= determineClassicState(o, subPart);
-
- return result;
-}
-
-bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
- const PaintInfo& i,
- const IntRect& r,
- bool drawEdges)
-{
- // Fallback to white if the specified color object is invalid.
- Color backgroundColor(Color::white);
- if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
- backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
-
- // If we have background-image, don't fill the content area to expose the
- // parent's background. Also, we shouldn't fill the content area if the
- // alpha of the color is 0. The API of Windows GDI ignores the alpha.
- //
- // Note that we should paint the content area white if we have neither the
- // background color nor background image explicitly specified to keep the
- // appearance of select element consistent with other browsers.
- bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha();
-
- if (o->style()->hasBorderRadius()) {
- // If the style has rounded borders, setup the context to clip the
- // background (themed or filled) appropriately.
- // FIXME: make sure we do the right thing if css background-clip is set.
- i.context->save();
- i.context->clipRoundedRect(o->style()->getRoundedBorderFor(r));
- }
- {
- const ThemeData& themeData = getThemeData(o);
- ThemePainter painter(i.context, r);
- blink::WebCanvas* canvas = painter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintTextField(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect()), backgroundColor.rgb(), fillContentArea, drawEdges);
- // End of block commits the painter before restoring context.
- }
- if (o->style()->hasBorderRadius())
- i.context->restore();
- return false;
-}
-
-void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(RenderStyle* style, Element*) const
-{
- int width = ScrollbarTheme::theme()->scrollbarThickness();
- style->setWidth(Length(width, Fixed));
- style->setMinWidth(Length(width, Fixed));
-}
-
-bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
-{
- IntRect half = rect;
-
- // Need explicit blocks to avoid to create multiple ThemePainter instances.
- {
- half.setHeight(rect.height() / 2);
- const ThemeData& upThemeData = getThemeData(object, SpinButtonUp);
- ThemePainter upPainter(info.context, half);
- blink::WebCanvas* canvas = upPainter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintSpinButton(canvas, upThemeData.m_part, upThemeData.m_state, upThemeData.m_classicState, blink::WebRect(upPainter.drawRect()));
- }
-
- {
- half.setY(rect.y() + rect.height() / 2);
- const ThemeData& downThemeData = getThemeData(object, SpinButtonDown);
- ThemePainter downPainter(info.context, half);
- blink::WebCanvas* canvas = downPainter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintSpinButton(canvas, downThemeData.m_part, downThemeData.m_state, downThemeData.m_classicState, blink::WebRect(downPainter.drawRect()));
- }
- return false;
-}
-
-// MSDN says that update intervals for the bar is 30ms.
-// http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx
-static const double progressAnimationFrameRate = 0.033;
-
-double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const
-{
- return progressAnimationFrameRate;
-}
-
-double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const
-{
- // On Chromium Windows port, animationProgress() and associated values aren't used.
- // So here we can return arbitrary positive value.
- return progressAnimationFrameRate;
-}
-
-bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
- if (!o->isProgress())
- return true;
-
- RenderProgress* renderProgress = toRenderProgress(o);
- // For indeterminate bar, valueRect is ignored and it is computed by the theme engine
- // because the animation is a platform detail and WebKit doesn't need to know how.
- IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0);
- double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0;
- ThemePainter painter(i.context, r);
- DirectionFlippingScope scope(o, i, r);
- blink::WebCanvas* canvas = painter.context()->canvas();
- blink::Platform::current()->themeEngine()->paintProgressBar(canvas, blink::WebRect(r), blink::WebRect(valueRect), renderProgress->isDeterminate(), animatedSeconds);
- return false;
-}
-
-bool RenderThemeChromiumWin::shouldOpenPickerWithF4Key() const
-{
- return true;
-}
-
-bool RenderThemeChromiumWin::shouldUseFallbackTheme(RenderStyle* style) const
-{
- ControlPart part = style->appearance();
- if (part == CheckboxPart || part == RadioPart)
- return style->effectiveZoom() != 1;
- return false;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.h b/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.h
deleted file mode 100644
index b44e44bb51e..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderThemeChromiumWin.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * This file is part of the WebKit project.
- *
- * Copyright (C) 2006 Apple Computer, Inc.
- * Copyright (C) 2008, 2009 Google, Inc.
- *
- * 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 RenderThemeChromiumWin_h
-#define RenderThemeChromiumWin_h
-
-#include "core/rendering/RenderThemeChromiumSkia.h"
-
-#if WIN32
-typedef void* HANDLE;
-typedef struct HINSTANCE__* HINSTANCE;
-typedef HINSTANCE HMODULE;
-#endif
-
-namespace WebCore {
-
-struct ThemeData {
- ThemeData() : m_part(0), m_state(0), m_classicState(0) { }
-
- unsigned m_part;
- unsigned m_state;
- unsigned m_classicState;
-};
-
-class RenderThemeChromiumWin : public RenderThemeChromiumSkia {
-public:
- static PassRefPtr<RenderTheme> create();
-
- // A method asking if the theme is able to draw the focus ring.
- virtual bool supportsFocusRing(const RenderStyle*) const OVERRIDE;
-
- // The platform selection color.
- virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE;
- virtual Color platformInactiveSelectionBackgroundColor() const OVERRIDE;
- virtual Color platformActiveSelectionForegroundColor() const OVERRIDE;
- virtual Color platformInactiveSelectionForegroundColor() const OVERRIDE;
- virtual Color platformActiveTextSearchHighlightColor() const OVERRIDE;
- virtual Color platformInactiveTextSearchHighlightColor() const OVERRIDE;
-
- virtual Color systemColor(CSSValueID) const OVERRIDE;
-
- virtual IntSize sliderTickSize() const OVERRIDE;
- virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
- virtual void adjustSliderThumbSize(RenderStyle*, Element*) const OVERRIDE;
-
- // Various paint functions.
- virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
-
- // MenuList refers to an unstyled menulist (meaning a menulist without
- // background-color or border set) and MenuListButton refers to a styled
- // menulist (a menulist with background-color or border set).
- virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
- virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
-
- virtual void adjustInnerSpinButtonStyle(RenderStyle*, Element*) const OVERRIDE;
- virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
-
- virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const OVERRIDE;
- virtual double animationDurationForProgressBar(RenderProgress*) const OVERRIDE;
- virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
-
- virtual bool shouldOpenPickerWithF4Key() const OVERRIDE;
-
-protected:
- virtual double caretBlinkIntervalInternal() const OVERRIDE;
- virtual bool shouldUseFallbackTheme(RenderStyle*) const OVERRIDE;
-
-private:
- enum ControlSubPart {
- None,
- SpinButtonDown,
- SpinButtonUp,
- };
-
- RenderThemeChromiumWin() { }
- virtual ~RenderThemeChromiumWin() { }
-
- unsigned determineState(RenderObject*, ControlSubPart = None);
- unsigned determineSliderThumbState(RenderObject*);
- unsigned determineClassicState(RenderObject*, ControlSubPart = None);
-
- ThemeData getThemeData(RenderObject*, ControlSubPart = None);
-
- bool paintTextFieldInternal(RenderObject*, const PaintInfo&, const IntRect&, bool);
-};
-
-} // namespace WebCore
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.cpp
index ccc630e5e81..a450d9773fe 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.cpp
@@ -26,30 +26,29 @@
#include "config.h"
#include "core/rendering/RenderTreeAsText.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/css/StylePropertySet.h"
#include "core/dom/Document.h"
#include "core/editing/FrameSelection.h"
-#include "core/html/HTMLElement.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLElement.h"
#include "core/page/PrintContext.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/FlowThreadController.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderBR.h"
#include "core/rendering/RenderDetailsMarker.h"
#include "core/rendering/RenderFileUploadControl.h"
+#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderInline.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderListMarker.h"
-#include "core/rendering/RenderNamedFlowThread.h"
#include "core/rendering/RenderPart.h"
-#include "core/rendering/RenderRegion.h"
#include "core/rendering/RenderTableCell.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/RenderWidget.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
#include "core/rendering/svg/RenderSVGContainer.h"
#include "core/rendering/svg/RenderSVGGradientStop.h"
#include "core/rendering/svg/RenderSVGImage.h"
@@ -115,17 +114,17 @@ static String getTagName(Node* n)
static bool isEmptyOrUnstyledAppleStyleSpan(const Node* node)
{
- if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))
+ if (!isHTMLSpanElement(node))
return false;
- const HTMLElement* elem = toHTMLElement(node);
- if (elem->getAttribute(classAttr) != "Apple-style-span")
+ const HTMLElement& elem = toHTMLElement(*node);
+ if (elem.getAttribute(classAttr) != "Apple-style-span")
return false;
- if (!node->hasChildNodes())
+ if (!elem.hasChildren())
return true;
- const StylePropertySet* inlineStyleDecl = elem->inlineStyle();
+ const StylePropertySet* inlineStyleDecl = elem.inlineStyle();
return (!inlineStyleDecl || inlineStyleDecl->isEmpty());
}
@@ -227,17 +226,17 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
// Do not dump invalid or transparent backgrounds, since that is the default.
Color backgroundColor = o.resolveColor(CSSPropertyBackgroundColor);
if (o.parent()->resolveColor(CSSPropertyBackgroundColor) != backgroundColor
- && backgroundColor.isValid() && backgroundColor.rgb())
+ && backgroundColor.rgb())
ts << " [bgcolor=" << backgroundColor.nameForRenderTreeAsText() << "]";
Color textFillColor = o.resolveColor(CSSPropertyWebkitTextFillColor);
if (o.parent()->resolveColor(CSSPropertyWebkitTextFillColor) != textFillColor
- && textFillColor.isValid() && textFillColor != color && textFillColor.rgb())
+ && textFillColor != color && textFillColor.rgb())
ts << " [textFillColor=" << textFillColor.nameForRenderTreeAsText() << "]";
Color textStrokeColor = o.resolveColor(CSSPropertyWebkitTextStrokeColor);
if (o.parent()->resolveColor(CSSPropertyWebkitTextStrokeColor) != textStrokeColor
- && textStrokeColor.isValid() && textStrokeColor != color && textStrokeColor.rgb())
+ && textStrokeColor != color && textStrokeColor.rgb())
ts << " [textStrokeColor=" << textStrokeColor.nameForRenderTreeAsText() << "]";
if (o.parent()->style()->textStrokeWidth() != o.style()->textStrokeWidth() && o.style()->textStrokeWidth() > 0)
@@ -475,7 +474,7 @@ void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavi
}
}
- for (RenderObject* child = o.firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = o.slowFirstChild(); child; child = child->nextSibling()) {
if (child->hasLayer())
continue;
write(ts, *child, indent + 1, behavior);
@@ -539,10 +538,10 @@ static void write(TextStream& ts, RenderLayer& l,
ts << " scrollX " << l.scrollableArea()->scrollXOffset();
if (l.scrollableArea()->scrollYOffset())
ts << " scrollY " << l.scrollableArea()->scrollYOffset();
- if (l.renderBox() && l.renderBox()->pixelSnappedClientWidth() != l.renderBox()->scrollWidth())
- ts << " scrollWidth " << l.renderBox()->scrollWidth();
- if (l.renderBox() && l.renderBox()->pixelSnappedClientHeight() != l.renderBox()->scrollHeight())
- ts << " scrollHeight " << l.renderBox()->scrollHeight();
+ if (l.renderBox() && l.renderBox()->pixelSnappedClientWidth() != l.renderBox()->pixelSnappedScrollWidth())
+ ts << " scrollWidth " << l.renderBox()->pixelSnappedScrollWidth();
+ if (l.renderBox() && l.renderBox()->pixelSnappedClientHeight() != l.renderBox()->pixelSnappedScrollHeight())
+ ts << " scrollHeight " << l.renderBox()->pixelSnappedScrollHeight();
}
if (paintPhase == LayerPaintPhaseBackground)
@@ -550,6 +549,11 @@ static void write(TextStream& ts, RenderLayer& l,
else if (paintPhase == LayerPaintPhaseForeground)
ts << " layerType: foreground only";
+ if (l.blendInfo().childLayerHasBlendMode())
+ ts << " isolatesBlending";
+ if (l.blendInfo().hasBlendMode())
+ ts << " blendMode: " << compositeOperatorName(CompositeSourceOver, l.blendInfo().blendMode());
+
if (behavior & RenderAsTextShowCompositedLayers) {
if (l.hasCompositedLayerMapping()) {
ts << " (composited, bounds="
@@ -558,6 +562,7 @@ static void write(TextStream& ts, RenderLayer& l,
<< l.compositedLayerMapping()->mainGraphicsLayer()->drawsContent()
<< ", paints into ancestor="
<< l.compositedLayerMapping()->paintsIntoCompositedAncestor()
+ << (l.shouldIsolateCompositedDescendants() ? ", isolatesCompositedBlending" : "")
<< ")";
}
}
@@ -568,91 +573,6 @@ static void write(TextStream& ts, RenderLayer& l,
write(ts, *l.renderer(), indent + 1, behavior);
}
-static void writeRenderRegionList(const RenderRegionList& flowThreadRegionList, TextStream& ts, int indent)
-{
- for (RenderRegionList::const_iterator itRR = flowThreadRegionList.begin(); itRR != flowThreadRegionList.end(); ++itRR) {
- const RenderRegion* renderRegion = *itRR;
-
- writeIndent(ts, indent);
- ts << renderRegion->renderName();
-
- Node* generatingNodeForRegion = renderRegion->generatingNodeForRegion();
- if (generatingNodeForRegion) {
- if (renderRegion->hasCustomRegionStyle())
- ts << " region style: 1";
- if (renderRegion->hasAutoLogicalHeight())
- ts << " hasAutoLogicalHeight";
-
- bool isRenderNamedFlowFragment = renderRegion->isRenderNamedFlowFragment();
- if (isRenderNamedFlowFragment)
- ts << " (anonymous child of";
-
- StringBuilder tagName;
- tagName.append(generatingNodeForRegion->nodeName());
-
- Node* nodeForRegion = renderRegion->nodeForRegion();
- if (nodeForRegion->isPseudoElement()) {
- if (nodeForRegion->isBeforePseudoElement())
- tagName.append("::before");
- else if (nodeForRegion->isAfterPseudoElement())
- tagName.append("::after");
- }
-
- ts << " {" << tagName.toString() << "}";
-
- if (generatingNodeForRegion->isElementNode() && generatingNodeForRegion->hasID()) {
- Element* element = toElement(generatingNodeForRegion);
- ts << " #" << element->idForStyleResolution();
- }
-
- if (isRenderNamedFlowFragment)
- ts << ")";
- }
-
- if (!renderRegion->isValid())
- ts << " invalid";
-
- ts << "\n";
- }
-}
-
-static void writeRenderNamedFlowThreads(TextStream& ts, RenderView* renderView, const RenderLayer* rootLayer,
- const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
-{
- if (!renderView->hasRenderNamedFlowThreads())
- return;
-
- const RenderNamedFlowThreadList* list = renderView->flowThreadController()->renderNamedFlowThreadList();
-
- writeIndent(ts, indent);
- ts << "Named flows\n";
-
- for (RenderNamedFlowThreadList::const_iterator iter = list->begin(); iter != list->end(); ++iter) {
- const RenderNamedFlowThread* renderFlowThread = *iter;
-
- writeIndent(ts, indent + 1);
- ts << "Named flow '" << renderFlowThread->flowThreadName() << "'\n";
-
- RenderLayer* layer = renderFlowThread->layer();
- RenderTreeAsText::writeLayers(ts, rootLayer, layer, paintRect, indent + 2, behavior);
-
- // Display the valid and invalid render regions attached to this flow thread.
- const RenderRegionList& validRegionsList = renderFlowThread->renderRegionList();
- if (!validRegionsList.isEmpty()) {
- writeIndent(ts, indent + 2);
- ts << "Regions for named flow '" << renderFlowThread->flowThreadName() << "'\n";
- writeRenderRegionList(validRegionsList, ts, indent + 3);
- }
-
- const RenderRegionList& invalidRegionsList = renderFlowThread->invalidRenderRegionList();
- if (!invalidRegionsList.isEmpty()) {
- writeIndent(ts, indent + 2);
- ts << "Invalid regions for named flow '" << renderFlowThread->flowThreadName() << "'\n";
- writeRenderRegionList(invalidRegionsList, ts, indent + 3);
- }
- }
-}
-
void RenderTreeAsText::writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* layer,
const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
{
@@ -667,7 +587,7 @@ void RenderTreeAsText::writeLayers(TextStream& ts, const RenderLayer* rootLayer,
// Calculate the clip rects we should use.
LayoutRect layerBounds;
ClipRect damageRect, clipRectToApply, outlineRect;
- layer->calculateRects(ClipRectsContext(rootLayer, 0, TemporaryClipRects), paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+ layer->clipper().calculateRects(ClipRectsContext(rootLayer, TemporaryClipRects), paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
// Ensure our lists are up-to-date.
layer->stackingNode()->updateLayerListsIfNeeded();
@@ -714,13 +634,6 @@ void RenderTreeAsText::writeLayers(TextStream& ts, const RenderLayer* rootLayer,
for (unsigned i = 0; i != posList->size(); ++i)
writeLayers(ts, rootLayer, posList->at(i)->layer(), paintDirtyRect, currIndent, behavior);
}
-
- // Altough the RenderFlowThread requires a layer, it is not collected by its parent,
- // so we have to treat it as a special case.
- if (layer->renderer()->isRenderView()) {
- RenderView* renderView = toRenderView(layer->renderer());
- writeRenderNamedFlowThreads(ts, renderView, rootLayer, paintDirtyRect, indent, behavior);
- }
}
static String nodePosition(Node* node)
@@ -764,7 +677,7 @@ static void writeSelection(TextStream& ts, const RenderObject* o)
return;
Document* doc = toDocument(n);
- Frame* frame = doc->frame();
+ LocalFrame* frame = doc->frame();
if (!frame)
return;
@@ -791,7 +704,7 @@ static String externalRepresentation(RenderBox* renderer, RenderAsTextBehavior b
return ts.release();
}
-String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior)
+String externalRepresentation(LocalFrame* frame, RenderAsTextBehavior behavior)
{
if (!(behavior & RenderAsTextDontUpdateLayout))
frame->document()->updateLayout();
@@ -802,7 +715,7 @@ String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior)
PrintContext printContext(frame);
if (behavior & RenderAsTextPrintingMode)
- printContext.begin(toRenderBox(renderer)->width());
+ printContext.begin(toRenderBox(renderer)->width().toFloat());
return externalRepresentation(toRenderBox(renderer), behavior);
}
@@ -823,7 +736,7 @@ String externalRepresentation(Element* element, RenderAsTextBehavior behavior)
static void writeCounterValuesFromChildren(TextStream& stream, RenderObject* parent, bool& isFirstCounter)
{
- for (RenderObject* child = parent->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = parent->slowFirstChild(); child; child = child->nextSibling()) {
if (child->isCounter()) {
if (!isFirstCounter)
stream << " ";
@@ -837,7 +750,7 @@ static void writeCounterValuesFromChildren(TextStream& stream, RenderObject* par
String counterValueForElement(Element* element)
{
// Make sure the element is not freed during the layout.
- RefPtr<Element> elementRef(element);
+ RefPtrWillBeRawPtr<Element> protector(element);
element->document().updateLayout();
TextStream stream;
bool isFirstCounter = true;
@@ -852,7 +765,7 @@ String counterValueForElement(Element* element)
String markerTextForListItem(Element* element)
{
// Make sure the element is not freed during the layout.
- RefPtr<Element> elementRef(element);
+ RefPtrWillBeRawPtr<Element> protector(element);
element->document().updateLayout();
RenderObject* renderer = element->renderer();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.h b/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.h
index 63c900ca947..aa66a867604 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderTreeAsText.h
@@ -32,7 +32,7 @@
namespace WebCore {
class Element;
-class Frame;
+class LocalFrame;
class LayoutRect;
class RenderLayer;
class RenderObject;
@@ -52,7 +52,7 @@ enum RenderAsTextBehaviorFlags {
typedef unsigned RenderAsTextBehavior;
// You don't need pageWidthInPixels if you don't specify RenderAsTextInPrintingMode.
-String externalRepresentation(Frame*, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
+String externalRepresentation(LocalFrame*, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
String externalRepresentation(Element*, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
void write(TextStream&, const RenderObject&, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.cpp
index 4507321ee6f..349e98ad698 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.cpp
@@ -27,7 +27,6 @@
#include "core/rendering/RenderVTTCue.h"
#include "core/html/track/vtt/VTTCue.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderView.h"
namespace WebCore {
@@ -40,7 +39,6 @@ RenderVTTCue::RenderVTTCue(VTTCueBox* element)
void RenderVTTCue::layout()
{
- LayoutRectRecorder recorder(*this);
RenderBlockFlow::layout();
// If WebVTT Regions are used, the regular WebVTT layout algorithm is no
@@ -50,14 +48,12 @@ void RenderVTTCue::layout()
if (!m_cue->regionId().isEmpty())
return;
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+ LayoutState state(*this, locationOffset());
if (m_cue->snapToLines())
repositionCueSnapToLinesSet();
else
repositionCueSnapToLinesNotSet();
-
- statePusher.pop();
}
bool RenderVTTCue::findFirstLineBox(InlineFlowBox*& firstLineBox)
@@ -127,7 +123,8 @@ void RenderVTTCue::placeBoxInDefaultPosition(LayoutUnit position, bool& switched
// 9. Default: Remember the position of all the boxes in boxes as their
// default position.
- m_fallbackPosition = FloatPoint(x(), y());
+ // FIXME: Why the direct conversion between float and LayoutUnit? crbug.com/350474
+ m_fallbackPosition = FloatPoint(location());
// 10. Let switched be false.
switched = false;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.h b/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.h
index d357b24cc3a..953ff82f4b0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderVTTCue.h
@@ -41,7 +41,6 @@ public:
private:
virtual void layout() OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
bool isOutside() const;
bool isOverlapping() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.cpp
index b498f90186a..902641ddd06 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.cpp
@@ -27,13 +27,11 @@
#include "core/rendering/RenderVideo.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
-#include "core/html/HTMLVideoElement.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
-#include "core/page/Page.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLVideoElement.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderFullScreen.h"
#include "platform/graphics/media/MediaPlayer.h"
@@ -83,7 +81,7 @@ void RenderVideo::updateIntrinsicSize()
setIntrinsicSize(size);
setPreferredLogicalWidthsDirty();
- setNeedsLayout();
+ setNeedsLayoutAndFullPaintInvalidation();
}
LayoutSize RenderVideo::calculateIntrinsicSize()
@@ -99,9 +97,9 @@ LayoutSize RenderVideo::calculateIntrinsicSize()
// The intrinsic height of a video element's playback area is the intrinsic height
// of the video resource, if that is available; otherwise it is the intrinsic
// height of the poster frame, if that is available; otherwise it is 150 CSS pixels.
- MediaPlayer* player = mediaElement()->player();
- if (player && video->readyState() >= HTMLVideoElement::HAVE_METADATA) {
- LayoutSize size = player->naturalSize();
+ blink::WebMediaPlayer* webMediaPlayer = mediaElement()->webMediaPlayer();
+ if (webMediaPlayer && video->readyState() >= HTMLVideoElement::HAVE_METADATA) {
+ IntSize size = webMediaPlayer->naturalSize();
if (!size.isEmpty())
return size;
}
@@ -186,14 +184,12 @@ bool RenderVideo::acceleratedRenderingInUse()
void RenderVideo::layout()
{
- LayoutRectRecorder recorder(*this);
updatePlayer();
RenderMedia::layout();
}
HTMLVideoElement* RenderVideo::videoElement() const
{
- ASSERT(isHTMLVideoElement(node()));
return toHTMLVideoElement(node());
}
@@ -214,7 +210,7 @@ void RenderVideo::updatePlayer()
if (!videoElement()->isActive())
return;
- contentChanged(VideoChanged);
+ videoElement()->setNeedsCompositingUpdate();
}
LayoutUnit RenderVideo::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
@@ -278,4 +274,18 @@ LayoutUnit RenderVideo::offsetHeight() const
return RenderMedia::offsetHeight();
}
+CompositingReasons RenderVideo::additionalCompositingReasons(CompositingTriggerFlags triggers) const
+{
+ if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled()) {
+ HTMLMediaElement* media = toHTMLMediaElement(node());
+ if (media->isFullscreen())
+ return CompositingReasonVideo;
+ }
+
+ if ((triggers & VideoTrigger) && shouldDisplayVideo() && supportsAcceleratedRendering())
+ return CompositingReasonVideo;
+
+ return CompositingReasonNone;
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.h b/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.h
index 40a400d9075..405f99cddee 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderVideo.h
@@ -30,7 +30,6 @@
namespace WebCore {
-class HTMLMediaElement;
class HTMLVideoElement;
class RenderVideo FINAL : public RenderMedia {
@@ -44,35 +43,36 @@ public:
bool supportsAcceleratedRendering() const;
- virtual bool shouldDisplayVideo() const;
+ bool shouldDisplayVideo() const;
private:
- virtual void updateFromElement();
+ virtual void updateFromElement() OVERRIDE;
inline HTMLVideoElement* videoElement() const;
- virtual void intrinsicSizeChanged();
+ virtual void intrinsicSizeChanged() OVERRIDE;
LayoutSize calculateIntrinsicSize();
void updateIntrinsicSize();
- virtual void imageChanged(WrappedImagePtr, const IntRect*);
+ virtual void imageChanged(WrappedImagePtr, const IntRect*) OVERRIDE;
- virtual const char* renderName() const { return "RenderVideo"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderVideo"; }
- virtual bool requiresLayer() const { return true; }
- virtual bool isVideo() const { return true; }
+ virtual bool isVideo() const OVERRIDE { return true; }
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual void layout();
+ virtual void layout() OVERRIDE;
virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const OVERRIDE;
- virtual LayoutUnit computeReplacedLogicalHeight() const;
+ virtual LayoutUnit computeReplacedLogicalHeight() const OVERRIDE;
virtual LayoutUnit minimumReplacedHeight() const OVERRIDE;
- virtual LayoutUnit offsetLeft() const;
- virtual LayoutUnit offsetTop() const;
- virtual LayoutUnit offsetWidth() const;
- virtual LayoutUnit offsetHeight() const;
+ virtual LayoutUnit offsetLeft() const OVERRIDE;
+ virtual LayoutUnit offsetTop() const OVERRIDE;
+ virtual LayoutUnit offsetWidth() const OVERRIDE;
+ virtual LayoutUnit offsetHeight() const OVERRIDE;
+
+ virtual CompositingReasons additionalCompositingReasons(CompositingTriggerFlags) const OVERRIDE;
void updatePlayer();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderView.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderView.cpp
index 05955691af5..8aa9ddacbd3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderView.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderView.cpp
@@ -21,31 +21,29 @@
#include "config.h"
#include "core/rendering/RenderView.h"
-#include "RuntimeEnabledFeatures.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLDialogElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLIFrameElement.h"
-#include "core/frame/Frame.h"
#include "core/page/Page.h"
#include "core/rendering/ColumnInfo.h"
-#include "core/rendering/CompositedLayerMapping.h"
#include "core/rendering/FlowThreadController.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderFlowThread.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerCompositor.h"
#include "core/rendering/RenderSelectionInfo.h"
-#include "core/rendering/RenderWidget.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "core/svg/SVGDocumentExtensions.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/TraceEvent.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
namespace WebCore {
@@ -56,11 +54,9 @@ RenderView::RenderView(Document* document)
, m_selectionEnd(0)
, m_selectionStartPos(-1)
, m_selectionEndPos(-1)
- , m_maximalOutlineSize(0)
, m_pageLogicalHeight(0)
, m_pageLogicalHeightChanged(false)
, m_layoutState(0)
- , m_layoutStateDisableCount(0)
, m_renderQuoteHead(0)
, m_renderCounterCount(0)
{
@@ -86,6 +82,8 @@ bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
{
+ TRACE_EVENT0("blink", "RenderView::hitTest");
+
// We have to recursively update layout/style here because otherwise, when the hit test recurses
// into a child document, it could trigger a layout on the parent document, which can destroy RenderLayers
// that are higher up in the call stack, leading to crashes.
@@ -111,7 +109,7 @@ LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType heightT
// If we have columns, then the available logical height is reduced to the column height.
if (hasColumns())
return columnInfo()->columnHeight();
- return RenderBlock::availableLogicalHeight(heightType);
+ return RenderBlockFlow::availableLogicalHeight(heightType);
}
bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
@@ -119,8 +117,9 @@ bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
return child->isBox();
}
-static bool dialogNeedsCentering(const RenderStyle* style)
+static bool canCenterDialog(const RenderStyle* style)
{
+ // FIXME: We must center for FixedPosition as well.
return style->position() == AbsolutePosition && style->hasAutoTopAndBottom();
}
@@ -130,18 +129,19 @@ void RenderView::positionDialog(RenderBox* box)
if (dialog->centeringMode() == HTMLDialogElement::NotCentered)
return;
if (dialog->centeringMode() == HTMLDialogElement::Centered) {
- if (dialogNeedsCentering(box->style()))
+ if (canCenterDialog(box->style()))
box->setY(dialog->centeredPosition());
return;
}
- if (!dialogNeedsCentering(box->style())) {
+ ASSERT(dialog->centeringMode() == HTMLDialogElement::NeedsCentering);
+ if (!canCenterDialog(box->style())) {
dialog->setNotCentered();
return;
}
FrameView* frameView = document().view();
int scrollTop = frameView->scrollOffset().height();
- int visibleHeight = frameView->visibleContentRect(ScrollableArea::IncludeScrollbars).height();
+ int visibleHeight = frameView->visibleContentRect(IncludeScrollbars).height();
LayoutUnit top = scrollTop;
if (box->height() < visibleHeight)
top += (visibleHeight - box->height()) / 2;
@@ -157,146 +157,68 @@ void RenderView::positionDialogs()
TrackedRendererListHashSet::iterator end = positionedDescendants->end();
for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
RenderBox* box = *it;
- if (box->node() && box->node()->hasTagName(HTMLNames::dialogTag))
+ if (isHTMLDialogElement(box->node()))
positionDialog(box);
}
}
-void RenderView::layoutContent(const LayoutState& state)
+void RenderView::layoutContent()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
- RenderBlock::layout();
+ RenderBlockFlow::layout();
if (RuntimeEnabledFeatures::dialogElementEnabled())
positionDialogs();
- if (m_frameView->partialLayout().isStopping())
- return;
-
- if (hasRenderNamedFlowThreads())
- flowThreadController()->layoutRenderNamedFlowThreads();
-
#ifndef NDEBUG
- checkLayoutState(state);
+ checkLayoutState();
#endif
}
#ifndef NDEBUG
-void RenderView::checkLayoutState(const LayoutState& state)
+void RenderView::checkLayoutState()
{
- ASSERT(layoutDeltaMatches(LayoutSize()));
- ASSERT(!m_layoutStateDisableCount);
- ASSERT(m_layoutState == &state);
+ if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
+ ASSERT(layoutDeltaMatches(LayoutSize()));
+ }
+ ASSERT(!m_layoutState->next());
}
#endif
-static RenderBox* enclosingSeamlessRenderer(const Document& doc)
+bool RenderView::shouldDoFullRepaintForNextLayout() const
{
- Element* ownerElement = doc.seamlessParentIFrame();
- if (!ownerElement)
- return 0;
- return ownerElement->renderBox();
-}
-
-void RenderView::addChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- // Seamless iframes are considered part of an enclosing render flow thread from the parent document. This is necessary for them to look
- // up regions in the parent document during layout.
- if (newChild && !newChild->isRenderFlowThread()) {
- RenderBox* seamlessBox = enclosingSeamlessRenderer(document());
- if (seamlessBox && seamlessBox->flowThreadContainingBlock())
- newChild->setFlowThreadState(seamlessBox->flowThreadState());
- }
- RenderBlock::addChild(newChild, beforeChild);
-}
+ // It's hard to predict here which of full repaint or per-descendant repaint costs less.
+ // For vertical writing mode or width change it's more likely that per-descendant repaint
+ // eventually turns out to be full repaint but with the cost to handle more layout states
+ // and discrete repaint rects, so marking full repaint here is more likely to cost less.
+ // Otherwise, per-descendant repaint is more likely to avoid unnecessary full repaints.
-bool RenderView::initializeLayoutState(LayoutState& state)
-{
- bool isSeamlessAncestorInFlowThread = false;
-
- // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
- state.m_clipped = false;
-
- // Check the writing mode of the seamless ancestor. It has to match our document's writing mode, or we won't inherit any
- // pagination information.
- RenderBox* seamlessAncestor = enclosingSeamlessRenderer(document());
- LayoutState* seamlessLayoutState = seamlessAncestor ? seamlessAncestor->view()->layoutState() : 0;
- bool shouldInheritPagination = seamlessLayoutState && !m_pageLogicalHeight && seamlessAncestor->style()->writingMode() == style()->writingMode();
-
- state.m_pageLogicalHeight = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeight : m_pageLogicalHeight;
- state.m_pageLogicalHeightChanged = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeightChanged : m_pageLogicalHeightChanged;
- state.m_isPaginated = state.m_pageLogicalHeight;
- if (state.m_isPaginated && shouldInheritPagination) {
- // Set up the correct pagination offset. We can use a negative offset in order to push the top of the RenderView into its correct place
- // on a page. We can take the iframe's offset from the logical top of the first page and make the negative into the pagination offset within the child
- // view.
- bool isFlipped = seamlessAncestor->style()->isFlippedBlocksWritingMode();
- LayoutSize layoutOffset = seamlessLayoutState->layoutOffset();
- LayoutSize iFrameOffset(layoutOffset.width() + seamlessAncestor->x() + (!isFlipped ? seamlessAncestor->borderLeft() + seamlessAncestor->paddingLeft() :
- seamlessAncestor->borderRight() + seamlessAncestor->paddingRight()),
- layoutOffset.height() + seamlessAncestor->y() + (!isFlipped ? seamlessAncestor->borderTop() + seamlessAncestor->paddingTop() :
- seamlessAncestor->borderBottom() + seamlessAncestor->paddingBottom()));
-
- LayoutSize offsetDelta = seamlessLayoutState->m_pageOffset - iFrameOffset;
- state.m_pageOffset = offsetDelta;
-
- // Set the current render flow thread to point to our ancestor. This will allow the seamless document to locate the correct
- // regions when doing a layout.
- if (seamlessAncestor->flowThreadContainingBlock()) {
- flowThreadController()->setCurrentRenderFlowThread(seamlessAncestor->view()->flowThreadController()->currentRenderFlowThread());
- isSeamlessAncestorInFlowThread = true;
+ if (shouldUsePrintingLayout())
+ return true;
+
+ if (!style()->isHorizontalWritingMode() || width() != viewWidth())
+ return true;
+
+ if (height() != viewHeight()) {
+ // FIXME: Disable optimization to fix crbug.com/390378 for the branch.
+ return true;
+#if 0
+ if (RenderObject* backgroundRenderer = this->backgroundRenderer()) {
+ // When background-attachment is 'fixed', we treat the viewport (instead of the 'root'
+ // i.e. html or body) as the background positioning area, and we should full repaint
+ // viewport resize if the background image is not composited and needs full repaint on
+ // background positioning area resize.
+ if (!m_compositor || !m_compositor->needsFixedRootBackgroundLayer(layer())) {
+ if (backgroundRenderer->style()->hasFixedBackgroundImage()
+ && mustInvalidateFillLayersPaintOnHeightChange(*backgroundRenderer->style()->backgroundLayers()))
+ return true;
+ }
}
+#endif
}
- // FIXME: We need to make line grids and exclusions work with seamless iframes as well here. Basically all layout state information needs
- // to propagate here and not just pagination information.
- return isSeamlessAncestorInFlowThread;
-}
-
-// The algorithm below assumes this is a full layout. In case there are previously computed values for regions, supplemental steps are taken
-// to ensure the results are the same as those obtained from a full layout (i.e. the auto-height regions from all the flows are marked as needing
-// layout).
-// 1. The flows are laid out from the outer flow to the inner flow. This successfully computes the outer non-auto-height regions size so the
-// inner flows have the necessary information to correctly fragment the content.
-// 2. The flows are laid out from the inner flow to the outer flow. After an inner flow is laid out it goes into the constrained layout phase
-// and marks the auto-height regions they need layout. This means the outer flows will relayout if they depend on regions with auto-height regions
-// belonging to inner flows. This step will correctly set the computedAutoHeight for the auto-height regions. It's possible for non-auto-height
-// regions to relayout if they depend on auto-height regions. This will invalidate the inner flow threads and mark them as needing layout.
-// 3. The last step is to do one last layout if there are pathological dependencies between non-auto-height regions and auto-height regions
-// as detected in the previous step.
-void RenderView::layoutContentInAutoLogicalHeightRegions(const LayoutState& state)
-{
- if (!m_frameView->partialLayout().isStopping()) {
- // Disable partial layout for any two-pass layout algorithm.
- m_frameView->partialLayout().reset();
- }
-
- // We need to invalidate all the flows with auto-height regions if one such flow needs layout.
- // If none is found we do a layout a check back again afterwards.
- if (!flowThreadController()->updateFlowThreadsNeedingLayout()) {
- // Do a first layout of the content. In some cases more layouts are not needed (e.g. only flows with non-auto-height regions have changed).
- layoutContent(state);
-
- // If we find no named flow needing a two step layout after the first layout, exit early.
- // Otherwise, initiate the two step layout algorithm and recompute all the flows.
- if (!flowThreadController()->updateFlowThreadsNeedingTwoStepLayout())
- return;
- }
-
- // Layout to recompute all the named flows with auto-height regions.
- layoutContent(state);
-
- // Propagate the computed auto-height values upwards.
- // Non-auto-height regions may invalidate the flow thread because they depended on auto-height regions, but that's ok.
- flowThreadController()->updateFlowThreadsIntoConstrainedPhase();
-
- // Do one last layout that should update the auto-height regions found in the main flow
- // and solve pathological dependencies between regions (e.g. a non-auto-height region depending
- // on an auto-height one).
- if (needsLayout())
- layoutContent(state);
+ return false;
}
void RenderView::layout()
@@ -307,7 +229,7 @@ void RenderView::layout()
if (shouldUsePrintingLayout())
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
- SubtreeLayoutScope layoutScope(this);
+ SubtreeLayoutScope layoutScope(*this);
// Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
@@ -320,45 +242,28 @@ void RenderView::layout()
if ((child->isBox() && toRenderBox(child)->hasRelativeLogicalHeight())
|| child->style()->logicalHeight().isPercent()
|| child->style()->logicalMinHeight().isPercent()
- || child->style()->logicalMaxHeight().isPercent()
- || child->style()->logicalHeight().isViewportPercentage()
- || child->style()->logicalMinHeight().isViewportPercentage()
- || child->style()->logicalMaxHeight().isViewportPercentage())
+ || child->style()->logicalMaxHeight().isPercent())
layoutScope.setChildNeedsLayout(child);
}
if (document().svgExtensions())
- document().accessSVGExtensions()->invalidateSVGRootsWithRelativeLengthDescendents(&layoutScope);
+ document().accessSVGExtensions().invalidateSVGRootsWithRelativeLengthDescendents(&layoutScope);
}
ASSERT(!m_layoutState);
if (!needsLayout())
return;
- LayoutState state;
- bool isSeamlessAncestorInFlowThread = initializeLayoutState(state);
+ LayoutState rootLayoutState(pageLogicalHeight(), pageLogicalHeightChanged(), *this);
m_pageLogicalHeightChanged = false;
- m_layoutState = &state;
- if (checkTwoPassLayoutForAutoHeightRegions())
- layoutContentInAutoLogicalHeightRegions(state);
- else
- layoutContent(state);
-
- if (m_frameView->partialLayout().isStopping()) {
- m_layoutState = 0;
- return;
- }
+ layoutContent();
#ifndef NDEBUG
- checkLayoutState(state);
+ checkLayoutState();
#endif
- m_layoutState = 0;
clearNeedsLayout();
-
- if (isSeamlessAncestorInFlowThread)
- flowThreadController()->setCurrentRenderFlowThread(0);
}
void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
@@ -444,32 +349,6 @@ void RenderView::computeSelfHitTestRects(Vector<LayoutRect>& rects, const Layout
rects.append(LayoutRect(LayoutPoint::zero(), frameView()->contentsSize()));
}
-bool RenderView::requiresColumns(int desiredColumnCount) const
-{
- if (m_frameView)
- return m_frameView->pagination().mode != Pagination::Unpaginated;
-
- return RenderBlock::requiresColumns(desiredColumnCount);
-}
-
-void RenderView::calcColumnWidth()
-{
- int columnWidth = contentLogicalWidth();
- if (m_frameView && style()->hasInlineColumnAxis()) {
- if (int pageLength = m_frameView->pagination().pageLength)
- columnWidth = pageLength;
- }
- setDesiredColumnCountAndWidth(1, columnWidth);
-}
-
-ColumnInfo::PaginationUnit RenderView::paginationUnit() const
-{
- if (m_frameView)
- return m_frameView->pagination().behavesLikeColumns ? ColumnInfo::Column : ColumnInfo::Page;
-
- return ColumnInfo::Page;
-}
-
void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// If we ever require layout but receive a paint anyway, something has gone horribly wrong.
@@ -480,33 +359,42 @@ void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
// This avoids painting garbage between columns if there is a column gap.
- if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated)
+ if (m_frameView && style()->isOverflowPaged())
paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor());
paintObject(paintInfo, paintOffset);
}
-static inline bool rendererObscuresBackground(RenderObject* rootObject)
+static inline bool rendererObscuresBackground(RenderBox* rootBox)
{
- if (!rootObject)
- return false;
-
- RenderStyle* style = rootObject->style();
+ ASSERT(rootBox);
+ RenderStyle* style = rootBox->style();
if (style->visibility() != VISIBLE
|| style->opacity() != 1
+ || style->hasFilter()
|| style->hasTransform())
return false;
- if (rootObject->compositingState() == PaintsIntoOwnBacking)
+ if (rootBox->compositingState() == PaintsIntoOwnBacking)
return false;
- const RenderObject* rootRenderer = rootObject->rendererForRootBackground();
+ const RenderObject* rootRenderer = rootBox->rendererForRootBackground();
if (rootRenderer->style()->backgroundClip() == TextFillBox)
return false;
return true;
}
+bool RenderView::rootFillsViewportBackground(RenderBox* rootBox) const
+{
+ ASSERT(rootBox);
+ // CSS Boxes always fill the viewport background (see paintRootBoxFillLayers)
+ if (!rootBox->isSVG())
+ return true;
+
+ return rootBox->frameRect().contains(frameRect());
+}
+
void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
{
// Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit
@@ -534,21 +422,13 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
if (paintInfo.skipRootBackground())
return;
- bool rootFillsViewport = false;
- bool rootObscuresBackground = false;
+ bool shouldPaintBackground = true;
Node* documentElement = document().documentElement();
- if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
- // The document element's renderer is currently forced to be a block, but may not always be.
- RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
- rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
- rootObscuresBackground = rendererObscuresBackground(rootRenderer);
- }
-
- Page* page = document().page();
- float pageScaleFactor = page ? page->pageScaleFactor() : 1;
+ if (RenderBox* rootBox = documentElement ? toRenderBox(documentElement->renderer()) : 0)
+ shouldPaintBackground = !rootFillsViewportBackground(rootBox) || !rendererObscuresBackground(rootBox);
// If painting will entirely fill the view, no need to fill the background.
- if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
+ if (!shouldPaintBackground)
return;
// This code typically only executes if the root element's visibility has been set to hidden,
@@ -570,63 +450,64 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
}
}
-bool RenderView::shouldRepaint(const LayoutRect& rect) const
+void RenderView::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
{
- if (document().printing())
- return false;
- return m_frameView && !rect.isEmpty();
+ ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ ASSERT(!needsLayout());
+
+ // We specifically need to repaint the viewRect since other renderers
+ // short-circuit on full-repaint.
+ if (doingFullRepaint() && !viewRect().isEmpty())
+ repaintViewRectangle(viewRect());
+
+ LayoutState rootLayoutState(0, false, *this);
+ RenderBlock::invalidateTreeAfterLayout(paintInvalidationContainer);
}
-void RenderView::repaintViewRectangle(const LayoutRect& ur) const
+void RenderView::repaintViewRectangle(const LayoutRect& repaintRect) const
{
- if (!shouldRepaint(ur))
+ ASSERT(!repaintRect.isEmpty());
+
+ if (document().printing() || !m_frameView)
return;
// We always just invalidate the root view, since we could be an iframe that is clipped out
// or even invisible.
- Element* elt = document().ownerElement();
- if (!elt)
- m_frameView->repaintContentRectangle(pixelSnappedIntRect(ur));
- else if (RenderBox* obj = elt->renderBox()) {
- LayoutRect vr = viewRect();
- LayoutRect r = intersection(ur, vr);
+ Element* owner = document().ownerElement();
+ if (layer()->compositingState() == PaintsIntoOwnBacking) {
+ layer()->repainter().setBackingNeedsRepaintInRect(repaintRect);
+ } else if (!owner) {
+ m_frameView->contentRectangleForPaintInvalidation(pixelSnappedIntRect(repaintRect));
+ } else if (RenderBox* obj = owner->renderBox()) {
+ LayoutRect viewRectangle = viewRect();
+ LayoutRect rectToRepaint = intersection(repaintRect, viewRectangle);
// Subtract out the contentsX and contentsY offsets to get our coords within the viewing
// rectangle.
- r.moveBy(-vr.location());
+ rectToRepaint.moveBy(-viewRectangle.location());
// FIXME: Hardcoded offsets here are not good.
- r.moveBy(obj->contentBoxRect().location());
- obj->repaintRectangle(r);
- }
-}
-
-void RenderView::repaintRectangleInViewAndCompositedLayers(const LayoutRect& ur)
-{
- if (!shouldRepaint(ur))
- return;
-
- repaintViewRectangle(ur);
-
- if (compositor()->inCompositingMode()) {
- IntRect repaintRect = pixelSnappedIntRect(ur);
- compositor()->repaintCompositedLayers(&repaintRect);
+ rectToRepaint.moveBy(obj->contentBoxRect().location());
+ obj->invalidatePaintRectangle(rectToRepaint);
}
}
void RenderView::repaintViewAndCompositedLayers()
{
- repaint();
+ paintInvalidationForWholeRenderer();
+
+ // The only way we know how to hit these ASSERTS below this point is via the Chromium OS login screen.
+ DisableCompositingQueryAsserts disabler;
if (compositor()->inCompositingMode())
compositor()->repaintCompositedLayers();
}
-void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+void RenderView::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, 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.
- ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
+ ASSERT_ARG(paintInvalidationContainer, !paintInvalidationContainer || paintInvalidationContainer == this);
if (document().printing())
return;
@@ -640,11 +521,16 @@ void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintCont
rect.setX(viewWidth() - rect.maxX());
}
- if (fixed && m_frameView)
+ if (fixed && m_frameView) {
rect.move(m_frameView->scrollOffsetForFixedPosition());
+ // If we have a pending scroll, invalidate the previous scroll position.
+ if (!m_frameView->pendingScrollDelta().isZero()) {
+ rect.move(-m_frameView->pendingScrollDelta());
+ }
+ }
// Apply our transform if we have one (because of full page zooming).
- if (!repaintContainer && layer() && layer()->transform())
+ if (!paintInvalidationContainer && layer() && layer()->transform())
rect = layer()->transform()->mapRect(rect);
}
@@ -682,7 +568,7 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
RenderBlock* cb = os->containingBlock();
while (cb && !cb->isRenderView()) {
- OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
+ OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).storedValue->value;
if (blockInfo)
break;
blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
@@ -700,7 +586,7 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
RenderSelectionInfo* info = i->value.get();
// RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
LayoutRect currRect = info->rect();
- if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
+ if (const RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
currRect = absQuad.enclosingBoundingBox();
}
@@ -731,19 +617,6 @@ void RenderView::repaintSelection() const
}
}
-// Compositing layer dimensions take outline size into account, so we have to recompute layer
-// bounds when it changes.
-// FIXME: This is ugly; it would be nice to have a better way to do this.
-void RenderView::setMaximalOutlineSize(int o)
-{
- if (o != m_maximalOutlineSize) {
- m_maximalOutlineSize = o;
-
- // maximalOutlineSize affects compositing layer dimensions.
- compositor()->setCompositingLayersNeedRebuild(); // FIXME: this really just needs to be a geometry update.
- }
-}
-
// When exploring the RenderTree looking for the nodes involved in the Selection, sometimes it's
// required to change the traversing direction because the "start" position is below the "end" one.
static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const RenderObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringBackwards)
@@ -810,7 +683,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
if (blockRepaintMode == RepaintNewXOROld) {
RenderBlock* cb = os->containingBlock();
while (cb && !cb->isRenderView()) {
- OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
+ OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).storedValue->value;
if (blockInfo)
break;
blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
@@ -865,7 +738,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)));
RenderBlock* cb = o->containingBlock();
while (cb && !cb->isRenderView()) {
- OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
+ OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).storedValue->value;
if (blockInfo)
break;
blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
@@ -879,8 +752,6 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
if (!m_frameView || blockRepaintMode == RepaintNothing)
return;
- FrameView::DeferredRepaintScope deferRepaints(*m_frameView);
-
// Have any of the old selected objects changed compared to the new selection?
for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
RenderObject* obj = i->key;
@@ -950,57 +821,6 @@ bool RenderView::shouldUsePrintingLayout() const
return m_frameView->frame().shouldUsePrintingLayout();
}
-size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets)
-{
- size_t size = m_widgets.size();
-
- renderWidgets.reserveCapacity(size);
-
- RenderWidgetSet::const_iterator end = m_widgets.end();
- for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) {
- renderWidgets.uncheckedAppend(*it);
- (*it)->ref();
- }
-
- return size;
-}
-
-void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets)
-{
- size_t size = renderWidgets.size();
-
- for (size_t i = 0; i < size; ++i)
- renderWidgets[i]->deref();
-}
-
-void RenderView::updateWidgetPositions()
-{
- // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running
- // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets
- // alive during enumeration.
-
- Vector<RenderWidget*> renderWidgets;
- size_t size = getRetainedWidgets(renderWidgets);
-
- for (size_t i = 0; i < size; ++i)
- renderWidgets[i]->updateWidgetPosition();
-
- for (size_t i = 0; i < size; ++i)
- renderWidgets[i]->widgetPositionsUpdated();
-
- releaseWidgets(renderWidgets);
-}
-
-void RenderView::addWidget(RenderWidget* o)
-{
- m_widgets.add(o);
-}
-
-void RenderView::removeWidget(RenderWidget* o)
-{
- m_widgets.remove(o);
-}
-
LayoutRect RenderView::viewRect() const
{
if (shouldUsePrintingLayout())
@@ -1019,12 +839,18 @@ IntRect RenderView::unscaledDocumentRect() const
bool RenderView::rootBackgroundIsEntirelyFixed() const
{
- RenderObject* rootObject = document().documentElement() ? document().documentElement()->renderer() : 0;
- if (!rootObject)
- return false;
+ if (RenderObject* backgroundRenderer = this->backgroundRenderer())
+ return backgroundRenderer->hasEntirelyFixedBackground();
+ return false;
+}
- RenderObject* rootRenderer = rootObject->rendererForRootBackground();
- return rootRenderer->hasEntirelyFixedBackground();
+RenderObject* RenderView::backgroundRenderer() const
+{
+ if (Element* documentElement = document().documentElement()) {
+ if (RenderObject* rootObject = documentElement->renderer())
+ return rootObject->rendererForRootBackground();
+ }
+ return 0;
}
LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
@@ -1049,7 +875,7 @@ IntRect RenderView::documentRect() const
return IntRect(overflowRect);
}
-int RenderView::viewHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const
+int RenderView::viewHeight(IncludeScrollbarsInRect scrollbarInclusion) const
{
int height = 0;
if (!shouldUsePrintingLayout() && m_frameView)
@@ -1058,7 +884,7 @@ int RenderView::viewHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarIncl
return height;
}
-int RenderView::viewWidth(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const
+int RenderView::viewWidth(IncludeScrollbarsInRect scrollbarInclusion) const
{
int width = 0;
if (!shouldUsePrintingLayout() && m_frameView)
@@ -1067,41 +893,21 @@ int RenderView::viewWidth(ScrollableArea::IncludeScrollbarsInRect scrollbarInclu
return width;
}
-int RenderView::viewLogicalHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion) const
-{
- int height = style()->isHorizontalWritingMode() ? viewHeight(scrollbarInclusion) : viewWidth(scrollbarInclusion);
-
- if (hasColumns() && !style()->hasInlineColumnAxis()) {
- if (int pageLength = m_frameView->pagination().pageLength)
- height = pageLength;
- }
-
- return height;
-}
-
-float RenderView::zoomFactor() const
+int RenderView::viewLogicalHeight() const
{
- return m_frameView->frame().pageZoomFactor();
+ return style()->isHorizontalWritingMode() ? viewHeight(ExcludeScrollbars) : viewWidth(ExcludeScrollbars);
}
-void RenderView::pushLayoutState(RenderObject* root)
+LayoutUnit RenderView::viewLogicalHeightForPercentages() const
{
- ASSERT(m_layoutStateDisableCount == 0);
- ASSERT(m_layoutState == 0);
-
- pushLayoutStateForCurrentFlowThread(root);
- m_layoutState = new LayoutState(root);
+ if (shouldUsePrintingLayout())
+ return pageLogicalHeight();
+ return viewLogicalHeight();
}
-bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
+float RenderView::zoomFactor() const
{
- RenderObject* o = renderer;
- while (o) {
- if (o->hasColumns() || o->hasTransform() || o->hasReflection())
- return true;
- o = o->container();
- }
- return false;
+ return m_frameView->frame().pageZoomFactor();
}
void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
@@ -1124,13 +930,13 @@ void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& p
bool RenderView::usesCompositing() const
{
- return m_compositor && m_compositor->inCompositingMode();
+ return m_compositor && m_compositor->staleInCompositingMode();
}
RenderLayerCompositor* RenderView::compositor()
{
if (!m_compositor)
- m_compositor = adoptPtr(new RenderLayerCompositor(this));
+ m_compositor = adoptPtr(new RenderLayerCompositor(*this));
return m_compositor.get();
}
@@ -1141,52 +947,28 @@ void RenderView::setIsInWindow(bool isInWindow)
m_compositor->setIsInWindow(isInWindow);
}
-CustomFilterGlobalContext* RenderView::customFilterGlobalContext()
-{
- if (!m_customFilterGlobalContext)
- m_customFilterGlobalContext = adoptPtr(new CustomFilterGlobalContext());
- return m_customFilterGlobalContext.get();
-}
-
-void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderBlock::styleDidChange(diff, oldStyle);
- if (hasRenderNamedFlowThreads())
- flowThreadController()->styleDidChange();
-}
-
-bool RenderView::hasRenderNamedFlowThreads() const
-{
- return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
-}
-
-bool RenderView::checkTwoPassLayoutForAutoHeightRegions() const
-{
- return hasRenderNamedFlowThreads() && m_flowThreadController->hasFlowThreadsWithAutoLogicalHeightRegions();
-}
-
FlowThreadController* RenderView::flowThreadController()
{
if (!m_flowThreadController)
- m_flowThreadController = FlowThreadController::create(this);
+ m_flowThreadController = FlowThreadController::create();
return m_flowThreadController.get();
}
-void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject* object)
+void RenderView::pushLayoutState(LayoutState& layoutState)
{
- if (!m_flowThreadController)
- return;
-
- RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
- if (!currentFlowThread)
- return;
-
- currentFlowThread->pushFlowThreadLayoutState(object);
+ if (m_flowThreadController) {
+ RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
+ if (currentFlowThread)
+ currentFlowThread->pushFlowThreadLayoutState(layoutState.renderer());
+ }
+ m_layoutState = &layoutState;
}
-void RenderView::popLayoutStateForCurrentFlowThread()
+void RenderView::popLayoutState()
{
+ ASSERT(m_layoutState);
+ m_layoutState = m_layoutState->next();
if (!m_flowThreadController)
return;
@@ -1207,70 +989,22 @@ IntervalArena* RenderView::intervalArena()
bool RenderView::backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const
{
// FIXME: Remove this main frame check. Same concept applies to subframes too.
- if (!m_frameView || !m_frameView->isMainFrame())
+ if (!frame()->isMainFrame())
return false;
return m_frameView->hasOpaqueBackground();
}
-LayoutUnit RenderView::viewportPercentageWidth(float percentage) const
-{
- return viewLogicalWidth(ScrollableArea::IncludeScrollbars) * percentage / 100.f;
-}
-
-LayoutUnit RenderView::viewportPercentageHeight(float percentage) const
+double RenderView::layoutViewportWidth() const
{
- return viewLogicalHeight(ScrollableArea::IncludeScrollbars) * percentage / 100.f;
+ float scale = m_frameView ? m_frameView->frame().pageZoomFactor() : 1;
+ return viewWidth(IncludeScrollbars) / scale;
}
-LayoutUnit RenderView::viewportPercentageMin(float percentage) const
+double RenderView::layoutViewportHeight() const
{
- return std::min(viewLogicalWidth(ScrollableArea::IncludeScrollbars), viewLogicalHeight(ScrollableArea::IncludeScrollbars))
- * percentage / 100.f;
-}
-
-LayoutUnit RenderView::viewportPercentageMax(float percentage) const
-{
- return std::max(viewLogicalWidth(ScrollableArea::IncludeScrollbars), viewLogicalHeight(ScrollableArea::IncludeScrollbars))
- * percentage / 100.f;
-}
-
-FragmentationDisabler::FragmentationDisabler(RenderObject* root)
-{
- RenderView* renderView = root->view();
- ASSERT(renderView);
-
- LayoutState* layoutState = renderView->layoutState();
-
- m_root = root;
- m_fragmenting = layoutState && layoutState->isPaginated();
- m_flowThreadState = m_root->flowThreadState();
-#ifndef NDEBUG
- m_layoutState = layoutState;
-#endif
-
- if (layoutState)
- layoutState->m_isPaginated = false;
-
- if (m_flowThreadState != RenderObject::NotInsideFlowThread)
- m_root->setFlowThreadStateIncludingDescendants(RenderObject::NotInsideFlowThread);
-}
-
-FragmentationDisabler::~FragmentationDisabler()
-{
- RenderView* renderView = m_root->view();
- ASSERT(renderView);
-
- LayoutState* layoutState = renderView->layoutState();
-#ifndef NDEBUG
- ASSERT(m_layoutState == layoutState);
-#endif
-
- if (layoutState)
- layoutState->m_isPaginated = m_fragmenting;
-
- if (m_flowThreadState != RenderObject::NotInsideFlowThread)
- m_root->setFlowThreadStateIncludingDescendants(m_flowThreadState);
+ float scale = m_frameView ? m_frameView->frame().pageZoomFactor() : 1;
+ return viewHeight(IncludeScrollbars) / scale;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderView.h b/chromium/third_party/WebKit/Source/core/rendering/RenderView.h
index 246db98be54..2ca7efbe591 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderView.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderView.h
@@ -23,7 +23,6 @@
#define RenderView_h
#include "core/frame/FrameView.h"
-#include "core/rendering/LayoutIndicator.h"
#include "core/rendering/LayoutState.h"
#include "core/rendering/RenderBlockFlow.h"
#include "platform/PODFreeListArena.h"
@@ -32,11 +31,9 @@
namespace WebCore {
-class CustomFilterGlobalContext;
class FlowThreadController;
class RenderLayerCompositor;
class RenderQuote;
-class RenderWidget;
// The root of the render tree, corresponding to the CSS initial containing block.
// It's dimensions match that of the logical viewport (which may be different from
@@ -54,7 +51,7 @@ public:
virtual bool isRenderView() const OVERRIDE { return true; }
- virtual bool requiresLayer() const OVERRIDE { return true; }
+ virtual LayerType layerTypeRequired() const OVERRIDE { return NormalLayer; }
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
@@ -62,31 +59,28 @@ public:
virtual void updateLogicalWidth() OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual bool supportsPartialLayout() const OVERRIDE { return true; }
-
virtual LayoutUnit availableLogicalHeight(AvailableLogicalHeightType) const OVERRIDE;
// The same as the FrameView's layoutHeight/layoutWidth but with null check guards.
- int viewHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion = ScrollableArea::ExcludeScrollbars) const;
- int viewWidth(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion = ScrollableArea::ExcludeScrollbars) const;
- int viewLogicalWidth(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion = ScrollableArea::ExcludeScrollbars) const
+ int viewHeight(IncludeScrollbarsInRect = ExcludeScrollbars) const;
+ int viewWidth(IncludeScrollbarsInRect = ExcludeScrollbars) const;
+ int viewLogicalWidth() const
{
- return style()->isHorizontalWritingMode() ? viewWidth(scrollbarInclusion) : viewHeight(scrollbarInclusion);
+ return style()->isHorizontalWritingMode() ? viewWidth(ExcludeScrollbars) : viewHeight(ExcludeScrollbars);
}
- int viewLogicalHeight(ScrollableArea::IncludeScrollbarsInRect scrollbarInclusion = ScrollableArea::ExcludeScrollbars) const;
+ int viewLogicalHeight() const;
+ LayoutUnit viewLogicalHeightForPercentages() const;
float zoomFactor() const;
FrameView* frameView() const { return m_frameView; }
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
void repaintViewRectangle(const LayoutRect&) const;
- // 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.
- void repaintRectangleInViewAndCompositedLayers(const LayoutRect&);
+
void repaintViewAndCompositedLayers();
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld, RepaintNothing };
@@ -99,61 +93,50 @@ public:
void selectionStartEnd(int& startPos, int& endPos) const;
void repaintSelection() const;
- virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
-
- void setMaximalOutlineSize(int o);
- int maximalOutlineSize() const { return m_maximalOutlineSize; }
-
- void setOldMaximalOutlineSize(int o) { m_oldMaximalOutlineSize = o; }
- int oldMaximalOutlineSize() const { return m_oldMaximalOutlineSize; }
+ virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
virtual LayoutRect viewRect() const OVERRIDE;
- void updateWidgetPositions();
- void addWidget(RenderWidget*);
- void removeWidget(RenderWidget*);
-
// layoutDelta is used transiently during layout to store how far an object has moved from its
// last layout location, in order to repaint correctly.
// If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
LayoutSize layoutDelta() const
{
- return m_layoutState ? m_layoutState->m_layoutDelta : LayoutSize();
+ ASSERT(!RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ return m_layoutState ? m_layoutState->layoutDelta() : LayoutSize();
}
void addLayoutDelta(const LayoutSize& delta)
{
- if (m_layoutState) {
- m_layoutState->m_layoutDelta += delta;
-#if !ASSERT_DISABLED
- m_layoutState->m_layoutDeltaXSaturated |= m_layoutState->m_layoutDelta.width() == LayoutUnit::max() || m_layoutState->m_layoutDelta.width() == LayoutUnit::min();
- m_layoutState->m_layoutDeltaYSaturated |= m_layoutState->m_layoutDelta.height() == LayoutUnit::max() || m_layoutState->m_layoutDelta.height() == LayoutUnit::min();
-#endif
- }
+ ASSERT(!RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ if (m_layoutState)
+ m_layoutState->addLayoutDelta(delta);
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool layoutDeltaMatches(const LayoutSize& delta)
{
+ ASSERT(!RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
if (!m_layoutState)
return false;
- return (delta.width() == m_layoutState->m_layoutDelta.width() || m_layoutState->m_layoutDeltaXSaturated) && (delta.height() == m_layoutState->m_layoutDelta.height() || m_layoutState->m_layoutDeltaYSaturated);
+ return (delta.width() == m_layoutState->layoutDelta().width() || m_layoutState->layoutDeltaXSaturated()) && (delta.height() == m_layoutState->layoutDelta().height() || m_layoutState->layoutDeltaYSaturated());
}
#endif
- bool doingFullRepaint() const { return m_frameView->needsFullRepaint(); }
-
- // Subtree push/pop
- void pushLayoutState(RenderObject*);
- void popLayoutState(RenderObject*) { return popLayoutState(); } // Just doing this to keep popLayoutState() private and to make the subtree calls symmetrical.
-
- bool shouldDisableLayoutStateForSubtree(RenderObject*) const;
+ bool shouldDoFullRepaintForNextLayout() const;
+ bool doingFullRepaint() const { return m_frameView->needsFullPaintInvalidation(); }
// Returns true if layoutState should be used for its cached offset and clip.
- bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; }
+ bool layoutStateCachedOffsetsEnabled() const { return m_layoutState && m_layoutState->cachedOffsetsEnabled(); }
LayoutState* layoutState() const { return m_layoutState; }
- virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
+ bool canMapUsingLayoutStateForContainer(const RenderObject* repaintContainer) const
+ {
+ // FIXME: LayoutState should be enabled for other repaint containers than the RenderView. crbug.com/363834
+ return layoutStateCachedOffsetsEnabled() && (repaintContainer == this);
+ }
+
+ virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) OVERRIDE;
LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
void setPageLogicalHeight(LayoutUnit height)
@@ -163,6 +146,7 @@ public:
m_pageLogicalHeightChanged = true;
}
}
+ bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
// Notification that this view moved into or out of a native window.
void setIsInWindow(bool);
@@ -170,8 +154,6 @@ public:
RenderLayerCompositor* compositor();
bool usesCompositing() const;
- CustomFilterGlobalContext* customFilterGlobalContext();
-
IntRect unscaledDocumentRect() const;
LayoutRect backgroundRect(RenderBox* backgroundRenderer) const;
@@ -180,12 +162,8 @@ public:
// Renderer that paints the root background has background-images which all have background-attachment: fixed.
bool rootBackgroundIsEntirelyFixed() const;
- bool hasRenderNamedFlowThreads() const;
- bool checkTwoPassLayoutForAutoHeightRegions() const;
FlowThreadController* flowThreadController();
- void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
IntervalArena* intervalArena();
void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; }
@@ -199,81 +177,39 @@ public:
void removeRenderCounter() { ASSERT(m_renderCounterCount > 0); m_renderCounterCount--; }
bool hasRenderCounters() { return m_renderCounterCount; }
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+ virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const OVERRIDE;
- virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const OVERRIDE FINAL;
-
- LayoutUnit viewportPercentageWidth(float percentage) const;
- LayoutUnit viewportPercentageHeight(float percentage) const;
- LayoutUnit viewportPercentageMin(float percentage) const;
- LayoutUnit viewportPercentageMax(float percentage) const;
+ double layoutViewportWidth() const;
+ double layoutViewportHeight() const;
+ void pushLayoutState(LayoutState&);
+ void popLayoutState();
private:
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
- virtual bool requiresColumns(int desiredColumnCount) const OVERRIDE;
+ virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
virtual void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const OVERRIDE;
- bool initializeLayoutState(LayoutState&);
-
- virtual void calcColumnWidth() OVERRIDE;
- virtual ColumnInfo::PaginationUnit paginationUnit() const OVERRIDE;
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer) OVERRIDE FINAL;
bool shouldRepaint(const LayoutRect&) const;
- // These functions may only be accessed by LayoutStateMaintainer.
- bool pushLayoutState(RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
- {
- // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
- if (!doingFullRepaint() || m_layoutState->isPaginated() || renderer->hasColumns() || renderer->flowThreadContainingBlock()
- || m_layoutState->lineGrid() || (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isRenderBlockFlow())
- || (renderer->isRenderBlock() && toRenderBlock(renderer)->shapeInsideInfo())
- || (m_layoutState->shapeInsideInfo() && renderer->isRenderBlock() && !toRenderBlock(renderer)->allowsShapeInsideInfoSharing(m_layoutState->shapeInsideInfo()->owner()))
- ) {
- pushLayoutStateForCurrentFlowThread(renderer);
- m_layoutState = new LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo);
- return true;
- }
- return false;
- }
-
- void popLayoutState()
- {
- LayoutState* state = m_layoutState;
- m_layoutState = state->m_next;
- delete state;
- popLayoutStateForCurrentFlowThread();
- }
-
- // Suspends the LayoutState optimization. Used under transforms that cannot be represented by
- // LayoutState (common in SVG) and when manipulating the render tree during layout in ways
- // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
- // Note that even when disabled, LayoutState is still used to store layoutDelta.
- // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler.
- void disableLayoutState() { m_layoutStateDisableCount++; }
- void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
+ bool rootFillsViewportBackground(RenderBox* rootBox) const;
- void layoutContent(const LayoutState&);
- void layoutContentInAutoLogicalHeightRegions(const LayoutState&);
+ void layoutContent();
#ifndef NDEBUG
- void checkLayoutState(const LayoutState&);
+ void checkLayoutState();
#endif
void positionDialog(RenderBox*);
void positionDialogs();
- size_t getRetainedWidgets(Vector<RenderWidget*>&);
- void releaseWidgets(Vector<RenderWidget*>&);
-
- void pushLayoutStateForCurrentFlowThread(const RenderObject*);
- void popLayoutStateForCurrentFlowThread();
-
- friend class LayoutStateMaintainer;
- friend class LayoutStateDisabler;
+ friend class ForceHorriblySlowRectMapping;
bool shouldUsePrintingLayout() const;
+ RenderObject* backgroundRenderer() const;
+
FrameView* m_frameView;
RenderObject* m_selectionStart;
@@ -282,18 +218,10 @@ private:
int m_selectionStartPos;
int m_selectionEndPos;
- int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
- int m_oldMaximalOutlineSize; // The fudge factor from the previous layout.
-
- typedef HashSet<RenderWidget*> RenderWidgetSet;
- RenderWidgetSet m_widgets;
-
LayoutUnit m_pageLogicalHeight;
bool m_pageLogicalHeightChanged;
LayoutState* m_layoutState;
- unsigned m_layoutStateDisableCount;
OwnPtr<RenderLayerCompositor> m_compositor;
- OwnPtr<CustomFilterGlobalContext> m_customFilterGlobalContext;
OwnPtr<FlowThreadController> m_flowThreadController;
RefPtr<IntervalArena> m_intervalArena;
@@ -303,99 +231,35 @@ private:
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderView, isRenderView());
-// Stack-based class to assist with LayoutState push/pop
-class LayoutStateMaintainer {
- WTF_MAKE_NONCOPYABLE(LayoutStateMaintainer);
+// Suspends the LayoutState cached offset and clipRect optimization. Used under transforms
+// that cannot be represented by LayoutState (common in SVG) and when manipulating the render
+// tree during layout in ways that can trigger repaint of a non-child (e.g. when a list item
+// moves its list marker around). Note that even when disabled, LayoutState is still used to
+// store layoutDelta.
+class ForceHorriblySlowRectMapping {
+ WTF_MAKE_NONCOPYABLE(ForceHorriblySlowRectMapping);
public:
- // ctor to push now
- LayoutStateMaintainer(RenderView* view, RenderBox* root, LayoutSize offset, bool disableState = false, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
- : m_view(view)
- , m_disabled(disableState)
- , m_didStart(false)
- , m_didEnd(false)
- , m_didCreateLayoutState(false)
+ ForceHorriblySlowRectMapping(const RenderObject& root)
+ : m_view(*root.view())
+ , m_didDisable(m_view.layoutState() && m_view.layoutState()->cachedOffsetsEnabled())
{
- push(root, offset, pageHeight, pageHeightChanged, colInfo);
- }
-
- // ctor to maybe push later
- LayoutStateMaintainer(RenderView* view)
- : m_view(view)
- , m_disabled(false)
- , m_didStart(false)
- , m_didEnd(false)
- , m_didCreateLayoutState(false)
- {
- }
-
- ~LayoutStateMaintainer()
- {
- ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop().
- }
-
- void push(RenderBox* root, LayoutSize offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
- {
- ASSERT(!m_didStart);
- // We push state even if disabled, because we still need to store layoutDelta
- m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, pageHeightChanged, colInfo);
- if (m_disabled && m_didCreateLayoutState)
- m_view->disableLayoutState();
- m_didStart = true;
- }
-
- void pop()
- {
- if (m_didStart) {
- ASSERT(!m_didEnd);
- if (m_didCreateLayoutState) {
- m_view->popLayoutState();
- if (m_disabled)
- m_view->enableLayoutState();
- }
-
- m_didEnd = true;
- }
- }
-
- bool didPush() const { return m_didStart; }
-
-private:
- RenderView* m_view;
- bool m_disabled : 1; // true if the offset and clip part of layoutState is disabled
- bool m_didStart : 1; // true if we did a push or disable
- bool m_didEnd : 1; // true if we popped or re-enabled
- bool m_didCreateLayoutState : 1; // true if we actually made a layout state.
-};
-
-class LayoutStateDisabler {
- WTF_MAKE_NONCOPYABLE(LayoutStateDisabler);
-public:
- LayoutStateDisabler(RenderView* view)
- : m_view(view)
- {
- if (m_view)
- m_view->disableLayoutState();
+ if (m_view.layoutState())
+ m_view.layoutState()->m_cachedOffsetsEnabled = false;
+#if ASSERT_ENABLED
+ m_layoutState = m_view.layoutState();
+#endif
}
- ~LayoutStateDisabler()
+ ~ForceHorriblySlowRectMapping()
{
- if (m_view)
- m_view->enableLayoutState();
+ ASSERT(m_view.layoutState() == m_layoutState);
+ if (m_didDisable)
+ m_view.layoutState()->m_cachedOffsetsEnabled = true;
}
private:
- RenderView* m_view;
-};
-
-class FragmentationDisabler {
- WTF_MAKE_NONCOPYABLE(FragmentationDisabler);
-public:
- FragmentationDisabler(RenderObject* root);
- ~FragmentationDisabler();
-private:
- RenderObject* m_root;
- RenderObject::FlowThreadState m_flowThreadState;
- bool m_fragmenting;
-#ifndef NDEBUG
+ RenderView& m_view;
+ bool m_didDisable;
+#if ASSERT_ENABLED
LayoutState* m_layoutState;
#endif
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.cpp
index 90b089686a8..43ecbdf8a8b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.cpp
@@ -25,89 +25,42 @@
#include "core/rendering/RenderWidget.h"
#include "core/accessibility/AXObjectCache.h"
-#include "core/frame/Frame.h"
-#include "core/rendering/CompositedLayerMapping.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLPlugInElement.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
-#include "platform/graphics/GraphicsContext.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "wtf/HashMap.h"
namespace WebCore {
-typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap;
-static WidgetToParentMap& widgetNewParentMap()
-{
- DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ());
- return map;
-}
-
-static unsigned s_updateSuspendCount = 0;
-
-RenderWidget::UpdateSuspendScope::UpdateSuspendScope()
-{
- ++s_updateSuspendCount;
-}
-
-RenderWidget::UpdateSuspendScope::~UpdateSuspendScope()
-{
- ASSERT(s_updateSuspendCount > 0);
- if (s_updateSuspendCount == 1) {
- WidgetToParentMap map;
- widgetNewParentMap().swap(map);
- WidgetToParentMap::iterator end = map.end();
- for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) {
- Widget* child = it->key.get();
- ScrollView* currentParent = toScrollView(child->parent());
- FrameView* newParent = it->value;
- if (newParent != currentParent) {
- if (currentParent)
- currentParent->removeChild(child);
- if (newParent)
- newParent->addChild(child);
- }
- }
- }
- --s_updateSuspendCount;
-}
-
-static void moveWidgetToParentSoon(Widget* child, FrameView* parent)
-{
- if (!s_updateSuspendCount) {
- if (parent)
- parent->addChild(child);
- else
- toScrollView(child->parent())->removeChild(child);
- return;
- }
- widgetNewParentMap().set(child, parent);
-}
-
RenderWidget::RenderWidget(Element* element)
: RenderReplaced(element)
- , m_widget(0)
- , m_frameView(element->document().view())
// Reference counting is used to prevent the widget from being
// destroyed while inside the Widget code, which might not be
// able to handle that.
, m_refCount(1)
{
- view()->addWidget(this);
+ ASSERT(element);
+ frameView()->addWidget(this);
}
void RenderWidget::willBeDestroyed()
{
- if (RenderView* v = view())
- v->removeWidget(this);
+ frameView()->removeWidget(this);
if (AXObjectCache* cache = document().existingAXObjectCache()) {
cache->childrenChanged(this->parent());
cache->remove(this);
}
- setWidget(0);
+ Element* element = toElement(node());
+ if (element && element->isFrameOwnerElement())
+ toHTMLFrameOwnerElement(element)->setWidget(nullptr);
RenderReplaced::willBeDestroyed();
}
@@ -122,7 +75,17 @@ void RenderWidget::destroy()
RenderWidget::~RenderWidget()
{
ASSERT(m_refCount <= 0);
- clearWidget();
+}
+
+Widget* RenderWidget::widget() const
+{
+ // Plugin widgets are stored in their DOM node. This includes HTMLAppletElement.
+ Element* element = toElement(node());
+
+ if (element && element->isFrameOwnerElement())
+ return toHTMLFrameOwnerElement(element)->ownedWidget();
+
+ return 0;
}
// Widgets are always placed on integer boundaries, so rounding the size is actually
@@ -138,35 +101,28 @@ bool RenderWidget::setWidgetGeometry(const LayoutRect& frame)
if (!node())
return false;
- IntRect clipRect = roundedIntRect(enclosingLayer()->childrenClipRect());
+ Widget* widget = this->widget();
+ ASSERT(widget);
+
IntRect newFrame = roundedIntRect(frame);
- bool clipChanged = m_clipRect != clipRect;
- bool frameRectChanged = m_widget->frameRect() != newFrame;
- if (!frameRectChanged && !clipChanged)
+ if (widget->frameRect() == newFrame)
return false;
- m_clipRect = clipRect;
-
RefPtr<RenderWidget> protector(this);
- RefPtr<Node> protectedNode(node());
- m_widget->setFrameRect(newFrame);
-
- if (clipChanged && !frameRectChanged)
- m_widget->clipRectChanged();
-
- if (hasLayer() && layer()->compositingState() == PaintsIntoOwnBacking)
- layer()->compositedLayerMapping()->updateAfterWidgetResize();
-
- bool boundsChanged = m_widget->frameRect().size() != newFrame.size();
- return boundsChanged;
+ RefPtrWillBeRawPtr<Node> protectedNode(node());
+ widget->setFrameRect(newFrame);
+ return widget->frameRect().size() != newFrame.size();
}
bool RenderWidget::updateWidgetGeometry()
{
+ Widget* widget = this->widget();
+ ASSERT(widget);
+
LayoutRect contentBox = contentBoxRect();
LayoutRect absoluteContentBox(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
- if (m_widget->isFrameView()) {
+ if (widget->isFrameView()) {
contentBox.setLocation(absoluteContentBox.location());
return setWidgetGeometry(contentBox);
}
@@ -174,54 +130,24 @@ bool RenderWidget::updateWidgetGeometry()
return setWidgetGeometry(absoluteContentBox);
}
-void RenderWidget::setWidget(PassRefPtr<Widget> widget)
-{
- if (widget == m_widget)
- return;
-
- if (m_widget) {
- moveWidgetToParentSoon(m_widget.get(), 0);
- clearWidget();
- }
- m_widget = widget;
- if (m_widget) {
- // If we've already received a layout, apply the calculated space to the
- // widget immediately, but we have to have really been fully constructed (with a non-null
- // style pointer).
- if (style()) {
- if (!needsLayout())
- updateWidgetGeometry();
-
- if (style()->visibility() != VISIBLE)
- m_widget->hide();
- else {
- m_widget->show();
- repaint();
- }
- }
- moveWidgetToParentSoon(m_widget.get(), m_frameView);
- }
-
- if (AXObjectCache* cache = document().existingAXObjectCache())
- cache->childrenChanged(this);
-}
-
void RenderWidget::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
clearNeedsLayout();
}
void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderReplaced::styleDidChange(diff, oldStyle);
- if (m_widget) {
- if (style()->visibility() != VISIBLE)
- m_widget->hide();
- else
- m_widget->show();
+ Widget* widget = this->widget();
+
+ if (widget) {
+ if (style()->visibility() != VISIBLE) {
+ widget->hide();
+ } else {
+ widget->show();
+ }
}
}
@@ -229,9 +155,12 @@ void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintO
{
LayoutPoint adjustedPaintOffset = paintOffset + location();
+ Widget* widget = this->widget();
+ ASSERT(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.
- IntPoint widgetLocation = m_widget->frameRect().location();
+ IntPoint widgetLocation = widget->frameRect().location();
IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()),
roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop()));
IntRect paintRect = paintInfo.rect;
@@ -240,20 +169,20 @@ void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintO
// 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()) {
- paintInfo.context->translate(widgetPaintOffset);
+ paintInfo.context->translate(widgetPaintOffset.width(), widgetPaintOffset.height());
paintRect.move(-widgetPaintOffset);
}
- m_widget->paint(paintInfo.context, paintRect);
+ widget->paint(paintInfo.context, paintRect);
if (!widgetPaintOffset.isZero())
- paintInfo.context->translate(-widgetPaintOffset);
+ paintInfo.context->translate(-widgetPaintOffset.width(), -widgetPaintOffset.height());
- if (m_widget->isFrameView()) {
- FrameView* frameView = toFrameView(m_widget.get());
+ if (widget->isFrameView()) {
+ FrameView* frameView = toFrameView(widget);
bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContent();
if (paintInfo.overlapTestRequests && runOverlapTests) {
ASSERT(!paintInfo.overlapTestRequests->contains(this));
- paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
+ paintInfo.overlapTestRequests->set(this, widget->frameRect());
}
}
}
@@ -278,7 +207,7 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && hasOutline())
paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
- if (!m_frameView || paintInfo.phase != PaintPhaseForeground)
+ if (paintInfo.phase != PaintPhaseForeground)
return;
if (style()->hasBorderRadius()) {
@@ -294,7 +223,8 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
clipRoundedInnerRect(paintInfo.context, borderRect, roundedInnerRect);
}
- if (m_widget)
+ Widget* widget = this->widget();
+ if (widget)
paintContents(paintInfo, paintOffset);
if (style()->hasBorderRadius())
@@ -312,9 +242,10 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
void RenderWidget::setIsOverlapped(bool isOverlapped)
{
- ASSERT(m_widget);
- ASSERT(m_widget->isFrameView());
- toFrameView(m_widget.get())->setIsOverlapped(isOverlapped);
+ Widget* widget = this->widget();
+ ASSERT(widget);
+ ASSERT(widget->isFrameView());
+ toFrameView(widget)->setIsOverlapped(isOverlapped);
}
void RenderWidget::deref()
@@ -323,17 +254,39 @@ void RenderWidget::deref()
postDestroy();
}
+void RenderWidget::updateOnWidgetChange()
+{
+ Widget* widget = this->widget();
+ if (!widget)
+ return;
+
+ if (!style())
+ return;
+
+ if (!needsLayout())
+ updateWidgetGeometry();
+
+ if (style()->visibility() != VISIBLE) {
+ widget->hide();
+ } else {
+ widget->show();
+ // FIXME: Why do we repaint in this case, but not the other?
+ paintInvalidationForWholeRenderer();
+ }
+}
+
void RenderWidget::updateWidgetPosition()
{
- if (!m_widget || !node()) // Check the node in case destroy() has been called.
+ Widget* widget = this->widget();
+ if (!widget || !node()) // Check the node in case destroy() has been called.
return;
bool boundsChanged = updateWidgetGeometry();
// if the frame bounds got changed, or if view needs layout (possibly indicating
// content size is wrong) we have to do a layout to set the right widget size
- if (m_widget && m_widget->isFrameView()) {
- FrameView* frameView = toFrameView(m_widget.get());
+ if (widget && widget->isFrameView()) {
+ FrameView* frameView = toFrameView(widget);
// Check the frame's page to make sure that the frame isn't in the process of being destroyed.
if ((boundsChanged || frameView->needsLayout()) && frameView->frame().page())
frameView->layout();
@@ -342,14 +295,10 @@ void RenderWidget::updateWidgetPosition()
void RenderWidget::widgetPositionsUpdated()
{
- if (!m_widget)
+ Widget* widget = this->widget();
+ if (!widget)
return;
- m_widget->widgetPositionsUpdated();
-}
-
-void RenderWidget::clearWidget()
-{
- m_widget = 0;
+ widget->widgetPositionsUpdated();
}
bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.h b/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.h
index 2cde8486906..7c29616245d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderWidget.h
@@ -31,9 +31,9 @@ class RenderWidget : public RenderReplaced {
public:
virtual ~RenderWidget();
- Widget* widget() const { return m_widget.get(); }
- virtual void setWidget(PassRefPtr<Widget>);
+ Widget* widget() const;
+ void updateOnWidgetChange();
void updateWidgetPosition();
void widgetPositionsUpdated();
@@ -42,37 +42,26 @@ public:
void ref() { ++m_refCount; }
void deref();
- class UpdateSuspendScope {
- public:
- UpdateSuspendScope();
- ~UpdateSuspendScope();
- };
+ virtual bool isWidget() const OVERRIDE FINAL { return true; }
+ bool updateWidgetGeometry();
protected:
explicit RenderWidget(Element*);
- void clearWidget();
-
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
- virtual void layout();
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
+ virtual void layout() OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const OVERRIDE FINAL;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual void paintContents(PaintInfo&, const LayoutPoint&);
private:
- virtual bool isWidget() const OVERRIDE FINAL { return true; }
-
virtual void willBeDestroyed() OVERRIDE FINAL;
virtual void destroy() OVERRIDE FINAL;
bool setWidgetGeometry(const LayoutRect&);
- bool updateWidgetGeometry();
- RefPtr<Widget> m_widget;
- FrameView* m_frameView;
- IntRect m_clipRect; // The rectangle needs to remain correct after scrolling, so it is stored in content view coordinates, and not clipped to window.
int m_refCount;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderWordBreak.h b/chromium/third_party/WebKit/Source/core/rendering/RenderWordBreak.h
index acf3c6075d0..d5b0d31c73d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderWordBreak.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderWordBreak.h
@@ -37,8 +37,8 @@ class RenderWordBreak FINAL : public RenderText {
public:
explicit RenderWordBreak(HTMLElement*);
- virtual const char* renderName() const;
- virtual bool isWordBreak() const;
+ virtual const char* renderName() const OVERRIDE;
+ virtual bool isWordBreak() const OVERRIDE;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.cpp
index 871cf0ff1ad..5b0a8fde96c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.cpp
@@ -47,7 +47,7 @@ COMPILE_ASSERT(sizeof(RootInlineBox) == sizeof(SameSizeAsRootInlineBox), RootInl
typedef WTF::HashMap<const RootInlineBox*, EllipsisBox*> EllipsisBoxMap;
static EllipsisBoxMap* gEllipsisBoxMap = 0;
-RootInlineBox::RootInlineBox(RenderBlockFlow* block)
+RootInlineBox::RootInlineBox(RenderBlockFlow& block)
: InlineFlowBox(block)
, m_lineBreakPos(0)
, m_lineBreakObj(0)
@@ -56,7 +56,7 @@ RootInlineBox::RootInlineBox(RenderBlockFlow* block)
, m_lineTopWithLeading(0)
, m_lineBottomWithLeading(0)
{
- setIsHorizontal(block->isHorizontalWritingMode());
+ setIsHorizontal(block.isHorizontalWritingMode());
}
@@ -78,7 +78,7 @@ void RootInlineBox::detachEllipsisBox()
RenderLineBoxList* RootInlineBox::rendererLineBoxes() const
{
- return block()->lineBoxes();
+ return block().lineBoxes();
}
void RootInlineBox::clearTruncation()
@@ -164,7 +164,7 @@ float RootInlineBox::placeEllipsisBox(bool ltr, float blockLeftEdge, float block
void RootInlineBox::paintEllipsisBox(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) const
{
- if (hasEllipsisBox() && paintInfo.shouldPaintWithinRoot(renderer()) && renderer()->style()->visibility() == VISIBLE
+ if (hasEllipsisBox() && paintInfo.shouldPaintWithinRoot(&renderer()) && renderer().style()->visibility() == VISIBLE
&& paintInfo.phase == PaintPhaseForeground)
ellipsisBox()->paint(paintInfo, paintOffset, lineTop, lineBottom);
}
@@ -179,7 +179,7 @@ bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
{
if (hasEllipsisBox() && visibleToHitTestRequest(request)) {
if (ellipsisBox()->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
- renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+ renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
return true;
}
}
@@ -200,38 +200,15 @@ void RootInlineBox::adjustPosition(float dx, float dy)
void RootInlineBox::childRemoved(InlineBox* box)
{
- if (box->renderer() == m_lineBreakObj)
+ if (&box->renderer() == m_lineBreakObj)
setLineBreakInfo(0, 0, BidiStatus());
- for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == box->renderer(); prev = prev->prevRootBox()) {
+ for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == &box->renderer(); prev = prev->prevRootBox()) {
prev->setLineBreakInfo(0, 0, BidiStatus());
prev->markDirty();
}
}
-RenderRegion* RootInlineBox::containingRegion() const
-{
- RenderRegion* region = m_fragmentationData ? m_fragmentationData->m_containingRegion : 0;
-
-#ifndef NDEBUG
- if (region) {
- RenderFlowThread* flowThread = block()->flowThreadContainingBlock();
- const RenderRegionList& regionList = flowThread->renderRegionList();
- ASSERT(regionList.contains(region));
- }
-#endif
-
- return region;
-}
-
-void RootInlineBox::setContainingRegion(RenderRegion* region)
-{
- ASSERT(!isDirty());
- ASSERT(block()->flowThreadContainingBlock());
- LineFragmentationData* fragmentationData = ensureLineFragmentationData();
- fragmentationData->m_containingRegion = region;
-}
-
LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache)
{
// SVG will handle vertical alignment on its own.
@@ -246,7 +223,7 @@ LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, G
bool setMaxDescent = false;
// Figure out if we're in no-quirks mode.
- bool noQuirksMode = renderer()->document().inNoQuirksMode();
+ bool noQuirksMode = renderer().document().inNoQuirksMode();
m_baselineType = requiresIdeographicBaseline(textBoxDataMap) ? IdeographicBaseline : AlphabeticBaseline;
@@ -272,22 +249,17 @@ LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, G
maxHeight = max<LayoutUnit>(0, maxHeight); // FIXME: Is this really necessary?
setLineTopBottomPositions(lineTop, lineBottom, heightOfBlock, heightOfBlock + maxHeight);
- setPaginatedLineWidth(block()->availableLogicalWidthForContent(heightOfBlock));
+ if (block().view()->layoutState()->isPaginated())
+ setPaginatedLineWidth(block().availableLogicalWidthForContent());
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.
- adjustBlockDirectionPosition(annotationsAdjustment);
+ adjustBlockDirectionPosition(annotationsAdjustment.toFloat());
heightOfBlock += annotationsAdjustment;
}
- LayoutUnit gridSnapAdjustment = lineSnapAdjustment();
- if (gridSnapAdjustment) {
- adjustBlockDirectionPosition(gridSnapAdjustment);
- heightOfBlock += gridSnapAdjustment;
- }
-
return heightOfBlock + maxHeight;
}
@@ -302,7 +274,7 @@ LayoutUnit RootInlineBox::beforeAnnotationsAdjustment() const
{
LayoutUnit result = 0;
- if (!renderer()->style()->isFlippedLinesWritingMode()) {
+ if (!renderer().style()->isFlippedLinesWritingMode()) {
// Annotations under the previous line may push us down.
if (prevRootBox() && prevRootBox()->hasAnnotationsAfter())
result = prevRootBox()->computeUnderAnnotationAdjustment(lineTop());
@@ -311,12 +283,12 @@ LayoutUnit RootInlineBox::beforeAnnotationsAdjustment() const
return result;
// Annotations over this line may push us further down.
- LayoutUnit highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) + result : static_cast<LayoutUnit>(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() : static_cast<LayoutUnit>(block()->borderBefore()));
+ result = computeUnderAnnotationAdjustment(prevRootBox() ? prevRootBox()->lineBottom() : static_cast<LayoutUnit>(block().borderBefore()));
if (!prevRootBox() || !prevRootBox()->hasAnnotationsAfter())
return result;
@@ -329,115 +301,26 @@ LayoutUnit RootInlineBox::beforeAnnotationsAdjustment() const
return result;
}
-LayoutUnit RootInlineBox::lineSnapAdjustment(LayoutUnit delta) const
-{
- // If our block doesn't have snapping turned on, do nothing.
- // FIXME: Implement bounds snapping.
- if (block()->style()->lineSnap() == LineSnapNone)
- return 0;
-
- // Get the current line grid and offset.
- LayoutState* layoutState = block()->view()->layoutState();
- RenderBlockFlow* lineGrid = layoutState->lineGrid();
- LayoutSize lineGridOffset = layoutState->lineGridOffset();
- if (!lineGrid || lineGrid->style()->writingMode() != block()->style()->writingMode())
- return 0;
-
- // Get the hypothetical line box used to establish the grid.
- RootInlineBox* lineGridBox = lineGrid->lineGridBox();
- if (!lineGridBox)
- return 0;
-
- LayoutUnit lineGridBlockOffset = lineGrid->isHorizontalWritingMode() ? lineGridOffset.height() : lineGridOffset.width();
- LayoutUnit blockOffset = block()->isHorizontalWritingMode() ? layoutState->layoutOffset().height() : layoutState->layoutOffset().width();
-
- // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple
- // as established by the line box.
- // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume
- // the grid should honor line-box-contain.
- LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading();
- if (!gridLineHeight)
- return 0;
-
- LayoutUnit lineGridFontAscent = lineGrid->style()->fontMetrics().ascent(baselineType());
- LayoutUnit lineGridFontHeight = lineGridBox->logicalHeight();
- LayoutUnit firstTextTop = lineGridBlockOffset + lineGridBox->logicalTop();
- LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading();
- LayoutUnit firstBaselinePosition = firstTextTop + lineGridFontAscent;
-
- LayoutUnit currentTextTop = blockOffset + logicalTop() + delta;
- LayoutUnit currentFontAscent = block()->style()->fontMetrics().ascent(baselineType());
- LayoutUnit currentBaselinePosition = currentTextTop + currentFontAscent;
-
- LayoutUnit lineGridPaginationOrigin = isHorizontal() ? layoutState->lineGridPaginationOrigin().height() : layoutState->lineGridPaginationOrigin().width();
-
- // If we're paginated, see if we're on a page after the first one. If so, the grid resets on subsequent pages.
- // FIXME: If the grid is an ancestor of the pagination establisher, then this is incorrect.
- LayoutUnit pageLogicalTop = 0;
- if (layoutState->isPaginated() && layoutState->pageLogicalHeight()) {
- pageLogicalTop = block()->pageLogicalTopForOffset(lineTopWithLeading() + delta);
- if (pageLogicalTop > firstLineTopWithLeading)
- firstTextTop = pageLogicalTop + lineGridBox->logicalTop() - lineGrid->borderBefore() - lineGrid->paddingBefore() + lineGridPaginationOrigin;
- }
-
- if (block()->style()->lineSnap() == LineSnapContain) {
- // Compute the desired offset from the text-top of a grid line.
- // Look at our height (logicalHeight()).
- // Look at the total available height. It's going to be (textBottom - textTop) + (n-1)*(multiple with leading)
- // where n is number of grid lines required to enclose us.
- if (logicalHeight() <= lineGridFontHeight)
- firstTextTop += (lineGridFontHeight - logicalHeight()) / 2;
- else {
- LayoutUnit numberOfLinesWithLeading = ceilf(static_cast<float>(logicalHeight() - lineGridFontHeight) / gridLineHeight);
- LayoutUnit totalHeight = lineGridFontHeight + numberOfLinesWithLeading * gridLineHeight;
- firstTextTop += (totalHeight - logicalHeight()) / 2;
- }
- firstBaselinePosition = firstTextTop + currentFontAscent;
- } else
- firstBaselinePosition = firstTextTop + lineGridFontAscent;
-
- // If we're above the first line, just push to the first line.
- if (currentBaselinePosition < firstBaselinePosition)
- return delta + firstBaselinePosition - currentBaselinePosition;
-
- // Otherwise we're in the middle of the grid somewhere. Just push to the next line.
- LayoutUnit baselineOffset = currentBaselinePosition - firstBaselinePosition;
- LayoutUnit remainder = roundToInt(baselineOffset) % roundToInt(gridLineHeight);
- LayoutUnit result = delta;
- if (remainder)
- result += gridLineHeight - remainder;
-
- // If we aren't paginated we can return the result.
- if (!layoutState->isPaginated() || !layoutState->pageLogicalHeight() || result == delta)
- return result;
-
- // We may end up shifted to a new page. We need to do a re-snap when that happens.
- LayoutUnit newPageLogicalTop = block()->pageLogicalTopForOffset(lineBottomWithLeading() + result);
- if (newPageLogicalTop == pageLogicalTop)
- return result;
-
- // Put ourselves at the top of the next page to force a snap onto the new grid established by that page.
- return lineSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading()));
-}
-
GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
LayoutUnit selTop, LayoutUnit selHeight, const PaintInfo* paintInfo)
{
RenderObject::SelectionState lineState = selectionState();
bool leftGap, rightGap;
- block()->getSelectionGapInfo(lineState, leftGap, rightGap);
+ block().getSelectionGapInfo(lineState, leftGap, rightGap);
GapRects result;
InlineBox* firstBox = firstSelectedBox();
InlineBox* lastBox = lastSelectedBox();
- if (leftGap)
- result.uniteLeft(block()->logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
- firstBox->parent()->renderer(), firstBox->logicalLeft(), selTop, selHeight, paintInfo));
- if (rightGap)
- result.uniteRight(block()->logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
- lastBox->parent()->renderer(), lastBox->logicalRight(), selTop, selHeight, paintInfo));
+ if (leftGap) {
+ result.uniteLeft(block().logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
+ &firstBox->parent()->renderer(), firstBox->logicalLeft(), selTop, selHeight, paintInfo));
+ }
+ if (rightGap) {
+ result.uniteRight(block().logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
+ &lastBox->parent()->renderer(), lastBox->logicalRight(), selTop, selHeight, paintInfo));
+ }
// When dealing with bidi text, a non-contiguous selection region is possible.
// e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out
@@ -453,11 +336,11 @@ GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoi
for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) {
if (box->selectionState() != RenderObject::SelectionNone) {
LayoutRect logicalRect(lastLogicalLeft, selTop, box->logicalLeft() - lastLogicalLeft, selHeight);
- logicalRect.move(renderer()->isHorizontalWritingMode() ? offsetFromRootBlock : LayoutSize(offsetFromRootBlock.height(), offsetFromRootBlock.width()));
+ logicalRect.move(renderer().isHorizontalWritingMode() ? offsetFromRootBlock : LayoutSize(offsetFromRootBlock.height(), offsetFromRootBlock.width()));
LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
if (isPreviousBoxSelected && gapRect.width() > 0 && gapRect.height() > 0) {
- if (paintInfo && box->parent()->renderer()->style()->visibility() == VISIBLE)
- paintInfo->context->fillRect(gapRect, box->parent()->renderer()->selectionBackgroundColor());
+ if (paintInfo && box->parent()->renderer().style()->visibility() == VISIBLE)
+ paintInfo->context->fillRect(gapRect, box->parent()->renderer().selectionBackgroundColor());
// VisibleSelection may be non-contiguous, see comment above.
result.uniteCenter(gapRect);
}
@@ -521,20 +404,20 @@ LayoutUnit RootInlineBox::selectionTop() const
LayoutUnit selectionTop = m_lineTop;
if (m_hasAnnotationsBefore)
- selectionTop -= !renderer()->style()->isFlippedLinesWritingMode() ? computeOverAnnotationAdjustment(m_lineTop) : computeUnderAnnotationAdjustment(m_lineTop);
+ selectionTop -= !renderer().style()->isFlippedLinesWritingMode() ? computeOverAnnotationAdjustment(m_lineTop) : computeUnderAnnotationAdjustment(m_lineTop);
- if (renderer()->style()->isFlippedLinesWritingMode())
+ if (renderer().style()->isFlippedLinesWritingMode() || !prevRootBox())
return selectionTop;
- LayoutUnit prevBottom = prevRootBox() ? prevRootBox()->selectionBottom() : block()->borderBefore() + block()->paddingBefore();
- if (prevBottom < selectionTop && block()->containsFloats()) {
+ LayoutUnit prevBottom = prevRootBox()->selectionBottom();
+ if (prevBottom < selectionTop && block().containsFloats()) {
// This line has actually been moved further down, probably from a large line-height, but possibly because the
// line was forced to clear floats. If so, let's check the offsets, and only be willing to use the previous
// line's bottom if the offsets are greater on both sides.
- LayoutUnit prevLeft = block()->logicalLeftOffsetForLine(prevBottom, false);
- LayoutUnit prevRight = block()->logicalRightOffsetForLine(prevBottom, false);
- LayoutUnit newLeft = block()->logicalLeftOffsetForLine(selectionTop, false);
- LayoutUnit newRight = block()->logicalRightOffsetForLine(selectionTop, false);
+ LayoutUnit prevLeft = block().logicalLeftOffsetForLine(prevBottom, false);
+ LayoutUnit prevRight = block().logicalRightOffsetForLine(prevBottom, false);
+ LayoutUnit newLeft = block().logicalLeftOffsetForLine(selectionTop, false);
+ LayoutUnit newRight = block().logicalRightOffsetForLine(selectionTop, false);
if (prevLeft > newLeft || prevRight < newRight)
return selectionTop;
}
@@ -546,12 +429,12 @@ LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
{
LayoutUnit top = selectionTop();
- RenderObject::SelectionState blockSelectionState = root()->block()->selectionState();
+ 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 (RenderBlock* block = root().block().blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
if (RootInlineBox* lastLine = block->lastRootBox()) {
RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
@@ -570,20 +453,20 @@ LayoutUnit RootInlineBox::selectionBottom() const
LayoutUnit selectionBottom = m_lineBottom;
if (m_hasAnnotationsAfter)
- selectionBottom += !renderer()->style()->isFlippedLinesWritingMode() ? computeUnderAnnotationAdjustment(m_lineBottom) : computeOverAnnotationAdjustment(m_lineBottom);
+ selectionBottom += !renderer().style()->isFlippedLinesWritingMode() ? computeUnderAnnotationAdjustment(m_lineBottom) : computeOverAnnotationAdjustment(m_lineBottom);
- if (!renderer()->style()->isFlippedLinesWritingMode() || !nextRootBox())
+ if (!renderer().style()->isFlippedLinesWritingMode() || !nextRootBox())
return selectionBottom;
LayoutUnit nextTop = nextRootBox()->selectionTop();
- if (nextTop > selectionBottom && block()->containsFloats()) {
+ if (nextTop > selectionBottom && block().containsFloats()) {
// The next line has actually been moved further over, probably from a large line-height, but possibly because the
// line was forced to clear floats. If so, let's check the offsets, and only be willing to use the next
// line's top if the offsets are greater on both sides.
- LayoutUnit nextLeft = block()->logicalLeftOffsetForLine(nextTop, false);
- LayoutUnit nextRight = block()->logicalRightOffsetForLine(nextTop, false);
- LayoutUnit newLeft = block()->logicalLeftOffsetForLine(selectionBottom, false);
- LayoutUnit newRight = block()->logicalRightOffsetForLine(selectionBottom, false);
+ LayoutUnit nextLeft = block().logicalLeftOffsetForLine(nextTop, false);
+ LayoutUnit nextRight = block().logicalRightOffsetForLine(nextTop, false);
+ LayoutUnit newLeft = block().logicalLeftOffsetForLine(selectionBottom, false);
+ LayoutUnit newRight = block().logicalRightOffsetForLine(selectionBottom, false);
if (nextLeft > newLeft || nextRight < newRight)
return selectionBottom;
}
@@ -593,22 +476,22 @@ LayoutUnit RootInlineBox::selectionBottom() const
int RootInlineBox::blockDirectionPointInLine() const
{
- return !block()->style()->isFlippedBlocksWritingMode() ? max(lineTop(), selectionTop()) : min(lineBottom(), selectionBottom());
+ return !block().style()->isFlippedBlocksWritingMode() ? max(lineTop(), selectionTop()) : min(lineBottom(), selectionBottom());
}
-RenderBlockFlow* RootInlineBox::block() const
+RenderBlockFlow& RootInlineBox::block() const
{
return toRenderBlockFlow(renderer());
}
static bool isEditableLeaf(InlineBox* leaf)
{
- return leaf && leaf->renderer() && leaf->renderer()->node() && leaf->renderer()->node()->rendererIsEditable();
+ return leaf && leaf->renderer().node() && leaf->renderer().node()->rendererIsEditable();
}
InlineBox* RootInlineBox::closestLeafChildForPoint(const IntPoint& pointInContents, bool onlyEditableLeaves)
{
- return closestLeafChildForLogicalLeftPosition(block()->isHorizontalWritingMode() ? pointInContents.x() : pointInContents.y(), onlyEditableLeaves);
+ return closestLeafChildForLogicalLeftPosition(block().isHorizontalWritingMode() ? pointInContents.x() : pointInContents.y(), onlyEditableLeaves);
}
InlineBox* RootInlineBox::closestLeafChildForLogicalLeftPosition(int leftPosition, bool onlyEditableLeaves)
@@ -627,19 +510,19 @@ InlineBox* RootInlineBox::closestLeafChildForLogicalLeftPosition(int leftPositio
return firstLeaf;
// Avoid returning a list marker when possible.
- if (leftPosition <= firstLeaf->logicalLeft() && !firstLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
+ if (leftPosition <= firstLeaf->logicalLeft() && !firstLeaf->renderer().isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
// The leftPosition coordinate is less or equal to left edge of the firstLeaf.
// Return it.
return firstLeaf;
- if (leftPosition >= lastLeaf->logicalRight() && !lastLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf)))
+ if (leftPosition >= lastLeaf->logicalRight() && !lastLeaf->renderer().isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf)))
// The leftPosition coordinate is greater or equal to right edge of the lastLeaf.
// Return it.
return lastLeaf;
InlineBox* closestLeaf = 0;
for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChildIgnoringLineBreak()) {
- if (!leaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
+ if (!leaf->renderer().isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
closestLeaf = leaf;
if (leftPosition < leaf->logicalRight())
// The x coordinate is less than the right edge of the box.
@@ -682,17 +565,17 @@ EllipsisBox* RootInlineBox::ellipsisBox() const
void RootInlineBox::removeLineBoxFromRenderObject()
{
- block()->lineBoxes()->removeLineBox(this);
+ block().lineBoxes()->removeLineBox(this);
}
void RootInlineBox::extractLineBoxFromRenderObject()
{
- block()->lineBoxes()->extractLineBox(this);
+ block().lineBoxes()->extractLineBox(this);
}
void RootInlineBox::attachLineBoxToRenderObject()
{
- block()->lineBoxes()->attachLineBox(this);
+ block().lineBoxes()->attachLineBox(this);
}
LayoutRect RootInlineBox::paddedLayoutOverflowRect(LayoutUnit endPadding) const
@@ -735,8 +618,8 @@ 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(isFirstLineStyle())->lineBoxContain() & LineBoxContainReplaced) {
+ if (box->renderer().isReplaced()) {
+ if (renderer().style(isFirstLineStyle())->lineBoxContain() & LineBoxContainReplaced) {
ascent = box->baselinePosition(baselineType());
descent = box->lineHeight() - ascent;
@@ -761,8 +644,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
bool setUsedFont = false;
bool setUsedFontWithLeading = false;
- if (usedFonts && !usedFonts->isEmpty() && (includeFont || (box->renderer()->style(isFirstLineStyle())->lineHeight().isNegative() && includeLeading))) {
- usedFonts->append(box->renderer()->style(isFirstLineStyle())->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();
int usedFontAscent = fontMetrics.ascent(baselineType());
@@ -800,8 +683,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
}
if (includeFontForBox(box) && !setUsedFont) {
- int fontAscent = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
- int fontDescent = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent(baselineType());
+ int fontAscent = box->renderer().style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
+ int fontDescent = box->renderer().style(isFirstLineStyle())->fontMetrics().descent(baselineType());
setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet);
affectsAscent = fontAscent - box->logicalTop() > 0;
affectsDescent = fontDescent + box->logicalTop() > 0;
@@ -811,14 +694,14 @@ 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(isFirstLineStyle())->fontMetrics().ascent(baselineType())));
- glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - box->renderer()->style(isFirstLineStyle())->fontMetrics().descent(baselineType())));
+ glyphOverflow->top = min(glyphOverflow->top, max(0, glyphOverflow->top - box->renderer().style(isFirstLineStyle())->fontMetrics().ascent(baselineType())));
+ glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - box->renderer().style(isFirstLineStyle())->fontMetrics().descent(baselineType())));
}
if (includeMarginForBox(box)) {
- LayoutUnit ascentWithMargin = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
- LayoutUnit descentWithMargin = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent(baselineType());
- if (box->parent() && !box->renderer()->isText()) {
+ LayoutUnit ascentWithMargin = box->renderer().style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
+ LayoutUnit descentWithMargin = box->renderer().style(isFirstLineStyle())->fontMetrics().descent(baselineType());
+ 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();
}
@@ -832,7 +715,7 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositionCache& verticalPositionCache)
{
- if (box->renderer()->isText())
+ if (box->renderer().isText())
return box->parent()->logicalTop();
RenderBoxModelObject* renderer = box->boxModelObject();
@@ -865,7 +748,7 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio
if (verticalAlign != BASELINE) {
const Font& font = parent->style(firstLine)->font();
const FontMetrics& fontMetrics = font.fontMetrics();
- int fontSize = font.pixelSize();
+ int fontSize = font.fontDescription().computedPixelSize();
LineDirectionMode lineDirection = parent->isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
@@ -891,7 +774,7 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio
lineHeight = renderer->style()->computedLineHeight();
else
lineHeight = renderer->lineHeight(firstLine, lineDirection);
- verticalPosition -= valueForLength(renderer->style()->verticalAlignLength(), lineHeight, renderer->view());
+ verticalPosition -= valueForLength(renderer->style()->verticalAlignLength(), lineHeight);
}
}
@@ -904,45 +787,45 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio
bool RootInlineBox::includeLeadingForBox(InlineBox* box) const
{
- if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+ if (box->renderer().isReplaced() || (box->renderer().isText() && !box->isText()))
return false;
- LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+ LineBoxContain lineBoxContain = renderer().style()->lineBoxContain();
return (lineBoxContain & LineBoxContainInline) || (box == this && (lineBoxContain & LineBoxContainBlock));
}
bool RootInlineBox::includeFontForBox(InlineBox* box) const
{
- if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+ if (box->renderer().isReplaced() || (box->renderer().isText() && !box->isText()))
return false;
if (!box->isText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren())
return false;
// For now map "glyphs" to "font" in vertical text mode until the bounds returned by glyphs aren't garbage.
- LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+ LineBoxContain lineBoxContain = renderer().style()->lineBoxContain();
return (lineBoxContain & LineBoxContainFont) || (!isHorizontal() && (lineBoxContain & LineBoxContainGlyphs));
}
bool RootInlineBox::includeGlyphsForBox(InlineBox* box) const
{
- if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+ if (box->renderer().isReplaced() || (box->renderer().isText() && !box->isText()))
return false;
if (!box->isText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren())
return false;
// FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
- LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+ LineBoxContain lineBoxContain = renderer().style()->lineBoxContain();
return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
}
bool RootInlineBox::includeMarginForBox(InlineBox* box) const
{
- if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+ if (box->renderer().isReplaced() || (box->renderer().isText() && !box->isText()))
return false;
- LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+ LineBoxContain lineBoxContain = renderer().style()->lineBoxContain();
return lineBoxContain & LineBoxContainInlineBox;
}
@@ -950,13 +833,13 @@ bool RootInlineBox::includeMarginForBox(InlineBox* box) const
bool RootInlineBox::fitsToGlyphs() const
{
// FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
- LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+ LineBoxContain lineBoxContain = renderer().style()->lineBoxContain();
return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
}
bool RootInlineBox::includesRootLineBoxFontOrLeading() const
{
- LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+ LineBoxContain lineBoxContain = renderer().style()->lineBoxContain();
return (lineBoxContain & LineBoxContainBlock) || (lineBoxContain & LineBoxContainInline) || (lineBoxContain & LineBoxContainFont);
}
@@ -965,9 +848,9 @@ Node* RootInlineBox::getLogicalStartBoxWithNode(InlineBox*& startBox) const
Vector<InlineBox*> leafBoxesInLogicalOrder;
collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
for (size_t i = 0; i < leafBoxesInLogicalOrder.size(); ++i) {
- if (leafBoxesInLogicalOrder[i]->renderer()->node()) {
+ if (leafBoxesInLogicalOrder[i]->renderer().node()) {
startBox = leafBoxesInLogicalOrder[i];
- return startBox->renderer()->node();
+ return startBox->renderer().node();
}
}
startBox = 0;
@@ -979,9 +862,9 @@ Node* RootInlineBox::getLogicalEndBoxWithNode(InlineBox*& endBox) const
Vector<InlineBox*> leafBoxesInLogicalOrder;
collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
for (size_t i = leafBoxesInLogicalOrder.size(); i > 0; --i) {
- if (leafBoxesInLogicalOrder[i - 1]->renderer()->node()) {
+ if (leafBoxesInLogicalOrder[i - 1]->renderer().node()) {
endBox = leafBoxesInLogicalOrder[i - 1];
- return endBox->renderer()->node();
+ return endBox->renderer().node();
}
}
endBox = 0;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.h b/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.h
index 7dfde5faf5b..32b1c55221d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/RootInlineBox.h
@@ -29,14 +29,13 @@ namespace WebCore {
class EllipsisBox;
class HitTestResult;
class RenderBlockFlow;
-class RenderRegion;
struct BidiStatus;
struct GapRects;
class RootInlineBox : public InlineFlowBox {
public:
- explicit RootInlineBox(RenderBlockFlow*);
+ explicit RootInlineBox(RenderBlockFlow&);
virtual void destroy() OVERRIDE FINAL;
@@ -64,9 +63,6 @@ public:
LayoutUnit paginatedLineWidth() const { return m_fragmentationData ? m_fragmentationData->m_paginatedLineWidth : LayoutUnit(0); }
void setPaginatedLineWidth(LayoutUnit width) { ensureLineFragmentationData()->m_paginatedLineWidth = width; }
- RenderRegion* containingRegion() const;
- void setContainingRegion(RenderRegion*);
-
LayoutUnit selectionTop() const;
LayoutUnit selectionBottom() const;
LayoutUnit selectionHeight() const { return max<LayoutUnit>(0, selectionBottom() - selectionTop()); }
@@ -117,7 +113,7 @@ public:
virtual int baselinePosition(FontBaseline baselineType) const OVERRIDE FINAL;
virtual LayoutUnit lineHeight() const OVERRIDE FINAL;
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE FINAL;
using InlineBox::hasSelectedChildren;
@@ -129,7 +125,7 @@ public:
GapRects lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, LayoutUnit selTop, LayoutUnit selHeight, const PaintInfo*);
- RenderBlockFlow* block() const;
+ RenderBlockFlow& block() const;
InlineBox* closestLeafChildForPoint(const IntPoint&, bool onlyEditableLeaves);
InlineBox* closestLeafChildForLogicalLeftPosition(int, bool onlyEditableLeaves = false);
@@ -189,11 +185,9 @@ public:
Node* getLogicalEndBoxWithNode(InlineBox*&) const;
#ifndef NDEBUG
- virtual const char* boxName() const;
+ virtual const char* boxName() const OVERRIDE;
#endif
private:
- LayoutUnit lineSnapAdjustment(LayoutUnit delta = 0) const;
-
LayoutUnit beforeAnnotationsAdjustment() const;
struct LineFragmentationData;
@@ -223,17 +217,13 @@ private:
WTF_MAKE_NONCOPYABLE(LineFragmentationData); WTF_MAKE_FAST_ALLOCATED;
public:
LineFragmentationData()
- : m_containingRegion(0)
- , m_paginationStrut(0)
+ : m_paginationStrut(0)
, m_paginatedLineWidth(0)
, m_isFirstAfterPageBreak(false)
{
}
- // It should not be assumed the |containingRegion| is always valid.
- // It can also be 0 if the flow has no region chain.
- RenderRegion* m_containingRegion;
LayoutUnit m_paginationStrut;
LayoutUnit m_paginatedLineWidth;
bool m_isFirstAfterPageBreak;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ScrollBehavior.cpp b/chromium/third_party/WebKit/Source/core/rendering/ScrollAlignment.cpp
index d331f1dc07b..433a0864815 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ScrollBehavior.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/ScrollAlignment.cpp
@@ -42,24 +42,24 @@
*/
#include "config.h"
-#include "core/rendering/ScrollBehavior.h"
+#include "core/rendering/ScrollAlignment.h"
#include "platform/geometry/LayoutRect.h"
namespace WebCore {
-const ScrollAlignment ScrollAlignment::alignCenterIfNeeded = { noScroll, alignCenter, alignToClosestEdge };
-const ScrollAlignment ScrollAlignment::alignToEdgeIfNeeded = { noScroll, alignToClosestEdge, alignToClosestEdge };
-const ScrollAlignment ScrollAlignment::alignCenterAlways = { alignCenter, alignCenter, alignCenter };
-const ScrollAlignment ScrollAlignment::alignTopAlways = { alignTop, alignTop, alignTop };
-const ScrollAlignment ScrollAlignment::alignBottomAlways = { alignBottom, alignBottom, alignBottom };
+const ScrollAlignment ScrollAlignment::alignCenterIfNeeded = { ScrollAlignmentNoScroll, ScrollAlignmentCenter, ScrollAlignmentClosestEdge };
+const ScrollAlignment ScrollAlignment::alignToEdgeIfNeeded = { ScrollAlignmentNoScroll, ScrollAlignmentClosestEdge, ScrollAlignmentClosestEdge };
+const ScrollAlignment ScrollAlignment::alignCenterAlways = { ScrollAlignmentCenter, ScrollAlignmentCenter, ScrollAlignmentCenter };
+const ScrollAlignment ScrollAlignment::alignTopAlways = { ScrollAlignmentTop, ScrollAlignmentTop, ScrollAlignmentTop };
+const ScrollAlignment ScrollAlignment::alignBottomAlways = { ScrollAlignmentBottom, ScrollAlignmentBottom, ScrollAlignmentBottom };
#define MIN_INTERSECT_FOR_REVEAL 32
LayoutRect ScrollAlignment::getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
{
// Determine the appropriate X behavior.
- ScrollBehavior scrollX;
+ ScrollAlignmentBehavior scrollX;
LayoutRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
LayoutUnit intersectWidth = intersection(visibleRect, exposeRectX).width();
if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL) {
@@ -70,8 +70,8 @@ LayoutRect ScrollAlignment::getRectToExpose(const LayoutRect& visibleRect, const
} else if (intersectWidth == visibleRect.width()) {
// If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
scrollX = getVisibleBehavior(alignX);
- if (scrollX == alignCenter)
- scrollX = noScroll;
+ if (scrollX == ScrollAlignmentCenter)
+ scrollX = ScrollAlignmentNoScroll;
} else if (intersectWidth > 0) {
// If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
scrollX = getPartialBehavior(alignX);
@@ -79,29 +79,29 @@ LayoutRect ScrollAlignment::getRectToExpose(const LayoutRect& visibleRect, const
scrollX = getHiddenBehavior(alignX);
}
- if (scrollX == alignToClosestEdge) {
+ if (scrollX == ScrollAlignmentClosestEdge) {
// Closest edge is the right in two cases:
// (1) exposeRect to the right of and smaller than visibleRect
// (2) exposeRect to the left of and larger than visibleRect
if ((exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width())
|| (exposeRect.maxX() < visibleRect.maxX() && exposeRect.width() > visibleRect.width())) {
- scrollX = alignRight;
+ scrollX = ScrollAlignmentRight;
}
}
// Given the X behavior, compute the X coordinate.
LayoutUnit x;
- if (scrollX == noScroll)
+ if (scrollX == ScrollAlignmentNoScroll)
x = visibleRect.x();
- else if (scrollX == alignRight)
+ else if (scrollX == ScrollAlignmentRight)
x = exposeRect.maxX() - visibleRect.width();
- else if (scrollX == alignCenter)
+ else if (scrollX == ScrollAlignmentCenter)
x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
else
x = exposeRect.x();
// Determine the appropriate Y behavior.
- ScrollBehavior scrollY;
+ ScrollAlignmentBehavior scrollY;
LayoutRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
LayoutUnit intersectHeight = intersection(visibleRect, exposeRectY).height();
if (intersectHeight == exposeRect.height()) {
@@ -110,8 +110,8 @@ LayoutRect ScrollAlignment::getRectToExpose(const LayoutRect& visibleRect, const
} else if (intersectHeight == visibleRect.height()) {
// If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
scrollY = getVisibleBehavior(alignY);
- if (scrollY == alignCenter)
- scrollY = noScroll;
+ if (scrollY == ScrollAlignmentCenter)
+ scrollY = ScrollAlignmentNoScroll;
} else if (intersectHeight > 0) {
// If the rectangle is partially visible, use the specified partial behavior
scrollY = getPartialBehavior(alignY);
@@ -119,23 +119,23 @@ LayoutRect ScrollAlignment::getRectToExpose(const LayoutRect& visibleRect, const
scrollY = getHiddenBehavior(alignY);
}
- if (scrollY == alignToClosestEdge) {
+ if (scrollY == ScrollAlignmentClosestEdge) {
// Closest edge is the bottom in two cases:
// (1) exposeRect below and smaller than visibleRect
// (2) exposeRect above and larger than visibleRect
if ((exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height())
|| (exposeRect.maxY() < visibleRect.maxY() && exposeRect.height() > visibleRect.height())) {
- scrollY = alignBottom;
+ scrollY = ScrollAlignmentBottom;
}
}
// Given the Y behavior, compute the Y coordinate.
LayoutUnit y;
- if (scrollY == noScroll)
+ if (scrollY == ScrollAlignmentNoScroll)
y = visibleRect.y();
- else if (scrollY == alignBottom)
+ else if (scrollY == ScrollAlignmentBottom)
y = exposeRect.maxY() - visibleRect.height();
- else if (scrollY == alignCenter)
+ else if (scrollY == ScrollAlignmentCenter)
y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
else
y = exposeRect.y();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/ScrollBehavior.h b/chromium/third_party/WebKit/Source/core/rendering/ScrollAlignment.h
index 7c683d874a0..f22b1d9d6a8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/ScrollBehavior.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/ScrollAlignment.h
@@ -41,27 +41,27 @@
* version of this file under any of the LGPL, the MPL or the GPL.
*/
-#ifndef ScrollBehavior_h
-#define ScrollBehavior_h
+#ifndef ScrollAlignment_h
+#define ScrollAlignment_h
namespace WebCore {
-enum ScrollBehavior {
- noScroll,
- alignCenter,
- alignTop,
- alignBottom,
- alignLeft,
- alignRight,
- alignToClosestEdge
+enum ScrollAlignmentBehavior {
+ ScrollAlignmentNoScroll,
+ ScrollAlignmentCenter,
+ ScrollAlignmentTop,
+ ScrollAlignmentBottom,
+ ScrollAlignmentLeft,
+ ScrollAlignmentRight,
+ ScrollAlignmentClosestEdge
};
class LayoutRect;
struct ScrollAlignment {
- static ScrollBehavior getVisibleBehavior(const ScrollAlignment& s) { return s.m_rectVisible; }
- static ScrollBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
- static ScrollBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
+ static ScrollAlignmentBehavior getVisibleBehavior(const ScrollAlignment& s) { return s.m_rectVisible; }
+ static ScrollAlignmentBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
+ static ScrollAlignmentBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
// FIXME: This function should probably go somewhere else but where?
static LayoutRect getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
@@ -72,12 +72,12 @@ struct ScrollAlignment {
static const ScrollAlignment alignTopAlways;
static const ScrollAlignment alignBottomAlways;
- ScrollBehavior m_rectVisible;
- ScrollBehavior m_rectHidden;
- ScrollBehavior m_rectPartial;
+ ScrollAlignmentBehavior m_rectVisible;
+ ScrollAlignmentBehavior m_rectHidden;
+ ScrollAlignmentBehavior m_rectPartial;
};
}; // namespace WebCore
-#endif // ScrollBehavior_h
+#endif // ScrollAlignment_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.cpp b/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.cpp
index d650513a1c8..a5793a69e9a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.cpp
@@ -36,21 +36,15 @@
namespace WebCore {
-SubtreeLayoutScope::SubtreeLayoutScope(RenderObject* root)
+SubtreeLayoutScope::SubtreeLayoutScope(RenderObject& root)
: m_root(root)
{
- RELEASE_ASSERT(m_root->document().view()->isInLayout());
+ RELEASE_ASSERT(m_root.document().view()->isInPerformLayout());
}
SubtreeLayoutScope::~SubtreeLayoutScope()
{
- // Partial layout early-exits layout and will leave the tree as needing layout.
- if (m_root->frameView()->partialLayout().isStopping()) {
- ASSERT(m_root->needsLayout());
- return;
- }
-
- RELEASE_ASSERT(!m_root->needsLayout());
+ RELEASE_ASSERT(!m_root.needsLayout());
#ifndef NDEBUG
for (HashSet<RenderObject*>::iterator it = m_renderersToLayout.begin(); it != m_renderersToLayout.end(); ++it)
@@ -60,13 +54,13 @@ SubtreeLayoutScope::~SubtreeLayoutScope()
void SubtreeLayoutScope::setNeedsLayout(RenderObject* descendant)
{
- ASSERT(descendant->isDescendantOf(m_root));
- descendant->setNeedsLayout(MarkContainingBlockChain, this);
+ ASSERT(descendant->isDescendantOf(&m_root));
+ descendant->setNeedsLayoutAndFullPaintInvalidation(MarkContainingBlockChain, this);
}
void SubtreeLayoutScope::setChildNeedsLayout(RenderObject* descendant)
{
- ASSERT(descendant->isDescendantOf(m_root));
+ ASSERT(descendant->isDescendantOf(&m_root));
descendant->setChildNeedsLayout(MarkContainingBlockChain, this);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.h b/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.h
index c073b7f4cf1..fc9219ff5da 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/SubtreeLayoutScope.h
@@ -48,17 +48,17 @@ class RenderObject;
class SubtreeLayoutScope {
public:
- SubtreeLayoutScope(RenderObject* root);
+ SubtreeLayoutScope(RenderObject& root);
~SubtreeLayoutScope();
void setNeedsLayout(RenderObject* descendant);
void setChildNeedsLayout(RenderObject* descendant);
- RenderObject* root() { return m_root; }
+ RenderObject& root() { return m_root; }
void addRendererToLayout(RenderObject* renderer);
private:
- RenderObject* m_root;
+ RenderObject& m_root;
#ifndef NDEBUG
HashSet<RenderObject*> m_renderersToLayout;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.cpp b/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.cpp
index bc57d66cfab..290c008fa79 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.cpp
@@ -24,9 +24,11 @@
#include <algorithm>
#include "core/dom/Document.h"
-#include "core/html/HTMLElement.h"
-#include "core/inspector/InspectorInstrumentation.h"
+#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
+#include "core/frame/UseCounter.h"
+#include "core/html/HTMLElement.h"
+#include "core/page/Page.h"
#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/RenderText.h"
@@ -36,10 +38,11 @@
#include "platform/TraceEvent.h"
#include "platform/geometry/IntSize.h"
#include "wtf/StdLibExtras.h"
-#include "wtf/Vector.h"
namespace WebCore {
+#define AUTOSIZING_CLUSTER_HASH
+
using namespace HTMLNames;
struct TextAutosizingWindowInfo {
@@ -47,26 +50,25 @@ struct TextAutosizingWindowInfo {
IntSize minLayoutSize;
};
-// Represents cluster related data. Instances should not persist between calls to processSubtree.
-struct TextAutosizingClusterInfo {
- explicit TextAutosizingClusterInfo(RenderBlock* root)
- : root(root)
- , blockContainingAllText(0)
- , maxAllowedDifferenceFromTextWidth(150)
+// Represents a POD of a selection of fields for hashing. The fields are selected to detect similar
+// nodes in the Render Tree from the viewpoint of text autosizing.
+struct RenderObjectPodForHash {
+ RenderObjectPodForHash()
+ : qualifiedNameHash(0)
+ , packedStyleProperties(0)
+ , width(0)
{
}
+ ~RenderObjectPodForHash() { }
- RenderBlock* root;
- const RenderBlock* blockContainingAllText;
+ unsigned qualifiedNameHash;
- // Upper limit on the difference between the width of the cluster's block containing all
- // text and that of a narrow child before the child becomes a separate cluster.
- float maxAllowedDifferenceFromTextWidth;
-
- // Descendants of the cluster that are narrower than the block containing all text and must be
- // processed together.
- Vector<TextAutosizingClusterInfo> narrowDescendants;
+ // Style specific selection of signals
+ unsigned packedStyleProperties;
+ float width;
};
+// To allow for efficient hashing using StringHasher.
+COMPILE_ASSERT(!(sizeof(RenderObjectPodForHash) % sizeof(UChar)), RenderObjectPodForHashMultipleOfUchar);
#ifdef AUTOSIZING_DOM_DEBUG_INFO
static void writeDebugInfo(RenderObject* renderObject, const AtomicString& output)
@@ -104,48 +106,115 @@ static RenderObject* getAncestorList(const RenderObject* renderer)
// see http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element
for (RenderObject* ancestor = renderer->parent(); ancestor; ancestor = ancestor->parent()) {
Node* parentNode = ancestor->generatingNode();
- if (parentNode && (parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag)))
+ if (parentNode && (isHTMLOListElement(*parentNode) || isHTMLUListElement(*parentNode)))
return ancestor;
}
return 0;
}
+static Node* getGeneratingElementNode(const RenderObject* renderer)
+{
+ Node* node = renderer->generatingNode();
+ return (node && node->isElementNode()) ? node : 0;
+}
+
+static unsigned hashMemory(const void* data, size_t length)
+{
+ return StringHasher::computeHash<UChar>(static_cast<const UChar*>(data), length / sizeof(UChar));
+}
+
+static unsigned computeLocalHash(const RenderObject* renderer)
+{
+ Node* generatingElementNode = getGeneratingElementNode(renderer);
+ ASSERT(generatingElementNode);
+
+ RenderObjectPodForHash podForHash;
+ podForHash.qualifiedNameHash = QualifiedNameHash::hash(toElement(generatingElementNode)->tagQName());
+
+ if (RenderStyle* style = renderer->style()) {
+ podForHash.packedStyleProperties = style->direction();
+ podForHash.packedStyleProperties |= (style->position() << 1);
+ podForHash.packedStyleProperties |= (style->floating() << 4);
+ podForHash.packedStyleProperties |= (style->display() << 6);
+ podForHash.packedStyleProperties |= (style->width().type() << 11);
+ // packedStyleProperties effectively using 15 bits now.
+
+ // consider for adding: writing mode, padding.
+
+ podForHash.width = style->width().getFloatValue();
+ }
+
+ return hashMemory(&podForHash, sizeof(podForHash));
+}
+
TextAutosizer::TextAutosizer(Document* document)
: m_document(document)
+ , m_previouslyAutosized(false)
+{
+}
+
+unsigned TextAutosizer::getCachedHash(const RenderObject* renderer, bool putInCacheIfAbsent)
{
+ HashMap<const RenderObject*, unsigned>::const_iterator it = m_hashCache.find(renderer);
+ if (it != m_hashCache.end())
+ return it->value;
+
+ RenderObject* rendererParent = renderer->parent();
+ while (rendererParent && !getGeneratingElementNode(rendererParent))
+ rendererParent = rendererParent->parent();
+
+ const unsigned parentHashValue = rendererParent ? getCachedHash(rendererParent, true) : 0;
+ const unsigned hashes[2] = { parentHashValue, computeLocalHash(renderer) };
+ const unsigned combinedHashValue = hashMemory(hashes, sizeof(hashes));
+ if (putInCacheIfAbsent)
+ m_hashCache.add(renderer, combinedHashValue);
+ return combinedHashValue;
+}
+
+bool TextAutosizer::isApplicable() const
+{
+ return m_document->settings()
+ && m_document->settings()->textAutosizingEnabled()
+ && m_document->page()
+ && m_document->page()->mainFrame()
+ && m_document->page()->deprecatedLocalMainFrame()->loader().stateMachine()->committedFirstRealDocumentLoad();
}
void TextAutosizer::recalculateMultipliers()
{
- RenderObject* renderer = m_document->renderer();
+ if (!isApplicable() && !m_previouslyAutosized)
+ return;
+
+ RenderObject* renderer = m_document->renderView();
while (renderer) {
if (renderer->style() && renderer->style()->textAutosizingMultiplier() != 1)
setMultiplier(renderer, 1);
renderer = renderer->nextInPreOrder();
}
+ m_previouslyAutosized = false;
}
bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
{
- TRACE_EVENT0("webkit", "TextAutosizer::processSubtree");
+ TRACE_EVENT0("webkit", "TextAutosizer: check if needed");
- if (!m_document->settings() || !m_document->settings()->textAutosizingEnabled() || layoutRoot->view()->document().printing() || !m_document->page())
+ if (!isApplicable() || layoutRoot->view()->document().printing())
return false;
- Frame* mainFrame = m_document->page()->mainFrame();
-
+ LocalFrame* mainFrame = m_document->page()->deprecatedLocalMainFrame();
TextAutosizingWindowInfo windowInfo;
// Window area, in logical (density-independent) pixels.
windowInfo.windowSize = m_document->settings()->textAutosizingWindowSizeOverride();
if (windowInfo.windowSize.isEmpty())
- windowInfo.windowSize = mainFrame->view()->unscaledVisibleContentSize(ScrollableArea::IncludeScrollbars);
+ windowInfo.windowSize = mainFrame->view()->unscaledVisibleContentSize(IncludeScrollbars);
// Largest area of block that can be visible at once (assuming the main
// frame doesn't get scaled to less than overview scale), in CSS pixels.
windowInfo.minLayoutSize = mainFrame->view()->layoutSize();
- for (Frame* frame = m_document->frame(); frame; frame = frame->tree().parent())
- windowInfo.minLayoutSize = windowInfo.minLayoutSize.shrunkTo(frame->view()->layoutSize());
+ for (Frame* frame = m_document->frame(); frame; frame = frame->tree().parent()) {
+ windowInfo.minLayoutSize = windowInfo.minLayoutSize.shrunkTo(toLocalFrame(frame)->view()->layoutSize());
+ }
// The layoutRoot could be neither a container nor a cluster, so walk up the tree till we find each of these.
RenderBlock* container = layoutRoot->isRenderBlock() ? toRenderBlock(layoutRoot) : layoutRoot->containingBlock();
@@ -163,9 +232,21 @@ bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
std::numeric_limits<float>::infinity()) == 1.0f)
return false;
+ TRACE_EVENT0("webkit", "TextAutosizer: process root cluster");
+ UseCounter::count(*m_document, UseCounter::TextAutosizing);
+
TextAutosizingClusterInfo clusterInfo(cluster);
processCluster(clusterInfo, container, layoutRoot, windowInfo);
- InspectorInstrumentation::didAutosizeText(layoutRoot);
+
+#ifdef AUTOSIZING_CLUSTER_HASH
+ // Second pass to autosize stale non-autosized clusters for consistency.
+ secondPassProcessStaleNonAutosizedClusters();
+ m_hashCache.clear();
+ m_hashToMultiplier.clear();
+ m_hashesToAutosizeSecondPass.clear();
+ m_nonAutosizedClusters.clear();
+#endif
+ m_previouslyAutosized = true;
return true;
}
@@ -180,9 +261,10 @@ float TextAutosizer::clusterMultiplier(WritingMode writingMode, const TextAutosi
multiplier *= m_document->settings()->accessibilityFontScaleFactor();
// If the page has a meta viewport or @viewport, don't apply the device scale adjustment.
- const ViewportDescription& viewportDescription = m_document->page()->mainFrame()->document()->viewportDescription();
+ const ViewportDescription& viewportDescription = m_document->page()->deprecatedLocalMainFrame()->document()->viewportDescription();
if (!viewportDescription.isSpecifiedByAuthor()) {
- multiplier *= m_document->settings()->deviceScaleAdjustment();
+ float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustment();
+ multiplier *= deviceScaleAdjustment;
}
return std::max(1.0f, multiplier);
}
@@ -191,7 +273,7 @@ void TextAutosizer::processClusterInternal(TextAutosizingClusterInfo& clusterInf
{
processContainer(multiplier, container, clusterInfo, subtreeRoot, windowInfo);
#ifdef AUTOSIZING_DOM_DEBUG_INFO
- writeDebugInfo(clusterInfo.root, String::format("cluster:%f", multiplier));
+ writeDebugInfo(clusterInfo.root, AtomicString(String::format("cluster:%f", multiplier)));
#endif
Vector<Vector<TextAutosizingClusterInfo> > narrowDescendantsGroups;
@@ -200,6 +282,58 @@ void TextAutosizer::processClusterInternal(TextAutosizingClusterInfo& clusterInf
processCompositeCluster(narrowDescendantsGroups[i], windowInfo);
}
+unsigned TextAutosizer::computeCompositeClusterHash(Vector<TextAutosizingClusterInfo>& clusterInfos)
+{
+ if (clusterInfos.size() == 1 && getGeneratingElementNode(clusterInfos[0].root))
+ return getCachedHash(clusterInfos[0].root, false);
+
+ // FIXME: consider hashing clusters for which clusterInfos.size() > 1
+ return 0;
+}
+
+void TextAutosizer::addNonAutosizedCluster(unsigned key, TextAutosizingClusterInfo& value)
+{
+ HashMap<unsigned, OwnPtr<Vector<TextAutosizingClusterInfo> > >::const_iterator it = m_nonAutosizedClusters.find(key);
+ if (it == m_nonAutosizedClusters.end()) {
+ m_nonAutosizedClusters.add(key, adoptPtr(new Vector<TextAutosizingClusterInfo>(1, value)));
+ return;
+ }
+ it->value->append(value);
+}
+
+float TextAutosizer::computeMultiplier(Vector<TextAutosizingClusterInfo>& clusterInfos, const TextAutosizingWindowInfo& windowInfo, float textWidth)
+{
+#ifdef AUTOSIZING_CLUSTER_HASH
+ // When hashing is enabled this function returns a multiplier based on previously seen clusters.
+ // It will return a non-unit multiplier if a cluster with the same hash value has been previously
+ // autosized.
+ unsigned clusterHash = computeCompositeClusterHash(clusterInfos);
+#else
+ unsigned clusterHash = 0;
+#endif
+
+ if (clusterHash) {
+ HashMap<unsigned, float>::iterator it = m_hashToMultiplier.find(clusterHash);
+ if (it != m_hashToMultiplier.end())
+ return it->value;
+ }
+
+ if (compositeClusterShouldBeAutosized(clusterInfos, textWidth)) {
+ float multiplier = clusterMultiplier(clusterInfos[0].root->style()->writingMode(), windowInfo, textWidth);
+ if (clusterHash) {
+ if (multiplier > 1 && m_nonAutosizedClusters.contains(clusterHash))
+ m_hashesToAutosizeSecondPass.append(clusterHash);
+ m_hashToMultiplier.add(clusterHash, multiplier);
+ }
+ return multiplier;
+ }
+
+ if (clusterHash)
+ addNonAutosizedCluster(clusterHash, clusterInfos[0]);
+
+ return 1.0f;
+}
+
void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
{
// Many pages set a max-width on their content. So especially for the RenderView, instead of
@@ -207,10 +341,11 @@ void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, Rende
// descendant text node of the cluster (i.e. the deepest wrapper block that contains all the
// text), and use its width instead.
clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
- float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth();
- float multiplier = 1.0;
- if (clusterShouldBeAutosized(clusterInfo, textWidth))
- multiplier = clusterMultiplier(clusterInfo.root->style()->writingMode(), windowInfo, textWidth);
+ float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth().toFloat();
+
+ Vector<TextAutosizingClusterInfo> clusterInfos(1, clusterInfo);
+ float multiplier = computeMultiplier(clusterInfos, windowInfo, textWidth);
+
processClusterInternal(clusterInfo, container, subtreeRoot, windowInfo, multiplier);
}
@@ -223,18 +358,52 @@ void TextAutosizer::processCompositeCluster(Vector<TextAutosizingClusterInfo>& c
for (size_t i = 0; i < clusterInfos.size(); ++i) {
TextAutosizingClusterInfo& clusterInfo = clusterInfos[i];
clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
- maxTextWidth = max<float>(maxTextWidth, clusterInfo.blockContainingAllText->contentLogicalWidth());
+ maxTextWidth = max<float>(maxTextWidth, clusterInfo.blockContainingAllText->contentLogicalWidth().toFloat());
}
- float multiplier = 1.0;
- if (compositeClusterShouldBeAutosized(clusterInfos, maxTextWidth))
- multiplier = clusterMultiplier(clusterInfos[0].root->style()->writingMode(), windowInfo, maxTextWidth);
+ float multiplier = computeMultiplier(clusterInfos, windowInfo, maxTextWidth);
for (size_t i = 0; i < clusterInfos.size(); ++i) {
ASSERT(clusterInfos[i].root->style()->writingMode() == clusterInfos[0].root->style()->writingMode());
processClusterInternal(clusterInfos[i], clusterInfos[i].root, clusterInfos[i].root, windowInfo, multiplier);
}
}
+void TextAutosizer::secondPassProcessStaleNonAutosizedClusters()
+{
+ for (size_t i = 0; i < m_hashesToAutosizeSecondPass.size(); ++i) {
+ unsigned hash = m_hashesToAutosizeSecondPass[i];
+ float multiplier = m_hashToMultiplier.get(hash);
+ Vector<TextAutosizingClusterInfo>* val = m_nonAutosizedClusters.get(hash);
+ for (Vector<TextAutosizingClusterInfo>::iterator it2 = val->begin(); it2 != val->end(); ++it2)
+ processStaleContainer(multiplier, (*it2).root, *it2);
+ }
+}
+
+void TextAutosizer::processStaleContainer(float multiplier, RenderBlock* cluster, TextAutosizingClusterInfo& clusterInfo)
+{
+ ASSERT(isAutosizingContainer(cluster));
+
+ // This method is different from processContainer() mainly in that it does not recurse into sub-clusters.
+ // Multiplier updates are restricted to the specified cluster only. Also the multiplier > 1 by construction
+ // of m_hashesToAutosizeSecondPass, so we don't need to check it explicitly.
+ float localMultiplier = containerShouldBeAutosized(cluster) ? multiplier : 1;
+
+ RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(cluster, cluster);
+ while (descendant) {
+ if (descendant->isText()) {
+ if (localMultiplier != 1 && descendant->style()->textAutosizingMultiplier() == 1) {
+ setMultiplier(descendant, localMultiplier);
+ setMultiplier(descendant->parent(), localMultiplier); // Parent does line spacing.
+ }
+ } else if (isAutosizingContainer(descendant)) {
+ RenderBlock* descendantBlock = toRenderBlock(descendant);
+ if (!isAutosizingCluster(descendantBlock, clusterInfo))
+ processStaleContainer(multiplier, descendantBlock, clusterInfo);
+ }
+ descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, cluster);
+ }
+}
+
void TextAutosizer::processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo& clusterInfo, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
{
ASSERT(isAutosizingContainer(container));
@@ -242,7 +411,7 @@ void TextAutosizer::processContainer(float multiplier, RenderBlock* container, T
writeDebugInfo(container, "container");
#endif
- float localMultiplier = containerShouldBeAutosized(container) ? multiplier: 1;
+ float localMultiplier = (multiplier > 1 && containerShouldBeAutosized(container)) ? multiplier: 1;
RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(subtreeRoot, subtreeRoot);
while (descendant) {
@@ -287,12 +456,12 @@ void TextAutosizer::setMultiplierForList(RenderObject* renderer, float multiplie
#ifndef NDEBUG
Node* parentNode = renderer->generatingNode();
ASSERT(parentNode);
- ASSERT(parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag));
+ ASSERT(isHTMLOListElement(parentNode) || isHTMLUListElement(parentNode));
#endif
setMultiplier(renderer, multiplier);
// Make sure all list items are autosized consistently.
- for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = renderer->slowFirstChild(); child; child = child->nextSibling()) {
if (child->isListItem() && child->style()->textAutosizingMultiplier() == 1)
setMultiplier(child, multiplier);
}
@@ -337,7 +506,7 @@ bool TextAutosizer::isAutosizingContainer(const RenderObject* renderer)
// - Must not be normal list items, as items in the same list should look
// consistent, unless they are floating or position:absolute/fixed.
Node* node = renderer->generatingNode();
- if ((node && !node->hasChildNodes())
+ if ((node && !node->hasChildren())
|| !renderer->isRenderBlock()
|| (renderer->isInline() && !renderer->style()->isDisplayReplacedType()))
return false;
@@ -367,14 +536,14 @@ bool TextAutosizer::isNarrowDescendant(const RenderBlock* renderer, TextAutosizi
// the enclosing cluster. This 150px limit is adjusted whenever a descendant container is
// less than 50px narrower than the current limit.
const float differenceFromMaxWidthDifference = 50;
- float contentWidth = renderer->contentLogicalWidth();
- float clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
- float widthDifference = clusterTextWidth - contentWidth;
+ LayoutUnit contentWidth = renderer->contentLogicalWidth();
+ LayoutUnit clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
+ LayoutUnit widthDifference = clusterTextWidth - contentWidth;
if (widthDifference - parentClusterInfo.maxAllowedDifferenceFromTextWidth > differenceFromMaxWidthDifference)
return true;
- parentClusterInfo.maxAllowedDifferenceFromTextWidth = std::max(widthDifference, parentClusterInfo.maxAllowedDifferenceFromTextWidth);
+ parentClusterInfo.maxAllowedDifferenceFromTextWidth = std::max(widthDifference.toFloat(), parentClusterInfo.maxAllowedDifferenceFromTextWidth);
return false;
}
@@ -384,8 +553,8 @@ bool TextAutosizer::isWiderDescendant(const RenderBlock* renderer, const TextAut
// Autosizing containers that are wider than the |blockContainingAllText| of their enclosing
// cluster are treated the same way as autosizing clusters to be autosized separately.
- float contentWidth = renderer->contentLogicalWidth();
- float clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
+ LayoutUnit contentWidth = renderer->contentLogicalWidth();
+ LayoutUnit clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
return contentWidth > clusterTextWidth;
}
@@ -412,6 +581,7 @@ bool TextAutosizer::isIndependentDescendant(const RenderBlock* renderer)
// from the box's parent (we want to avoid having significantly different
// width blocks within a cluster, since the narrower blocks would end up
// larger than would otherwise be necessary).
+ RenderBlock* containingBlock = renderer->containingBlock();
return renderer->isRenderView()
|| renderer->isFloating()
|| renderer->isOutOfFlowPositioned()
@@ -419,7 +589,7 @@ bool TextAutosizer::isIndependentDescendant(const RenderBlock* renderer)
|| renderer->isTableCaption()
|| renderer->isFlexibleBoxIncludingDeprecated()
|| renderer->hasColumns()
- || renderer->containingBlock()->isHorizontalWritingMode() != renderer->isHorizontalWritingMode()
+ || (containingBlock && containingBlock->isHorizontalWritingMode() != renderer->isHorizontalWritingMode())
|| renderer->style()->isDisplayReplacedType()
|| renderer->isTextArea()
|| renderer->style()->userModify() != READ_ONLY;
@@ -520,7 +690,7 @@ bool TextAutosizer::contentHeightIsConstrained(const RenderBlock* container)
if (style->height().isSpecified() || style->maxHeight().isSpecified() || container->isOutOfFlowPositioned()) {
// Some sites (e.g. wikipedia) set their html and/or body elements to height:100%,
// without intending to constrain the height of the content within them.
- return !container->isRoot() && !container->isBody();
+ return !container->isDocumentElement() && !container->isBody();
}
if (container->isFloating())
return false;
@@ -528,12 +698,6 @@ bool TextAutosizer::contentHeightIsConstrained(const RenderBlock* container)
return false;
}
-bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterInfo, float blockWidth)
-{
- Vector<TextAutosizingClusterInfo> clusterInfos(1, clusterInfo);
- return compositeClusterShouldBeAutosized(clusterInfos, blockWidth);
-}
-
bool TextAutosizer::compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>& clusterInfos, float blockWidth)
{
// Don't autosize clusters that contain less than 4 lines of text (in
@@ -634,11 +798,11 @@ const RenderBlock* TextAutosizer::findDeepestBlockContainingAllText(const Render
const RenderObject* TextAutosizer::findFirstTextLeafNotInCluster(const RenderObject* parent, size_t& depth, TraversalDirection direction)
{
- if (parent->isEmpty())
- return parent->isText() ? parent : 0;
+ if (parent->isText())
+ return parent;
++depth;
- const RenderObject* child = (direction == FirstToLast) ? parent->firstChild() : parent->lastChild();
+ const RenderObject* child = (direction == FirstToLast) ? parent->slowFirstChild() : parent->slowLastChild();
while (child) {
if (!isAutosizingContainer(child) || !isIndependentDescendant(toRenderBlock(child))) {
const RenderObject* leaf = findFirstTextLeafNotInCluster(child, depth, direction);
@@ -681,8 +845,8 @@ void TextAutosizer::getNarrowDescendantsGroupedByWidth(const TextAutosizingClust
groups.last().append(clusterInfos[i]);
if (i + 1 < clusterInfos.size()) {
- float currentWidth = clusterInfos[i].root->contentLogicalWidth();
- float nextWidth = clusterInfos[i + 1].root->contentLogicalWidth();
+ LayoutUnit currentWidth = clusterInfos[i].root->contentLogicalWidth();
+ LayoutUnit nextWidth = clusterInfos[i + 1].root->contentLogicalWidth();
if (currentWidth - nextWidth > maxWidthDifferenceWithinGroup)
groups.grow(groups.size() + 1);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.h b/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.h
index dda763efa7b..aac87074bb4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.h
@@ -26,9 +26,11 @@
#ifndef TextAutosizer_h
#define TextAutosizer_h
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "platform/text/WritingMode.h"
+#include "wtf/HashMap.h"
#include "wtf/Noncopyable.h"
+#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
namespace WebCore {
@@ -36,9 +38,28 @@ namespace WebCore {
class Document;
class RenderBlock;
class RenderObject;
-class RenderText;
struct TextAutosizingWindowInfo;
-struct TextAutosizingClusterInfo;
+
+// Represents cluster related data. Instances should not persist between calls to processSubtree.
+struct TextAutosizingClusterInfo {
+ explicit TextAutosizingClusterInfo(RenderBlock* root)
+ : root(root)
+ , blockContainingAllText(0)
+ , maxAllowedDifferenceFromTextWidth(150)
+ {
+ }
+
+ RenderBlock* root;
+ const RenderBlock* blockContainingAllText;
+
+ // Upper limit on the difference between the width of the cluster's block containing all
+ // text and that of a narrow child before the child becomes a separate cluster.
+ float maxAllowedDifferenceFromTextWidth;
+
+ // Descendants of the cluster that are narrower than the block containing all text and must be
+ // processed together.
+ Vector<TextAutosizingClusterInfo> narrowDescendants;
+};
class TextAutosizer FINAL {
WTF_MAKE_NONCOPYABLE(TextAutosizer);
@@ -61,6 +82,7 @@ private:
explicit TextAutosizer(Document*);
+ bool isApplicable() const;
float clusterMultiplier(WritingMode, const TextAutosizingWindowInfo&, float textWidth) const;
void processClusterInternal(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&, float multiplier);
@@ -71,6 +93,8 @@ private:
void setMultiplier(RenderObject*, float);
void setMultiplierForList(RenderObject* renderer, float multiplier);
+ unsigned getCachedHash(const RenderObject* renderer, bool putInCacheIfAbsent);
+
static bool isAutosizingContainer(const RenderObject*);
static bool isNarrowDescendant(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);
static bool isWiderDescendant(const RenderBlock*, const TextAutosizingClusterInfo& parentClusterInfo);
@@ -81,9 +105,10 @@ private:
static bool containerContainsOneOfTags(const RenderBlock* cluster, const Vector<QualifiedName>& tags);
static bool containerIsRowOfLinks(const RenderObject* container);
static bool contentHeightIsConstrained(const RenderBlock* container);
- static bool clusterShouldBeAutosized(TextAutosizingClusterInfo&, float blockWidth);
static bool compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>&, float blockWidth);
static void measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo&, float minTextWidth, float& textWidth);
+ unsigned computeCompositeClusterHash(Vector<TextAutosizingClusterInfo>&);
+ float computeMultiplier(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&, float textWidth);
// Use to traverse the tree of descendants, excluding descendants of containers (but returning the containers themselves).
static RenderObject* nextInPreOrderSkippingDescendantsOfContainers(const RenderObject*, const RenderObject* stayWithin);
@@ -99,7 +124,22 @@ private:
// |blockContainingAllText|.
static void getNarrowDescendantsGroupedByWidth(const TextAutosizingClusterInfo& parentClusterInfo, Vector<Vector<TextAutosizingClusterInfo> >&);
+ void addNonAutosizedCluster(unsigned key, TextAutosizingClusterInfo& value);
+ void secondPassProcessStaleNonAutosizedClusters();
+ void processStaleContainer(float multiplier, RenderBlock* cluster, TextAutosizingClusterInfo&);
+
Document* m_document;
+
+ HashMap<const RenderObject*, unsigned> m_hashCache;
+
+ // Mapping from all autosized (i.e. multiplier > 1) cluster hashes to their respective multipliers.
+ HashMap<unsigned, float> m_hashToMultiplier;
+ Vector<unsigned> m_hashesToAutosizeSecondPass;
+
+ // Mapping from a cluster hash to the corresponding cluster infos which have not been autosized yet.
+ HashMap<unsigned, OwnPtr<Vector<TextAutosizingClusterInfo> > > m_nonAutosizedClusters;
+
+ bool m_previouslyAutosized;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/TrailingFloatsRootInlineBox.h b/chromium/third_party/WebKit/Source/core/rendering/TrailingFloatsRootInlineBox.h
index 8036f5a0432..151f0b08b19 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/TrailingFloatsRootInlineBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/TrailingFloatsRootInlineBox.h
@@ -32,14 +32,14 @@ namespace WebCore {
class TrailingFloatsRootInlineBox FINAL : public RootInlineBox {
public:
- TrailingFloatsRootInlineBox(RenderBlockFlow* block)
+ TrailingFloatsRootInlineBox(RenderBlockFlow& block)
: RootInlineBox(block)
{
setHasVirtualLogicalHeight();
}
private:
- virtual float virtualLogicalHeight() const { return 0; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return 0; }
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.cpp b/chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.cpp
deleted file mode 100644
index 473e3ff8073..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2013 Intel Corporation. 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 "core/rendering/animation/WebAnimationProvider.h"
-
-#include "core/platform/animation/AnimationTranslationUtil.h"
-#include "core/platform/animation/CSSAnimationData.h"
-#include "core/rendering/style/KeyframeList.h"
-#include "core/rendering/style/RenderStyle.h"
-#include "public/platform/WebAnimation.h"
-#include "wtf/text/StringBuilder.h"
-
-using blink::WebAnimation;
-
-namespace WebCore {
-
-namespace {
-
-String animationNameForTransition(AnimatedPropertyID property)
-{
- // | is not a valid identifier character in CSS, so this can never conflict with a keyframe identifier.
- StringBuilder id;
- id.appendLiteral("-|transition");
- id.appendNumber(static_cast<int>(property));
- id.append('-');
- return id.toString();
-}
-
-AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
-{
- switch (cssProperty) {
- case CSSPropertyWebkitTransform:
- return AnimatedPropertyWebkitTransform;
- case CSSPropertyOpacity:
- return AnimatedPropertyOpacity;
- case CSSPropertyBackgroundColor:
- ASSERT_NOT_REACHED();
- return AnimatedPropertyInvalid; // Chromium compositor cannot accelerate background color yet.
- case CSSPropertyWebkitFilter:
- return AnimatedPropertyWebkitFilter;
- default:
- // It's fine if we see other css properties here; they are just not accelerated.
- break;
- }
- return AnimatedPropertyInvalid;
-}
-
-} // namespace
-
-WebAnimations::WebAnimations()
-{
-}
-
-WebAnimations::~WebAnimations()
-{
-}
-
-// Copy constructor is needed to use this struct as a return value. It actually moves the ownership, not copy.
-WebAnimations::WebAnimations(const WebAnimations& other)
-{
- ASSERT(isEmpty());
- m_transformAnimation.swap(const_cast<OwnPtr<WebAnimation>& >(other.m_transformAnimation));
- m_opacityAnimation.swap(const_cast<OwnPtr<WebAnimation>& >(other.m_opacityAnimation));
- m_filterAnimation.swap(const_cast<OwnPtr<WebAnimation>& >(other.m_filterAnimation));
- ASSERT(other.isEmpty());
-}
-
-bool WebAnimations::isEmpty() const
-{
- return !m_transformAnimation && !m_opacityAnimation && !m_filterAnimation;
-}
-
-WebAnimationProvider::WebAnimationProvider()
-{
-}
-
-WebAnimationProvider::~WebAnimationProvider()
-{
-}
-
-int WebAnimationProvider::getWebAnimationId(const String& animationName) const
-{
- if (!m_animationIdMap.contains(animationName))
- return 0;
- return m_animationIdMap.get(animationName);
-}
-
-int WebAnimationProvider::getWebAnimationId(CSSPropertyID property) const
-{
- AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
- ASSERT(animatedProperty != AnimatedPropertyInvalid);
- return getWebAnimationId(animationNameForTransition(animatedProperty));
-}
-
-WebAnimations WebAnimationProvider::startAnimation(double timeOffset, const CSSAnimationData* anim, const KeyframeList& keyframes, bool hasTransform, const IntSize& boxSize)
-{
- ASSERT(hasTransform || boxSize.isEmpty());
- bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
- bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
-
- if (!hasOpacity && !hasTransform && !hasFilter)
- return WebAnimations();
-
- KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
- KeyframeValueList opacityVector(AnimatedPropertyOpacity);
- KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
-
- size_t numKeyframes = keyframes.size();
- for (size_t i = 0; i < numKeyframes; ++i) {
- const KeyframeValue& currentKeyframe = keyframes[i];
- const RenderStyle* keyframeStyle = currentKeyframe.style();
- double key = currentKeyframe.key();
-
- if (!keyframeStyle)
- continue;
-
- // Get timing function.
- RefPtr<TimingFunction> tf = KeyframeValue::timingFunction(*keyframeStyle);
-
- bool isFirstOrLastKeyframe = !key || key == 1;
- if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
- transformVector.insert(adoptPtr(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf)));
-
- if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
- opacityVector.insert(adoptPtr(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)));
-
- if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
- filterVector.insert(adoptPtr(new FilterAnimationValue(key, &(keyframeStyle->filter()), tf)));
- }
- WebAnimations resultAnimations;
- if (hasTransform)
- resultAnimations.m_transformAnimation = createWebAnimationAndStoreId(transformVector, boxSize, anim, keyframes.animationName(), timeOffset);
- if (hasOpacity)
- resultAnimations.m_opacityAnimation = createWebAnimationAndStoreId(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset);
- if (hasFilter)
- resultAnimations.m_filterAnimation = createWebAnimationAndStoreId(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset);
-
- return resultAnimations;
-}
-
-WebAnimations WebAnimationProvider::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle, bool hasTransform, bool hasFilter, const IntSize& boxSize, float fromOpacity, float toOpacity)
-{
- ASSERT(property != CSSPropertyInvalid);
- ASSERT(property == CSSPropertyOpacity || (!fromOpacity && !toOpacity));
-
- WebAnimations resultAnimations;
- if (property == CSSPropertyOpacity) {
- const CSSAnimationData* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
- if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
- KeyframeValueList opacityVector(AnimatedPropertyOpacity);
- opacityVector.insert(adoptPtr(new FloatAnimationValue(0, fromOpacity)));
- opacityVector.insert(adoptPtr(new FloatAnimationValue(1, toOpacity)));
- resultAnimations.m_opacityAnimation = createWebAnimationAndStoreId(opacityVector, IntSize(), opacityAnim, animationNameForTransition(AnimatedPropertyOpacity), timeOffset);
- }
- }
- if (property == CSSPropertyWebkitTransform && hasTransform) {
- const CSSAnimationData* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
- if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
- KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
- transformVector.insert(adoptPtr(new TransformAnimationValue(0, &fromStyle->transform())));
- transformVector.insert(adoptPtr(new TransformAnimationValue(1, &toStyle->transform())));
- resultAnimations.m_transformAnimation = createWebAnimationAndStoreId(transformVector, boxSize, transformAnim, animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset);
- }
- }
- if (property == CSSPropertyWebkitFilter && hasFilter) {
- const CSSAnimationData* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
- if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
- KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
- filterVector.insert(adoptPtr(new FilterAnimationValue(0, &fromStyle->filter())));
- filterVector.insert(adoptPtr(new FilterAnimationValue(1, &toStyle->filter())));
- resultAnimations.m_filterAnimation = createWebAnimationAndStoreId(filterVector, IntSize(), filterAnim, animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset);
- }
- }
-
- return resultAnimations;
-}
-
-PassOwnPtr<WebAnimation> WebAnimationProvider::createWebAnimationAndStoreId(const KeyframeValueList& values, const IntSize& boxSize, const CSSAnimationData* animation, const String& animationName, double timeOffset)
-{
- int animationId = getWebAnimationId(animationName);
- OwnPtr<WebAnimation> webAnimation(createWebAnimation(values, animation, animationId, timeOffset, boxSize));
- if (!webAnimation)
- return PassOwnPtr<WebAnimation>();
-
- if (!animationId)
- m_animationIdMap.set(animationName, webAnimation->id());
- return webAnimation.release();
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.h b/chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.h
deleted file mode 100644
index 724de2e1696..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/animation/WebAnimationProvider.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013 Intel Corporation. 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 WebAnimationProvider_h
-#define WebAnimationProvider_h
-
-#include "CSSPropertyNames.h"
-#include "core/platform/animation/KeyframeValueList.h"
-#include "wtf/HashMap.h"
-#include "wtf/OwnPtr.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-class WebAnimation;
-}
-
-namespace WebCore {
-class CSSAnimationData;
-class IntSize;
-class KeyframeList;
-class RenderStyle;
-
-struct WebAnimations {
- WebAnimations();
- ~WebAnimations();
- WebAnimations(const WebAnimations&);
- bool isEmpty() const;
- OwnPtr<blink::WebAnimation> m_transformAnimation;
- OwnPtr<blink::WebAnimation> m_opacityAnimation;
- OwnPtr<blink::WebAnimation> m_filterAnimation;
-};
-
-class WebAnimationProvider {
- WTF_MAKE_NONCOPYABLE(WebAnimationProvider); WTF_MAKE_FAST_ALLOCATED;
-public:
- WebAnimationProvider();
- ~WebAnimationProvider();
-
- int getWebAnimationId(const String& animationName) const;
- int getWebAnimationId(CSSPropertyID) const;
- WebAnimations startAnimation(double timeOffset, const CSSAnimationData*, const KeyframeList&, bool hasTransform, const IntSize& boxSize);
- WebAnimations startTransition(double timeOffset, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle, bool hasTransform, bool hasFilter, const IntSize& boxSize, float fromOpacity, float toOpacity);
-
-private:
- PassOwnPtr<blink::WebAnimation> createWebAnimationAndStoreId(const KeyframeValueList&, const IntSize& boxSize, const CSSAnimationData*, const String& animationName, double timeOffset);
-
- typedef HashMap<String, int> AnimationIdMap;
- AnimationIdMap m_animationIdMap;
-};
-
-} // namespace WebCore
-
-#endif // WebAnimationProvider_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.cpp
new file mode 100644
index 00000000000..0b01a059bc5
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.cpp
@@ -0,0 +1,2246 @@
+/*
+ * Copyright (C) 2009, 2010, 2011 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 "core/rendering/compositing/CompositedLayerMapping.h"
+
+#include "core/HTMLNames.h"
+#include "core/fetch/ImageResource.h"
+#include "core/html/HTMLCanvasElement.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/canvas/CanvasRenderingContext.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorNodeIds.h"
+#include "core/inspector/InspectorTraceEvents.h"
+#include "core/page/Chrome.h"
+#include "core/frame/FrameView.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/plugins/PluginView.h"
+#include "core/rendering/FilterEffectRenderer.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderLayerStackingNodeIterator.h"
+#include "core/rendering/RenderVideo.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+#include "core/rendering/style/KeyframeList.h"
+#include "platform/LengthFunctions.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/fonts/FontCache.h"
+#include "platform/graphics/GraphicsContext.h"
+#include "wtf/CurrentTime.h"
+#include "wtf/text/StringBuilder.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static IntRect clipBox(RenderBox* renderer);
+
+static IntRect contentsRect(const RenderObject* renderer)
+{
+ if (!renderer->isBox())
+ return IntRect();
+
+ return renderer->isVideo() ?
+ toRenderVideo(renderer)->videoBox() :
+ pixelSnappedIntRect(toRenderBox(renderer)->contentBoxRect());
+}
+
+static IntRect backgroundRect(const RenderObject* renderer)
+{
+ if (!renderer->isBox())
+ return IntRect();
+
+ LayoutRect rect;
+ const RenderBox* box = toRenderBox(renderer);
+ EFillBox clip = box->style()->backgroundClip();
+ switch (clip) {
+ case BorderFillBox:
+ rect = box->borderBoxRect();
+ break;
+ case PaddingFillBox:
+ rect = box->paddingBoxRect();
+ break;
+ case ContentFillBox:
+ rect = box->contentBoxRect();
+ break;
+ case TextFillBox:
+ break;
+ }
+
+ return pixelSnappedIntRect(rect);
+}
+
+static inline bool isAcceleratedCanvas(const RenderObject* renderer)
+{
+ if (renderer->isCanvas()) {
+ HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
+ if (CanvasRenderingContext* context = canvas->renderingContext())
+ return context->isAccelerated();
+ }
+ return false;
+}
+
+static bool hasBoxDecorations(const RenderStyle* style)
+{
+ return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
+}
+
+static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
+{
+ return hasBoxDecorations(style) || style->hasBackgroundImage();
+}
+
+static bool contentLayerSupportsDirectBackgroundComposition(const RenderObject* renderer)
+{
+ // No support for decorations - border, border-radius or outline.
+ // Only simple background - solid color or transparent.
+ if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
+ return false;
+
+ // If there is no background, there is nothing to support.
+ if (!renderer->style()->hasBackground())
+ return true;
+
+ // Simple background that is contained within the contents rect.
+ return contentsRect(renderer).contains(backgroundRect(renderer));
+}
+
+static blink::WebLayer* platformLayerForPlugin(RenderObject* renderer)
+{
+ if (!renderer->isEmbeddedObject())
+ return 0;
+ Widget* widget = toRenderEmbeddedObject(renderer)->widget();
+ if (!widget || !widget->isPluginView())
+ return 0;
+ return toPluginView(widget)->platformLayer();
+
+}
+
+static inline bool isAcceleratedContents(RenderObject* renderer)
+{
+ return isAcceleratedCanvas(renderer)
+ || (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing())
+ || renderer->isVideo();
+}
+
+// Get the scrolling coordinator in a way that works inside CompositedLayerMapping's destructor.
+static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer)
+{
+ Page* page = layer.renderer()->frame()->page();
+ if (!page)
+ return 0;
+
+ return page->scrollingCoordinator();
+}
+
+CompositedLayerMapping::CompositedLayerMapping(RenderLayer& layer)
+ : m_owningLayer(layer)
+ , m_pendingUpdateScope(GraphicsLayerUpdateNone)
+ , m_isMainFrameRenderViewLayer(false)
+ , m_requiresOwnBackingStoreForIntrinsicReasons(true)
+ , m_requiresOwnBackingStoreForAncestorReasons(true)
+ , m_canCompositeFilters(false)
+ , m_backgroundLayerPaintsFixedRootBackground(false)
+ , m_scrollingContentsAreEmpty(false)
+{
+ if (layer.isRootLayer() && renderer()->frame()->isMainFrame())
+ m_isMainFrameRenderViewLayer = true;
+
+ createPrimaryGraphicsLayer();
+}
+
+CompositedLayerMapping::~CompositedLayerMapping()
+{
+ // Hits in compositing/squashing/squash-onto-nephew.html.
+ DisableCompositingQueryAsserts disabler;
+
+ // Do not leave the destroyed pointer dangling on any RenderLayers that painted to this mapping's squashing layer.
+ for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
+ RenderLayer* oldSquashedLayer = m_squashedLayers[i].renderLayer;
+ if (oldSquashedLayer->groupedMapping() == this) {
+ oldSquashedLayer->setGroupedMapping(0, true);
+ oldSquashedLayer->setLostGroupedMapping(true);
+ }
+ }
+
+ updateClippingLayers(false, false);
+ updateOverflowControlsLayers(false, false, false);
+ updateChildTransformLayer(false);
+ updateForegroundLayer(false);
+ updateBackgroundLayer(false);
+ updateMaskLayer(false);
+ updateClippingMaskLayers(false);
+ updateScrollingLayers(false);
+ updateSquashingLayers(false);
+ destroyGraphicsLayers();
+}
+
+PassOwnPtr<GraphicsLayer> CompositedLayerMapping::createGraphicsLayer(CompositingReasons reasons)
+{
+ GraphicsLayerFactory* graphicsLayerFactory = 0;
+ if (Page* page = renderer()->frame()->page())
+ graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
+
+ OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
+
+ graphicsLayer->setCompositingReasons(reasons);
+ if (Node* owningNode = m_owningLayer.renderer()->generatingNode())
+ graphicsLayer->setOwnerNodeId(InspectorNodeIds::idForNode(owningNode));
+
+ return graphicsLayer.release();
+}
+
+void CompositedLayerMapping::createPrimaryGraphicsLayer()
+{
+ m_graphicsLayer = createGraphicsLayer(m_owningLayer.compositingReasons());
+
+#if !OS(ANDROID)
+ if (m_isMainFrameRenderViewLayer)
+ m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
+#endif
+
+ updateOpacity(renderer()->style());
+ updateTransform(renderer()->style());
+ updateFilters(renderer()->style());
+
+ if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
+ updateLayerBlendMode(renderer()->style());
+ updateIsRootForIsolatedGroup();
+ }
+}
+
+void CompositedLayerMapping::destroyGraphicsLayers()
+{
+ if (m_graphicsLayer)
+ m_graphicsLayer->removeFromParent();
+
+ m_ancestorClippingLayer = nullptr;
+ m_graphicsLayer = nullptr;
+ m_foregroundLayer = nullptr;
+ m_backgroundLayer = nullptr;
+ m_childContainmentLayer = nullptr;
+ m_childTransformLayer = nullptr;
+ m_maskLayer = nullptr;
+ m_childClippingMaskLayer = nullptr;
+
+ m_scrollingLayer = nullptr;
+ m_scrollingContentsLayer = nullptr;
+ m_scrollingBlockSelectionLayer = nullptr;
+}
+
+void CompositedLayerMapping::updateOpacity(const RenderStyle* style)
+{
+ m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
+}
+
+void CompositedLayerMapping::updateTransform(const RenderStyle* style)
+{
+ // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
+ // baked into it, and we don't want that.
+ TransformationMatrix t;
+ if (m_owningLayer.hasTransform()) {
+ style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
+ makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing());
+ }
+
+ m_graphicsLayer->setTransform(t);
+}
+
+void CompositedLayerMapping::updateFilters(const RenderStyle* style)
+{
+ unsigned didCompositeFilters = m_canCompositeFilters;
+ m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer().computeFilterOperations(style));
+ if (didCompositeFilters != m_canCompositeFilters) {
+ //
+ // If filters used to be painted in software and are now painted in the compositor, we need to:
+ // (1) Remove the FilterEffectRenderer, which was used for painting filters in software.
+ // (2) Repaint the layer contents to remove the software-applied filter because the compositor will apply it.
+ //
+ // Similarly, if filters used to be painted in the compositor and are now painted in software, we need to:
+ // (1) Create a FilterEffectRenderer.
+ // (2) Repaint the layer contents to apply a software filter because the compositor won't apply it.
+ //
+ m_owningLayer.updateOrRemoveFilterEffectRenderer();
+ setContentsNeedDisplay();
+ }
+}
+
+void CompositedLayerMapping::updateLayerBlendMode(const RenderStyle* style)
+{
+ setBlendMode(style->blendMode());
+}
+
+void CompositedLayerMapping::updateIsRootForIsolatedGroup()
+{
+ bool isolate = m_owningLayer.shouldIsolateCompositedDescendants();
+
+ // non stacking context layers should never isolate
+ ASSERT(m_owningLayer.stackingNode()->isStackingContext() || !isolate);
+
+ m_graphicsLayer->setIsRootForIsolatedGroup(isolate);
+}
+
+void CompositedLayerMapping::updateContentsOpaque()
+{
+ // For non-root layers, background is always painted by the primary graphics layer.
+ ASSERT(m_isMainFrameRenderViewLayer || !m_backgroundLayer);
+ if (m_backgroundLayer) {
+ m_graphicsLayer->setContentsOpaque(false);
+ m_backgroundLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
+ } else {
+ m_graphicsLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
+ }
+}
+
+void CompositedLayerMapping::updateCompositedBounds(GraphicsLayerUpdater::UpdateType updateType)
+{
+ if (!shouldUpdateGraphicsLayer(updateType))
+ return;
+
+ // FIXME: if this is really needed for performance, it would be better to store it on RenderLayer.
+ m_compositedBounds = m_owningLayer.boundingBoxForCompositing();
+}
+
+void CompositedLayerMapping::updateAfterWidgetResize()
+{
+ if (renderer()->isRenderPart()) {
+ if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
+ innerCompositor->frameViewDidChangeSize();
+ // We can floor this point because our frameviews are always aligned to pixel boundaries.
+ ASSERT(contentsBox().location() == flooredIntPoint(contentsBox().location()));
+ innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
+ }
+ }
+}
+
+void CompositedLayerMapping::updateCompositingReasons()
+{
+ // All other layers owned by this mapping will have the same compositing reason
+ // for their lifetime, so they are initialized only when created.
+ m_graphicsLayer->setCompositingReasons(m_owningLayer.compositingReasons());
+}
+
+bool CompositedLayerMapping::updateGraphicsLayerConfiguration(GraphicsLayerUpdater::UpdateType updateType)
+{
+ if (!shouldUpdateGraphicsLayer(updateType))
+ return false;
+
+ RenderLayerCompositor* compositor = this->compositor();
+ RenderObject* renderer = this->renderer();
+
+ m_owningLayer.updateDescendantDependentFlags();
+ m_owningLayer.stackingNode()->updateZOrderLists();
+
+ bool layerConfigChanged = false;
+ setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(&m_owningLayer));
+
+ // The background layer is currently only used for fixed root backgrounds.
+ if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
+ layerConfigChanged = true;
+
+ if (updateForegroundLayer(compositor->needsContentsCompositingLayer(&m_owningLayer)))
+ layerConfigChanged = true;
+
+ bool needsDescendantsClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer);
+
+ // Our scrolling layer will clip.
+ if (m_owningLayer.needsCompositedScrolling())
+ needsDescendantsClippingLayer = false;
+
+ RenderLayer* scrollParent = compositor->acceleratedCompositingForOverflowScrollEnabled() ? m_owningLayer.scrollParent() : 0;
+ bool needsAncestorClip = compositor->clippedByNonAncestorInStackingTree(&m_owningLayer);
+ if (scrollParent) {
+ // If our containing block is our ancestor scrolling layer, then we'll already be clipped
+ // to it via our scroll parent and we don't need an ancestor clipping layer.
+ if (m_owningLayer.renderer()->containingBlock()->enclosingLayer() == m_owningLayer.ancestorScrollingLayer())
+ needsAncestorClip = false;
+ }
+
+ if (updateClippingLayers(needsAncestorClip, needsDescendantsClippingLayer))
+ layerConfigChanged = true;
+
+ if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
+ layerConfigChanged = true;
+
+ bool scrollingConfigChanged = false;
+ if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling())) {
+ layerConfigChanged = true;
+ scrollingConfigChanged = true;
+ }
+
+ bool hasPerspective = false;
+ if (RenderStyle* style = renderer->style())
+ hasPerspective = style->hasPerspective();
+ bool needsChildTransformLayer = hasPerspective && (layerForChildrenTransform() == m_childTransformLayer.get()) && renderer->isBox();
+ if (updateChildTransformLayer(needsChildTransformLayer))
+ layerConfigChanged = true;
+
+ updateScrollParent(scrollParent);
+ updateClipParent(m_owningLayer.clipParent());
+
+ if (updateSquashingLayers(!m_squashedLayers.isEmpty()))
+ layerConfigChanged = true;
+
+ if (layerConfigChanged)
+ updateInternalHierarchy();
+
+ if (scrollingConfigChanged) {
+ if (renderer->view())
+ compositor->scrollingLayerDidChange(&m_owningLayer);
+ }
+
+ // A mask layer is not part of the hierarchy proper, it's an auxiliary layer
+ // that's plugged into another GraphicsLayer that is part of the hierarchy.
+ // It has no parent or child GraphicsLayer. For that reason, we process it
+ // here, after the hierarchy has been updated.
+ bool maskLayerChanged = false;
+ if (updateMaskLayer(renderer->hasMask())) {
+ maskLayerChanged = true;
+ m_graphicsLayer->setMaskLayer(m_maskLayer.get());
+ }
+
+ bool hasChildClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer) && (hasClippingLayer() || hasScrollingLayer());
+ // If we have a border radius or clip path on a scrolling layer, we need a clipping mask to properly
+ // clip the scrolled contents, even if there are no composited descendants.
+ bool hasClipPath = renderer->style()->clipPath();
+ bool needsChildClippingMask = (hasClipPath || renderer->style()->hasBorderRadius()) && (hasChildClippingLayer || isAcceleratedContents(renderer) || hasScrollingLayer());
+ if (updateClippingMaskLayers(needsChildClippingMask)) {
+ // Clip path clips the entire subtree, including scrollbars. It must be attached directly onto
+ // the main m_graphicsLayer.
+ if (hasClipPath)
+ m_graphicsLayer->setMaskLayer(m_childClippingMaskLayer.get());
+ else if (hasClippingLayer())
+ clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
+ else if (hasScrollingLayer())
+ scrollingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
+ else if (isAcceleratedContents(renderer))
+ m_graphicsLayer->setContentsClippingMaskLayer(m_childClippingMaskLayer.get());
+ }
+
+ if (m_owningLayer.reflectionInfo()) {
+ if (m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
+ GraphicsLayer* reflectionLayer = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping()->mainGraphicsLayer();
+ m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
+ }
+ } else {
+ m_graphicsLayer->setReplicatedByLayer(0);
+ }
+
+ updateBackgroundColor();
+
+ if (isDirectlyCompositedImage())
+ updateImageContents();
+
+ if (blink::WebLayer* layer = platformLayerForPlugin(renderer)) {
+ m_graphicsLayer->setContentsToPlatformLayer(layer);
+ } else if (renderer->node() && renderer->node()->isFrameOwnerElement() && toHTMLFrameOwnerElement(renderer->node())->contentFrame()) {
+ blink::WebLayer* layer = toHTMLFrameOwnerElement(renderer->node())->contentFrame()->remotePlatformLayer();
+ if (layer)
+ m_graphicsLayer->setContentsToPlatformLayer(layer);
+ } else if (renderer->isVideo()) {
+ HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer->node());
+ m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer());
+ } else if (isAcceleratedCanvas(renderer)) {
+ HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
+ if (CanvasRenderingContext* context = canvas->renderingContext())
+ m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer());
+ layerConfigChanged = true;
+ }
+ if (renderer->isRenderPart())
+ layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
+
+ // Changes to either the internal hierarchy or the mask layer have an impact
+ // on painting phases, so we need to update when either are updated.
+ if (layerConfigChanged || maskLayerChanged)
+ updatePaintingPhases();
+
+ return layerConfigChanged;
+}
+
+static IntRect clipBox(RenderBox* renderer)
+{
+ LayoutRect result = PaintInfo::infiniteRect();
+ if (renderer->hasOverflowClip())
+ result = renderer->overflowClipRect(LayoutPoint());
+
+ if (renderer->hasClip())
+ result.intersect(renderer->clipRect(LayoutPoint()));
+
+ return pixelSnappedIntRect(result);
+}
+
+static LayoutPoint computeOffsetFromCompositedAncestor(const RenderLayer* layer, const RenderLayer* compositedAncestor)
+{
+ LayoutPoint offset;
+ layer->convertToLayerCoords(compositedAncestor, offset);
+ if (compositedAncestor)
+ offset.move(compositedAncestor->compositedLayerMapping()->owningLayer().subpixelAccumulation());
+ return offset;
+}
+
+void CompositedLayerMapping::computeBoundsOfOwningLayer(const RenderLayer* compositedAncestor, IntRect& localBounds, IntRect& compositingBoundsRelativeToCompositedAncestor, LayoutPoint& offsetFromCompositedAncestor,
+ IntPoint& snappedOffsetFromCompositedAncestor)
+{
+ LayoutRect localRawCompositingBounds = compositedBounds();
+ offsetFromCompositedAncestor = computeOffsetFromCompositedAncestor(&m_owningLayer, compositedAncestor);
+ snappedOffsetFromCompositedAncestor = IntPoint(offsetFromCompositedAncestor.x().round(), offsetFromCompositedAncestor.y().round());
+
+ LayoutSize subpixelAccumulation = offsetFromCompositedAncestor - snappedOffsetFromCompositedAncestor;
+ m_owningLayer.setSubpixelAccumulation(subpixelAccumulation);
+
+ // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates.
+ localRawCompositingBounds.move(subpixelAccumulation);
+ localBounds = pixelSnappedIntRect(localRawCompositingBounds);
+
+ compositingBoundsRelativeToCompositedAncestor = localBounds;
+ compositingBoundsRelativeToCompositedAncestor.moveBy(snappedOffsetFromCompositedAncestor);
+}
+
+void CompositedLayerMapping::updateSquashingLayerGeometry(const LayoutPoint& offsetFromCompositedAncestor, const IntPoint& graphicsLayerParentLocation, const RenderLayer& referenceLayer,
+ Vector<GraphicsLayerPaintInfo>& layers, GraphicsLayer* squashingLayer, LayoutPoint* offsetFromTransformedAncestor, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
+{
+ if (!squashingLayer)
+ return;
+ ASSERT(compositor()->layerSquashingEnabled());
+
+ LayoutPoint offsetFromReferenceLayerToParentGraphicsLayer(offsetFromCompositedAncestor);
+ offsetFromReferenceLayerToParentGraphicsLayer.moveBy(-graphicsLayerParentLocation);
+
+ // FIXME: Cache these offsets.
+ LayoutPoint referenceOffsetFromTransformedAncestor = referenceLayer.computeOffsetFromTransformedAncestor();
+
+ LayoutRect totalSquashBounds;
+ for (size_t i = 0; i < layers.size(); ++i) {
+ LayoutRect squashedBounds = layers[i].renderLayer->boundingBoxForCompositing();
+
+ // Store the local bounds of the RenderLayer subtree before applying the offset.
+ layers[i].compositedBounds = squashedBounds;
+
+ LayoutPoint offsetFromTransformedAncestorForSquashedLayer = layers[i].renderLayer->computeOffsetFromTransformedAncestor();
+ LayoutSize offsetFromSquashingLayer = offsetFromTransformedAncestorForSquashedLayer - referenceOffsetFromTransformedAncestor;
+
+ squashedBounds.move(offsetFromSquashingLayer);
+ totalSquashBounds.unite(squashedBounds);
+ }
+
+ // The totalSquashBounds is positioned with respect to referenceLayer of this CompositedLayerMapping.
+ // But the squashingLayer needs to be positioned with respect to the ancestor CompositedLayerMapping.
+ // The conversion between referenceLayer and the ancestor CLM is already computed as
+ // offsetFromReferenceLayerToParentGraphicsLayer.
+ totalSquashBounds.moveBy(offsetFromReferenceLayerToParentGraphicsLayer);
+ IntRect squashLayerBounds = enclosingIntRect(totalSquashBounds);
+ IntPoint squashLayerOrigin = squashLayerBounds.location();
+ LayoutSize squashLayerOriginInOwningLayerSpace = squashLayerOrigin - offsetFromReferenceLayerToParentGraphicsLayer;
+
+ // Now that the squashing bounds are known, we can convert the RenderLayer painting offsets
+ // from CLM owning layer space to the squashing layer space.
+ //
+ // The painting offset we want to compute for each squashed RenderLayer is essentially the position of
+ // the squashed RenderLayer described w.r.t. referenceLayer's origin. For this purpose we already cached
+ // offsetFromSquashingCLM before, which describes where the squashed RenderLayer is located w.r.t.
+ // referenceLayer. So we just need to convert that point from referenceLayer space to referenceLayer
+ // space. This is simply done by subtracing squashLayerOriginInOwningLayerSpace, but then the offset
+ // overall needs to be negated because that's the direction that the painting code expects the
+ // offset to be.
+ for (size_t i = 0; i < layers.size(); ++i) {
+ LayoutPoint offsetFromTransformedAncestorForSquashedLayer = layers[i].renderLayer->computeOffsetFromTransformedAncestor();
+ LayoutSize offsetFromSquashLayerOrigin = (offsetFromTransformedAncestorForSquashedLayer - referenceOffsetFromTransformedAncestor) - squashLayerOriginInOwningLayerSpace;
+
+ // It is ok to repaint here, because all of the geometry needed to correctly repaint is computed by this point.
+ IntSize newOffsetFromRenderer = -IntSize(offsetFromSquashLayerOrigin.width().round(), offsetFromSquashLayerOrigin.height().round());
+ LayoutSize subpixelAccumulation = offsetFromSquashLayerOrigin + newOffsetFromRenderer;
+ if (layers[i].offsetFromRendererSet && layers[i].offsetFromRenderer != newOffsetFromRenderer) {
+ layers[i].renderLayer->repainter().repaintIncludingNonCompositingDescendants();
+ layersNeedingPaintInvalidation.append(layers[i].renderLayer);
+ }
+ layers[i].offsetFromRenderer = newOffsetFromRenderer;
+ layers[i].offsetFromRendererSet = true;
+
+ layers[i].renderLayer->setSubpixelAccumulation(subpixelAccumulation);
+
+ // FIXME: find a better design to avoid this redundant value - most likely it will make
+ // sense to move the paint task info into RenderLayer's m_compositingProperties.
+ layers[i].renderLayer->setOffsetFromSquashingLayerOrigin(layers[i].offsetFromRenderer);
+ }
+
+ squashingLayer->setPosition(squashLayerBounds.location());
+ squashingLayer->setSize(squashLayerBounds.size());
+
+ *offsetFromTransformedAncestor = referenceOffsetFromTransformedAncestor;
+ offsetFromTransformedAncestor->move(squashLayerOriginInOwningLayerSpace);
+
+ for (size_t i = 0; i < layers.size(); ++i)
+ layers[i].localClipRectForSquashedLayer = localClipRectForSquashedLayer(referenceLayer, layers[i], layers);
+}
+
+void CompositedLayerMapping::updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType updateType, const RenderLayer* compositingContainer, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
+{
+ if (!shouldUpdateGraphicsLayer(updateType))
+ return;
+
+ // Set transform property, if it is not animating. We have to do this here because the transform
+ // is affected by the layer dimensions.
+ if (!renderer()->style()->isRunningTransformAnimationOnCompositor())
+ updateTransform(renderer()->style());
+
+ // Set opacity, if it is not animating.
+ if (!renderer()->style()->isRunningOpacityAnimationOnCompositor())
+ updateOpacity(renderer()->style());
+
+ m_owningLayer.updateDescendantDependentFlags();
+
+ // We compute everything relative to the enclosing compositing layer.
+ IntRect ancestorCompositingBounds;
+ if (compositingContainer) {
+ ASSERT(compositingContainer->hasCompositedLayerMapping());
+ ancestorCompositingBounds = compositingContainer->compositedLayerMapping()->pixelSnappedCompositedBounds();
+ }
+
+ IntRect localCompositingBounds;
+ IntRect relativeCompositingBounds;
+ LayoutPoint offsetFromCompositedAncestor;
+ IntPoint snappedOffsetFromCompositedAncestor;
+ computeBoundsOfOwningLayer(compositingContainer, localCompositingBounds, relativeCompositingBounds, offsetFromCompositedAncestor, snappedOffsetFromCompositedAncestor);
+
+ IntPoint graphicsLayerParentLocation;
+ computeGraphicsLayerParentLocation(compositingContainer, ancestorCompositingBounds, graphicsLayerParentLocation);
+
+ // Might update graphicsLayerParentLocation.
+ updateAncestorClippingLayerGeometry(compositingContainer, snappedOffsetFromCompositedAncestor, graphicsLayerParentLocation);
+
+ FloatSize contentsSize = relativeCompositingBounds.size();
+
+ updateMainGraphicsLayerGeometry(relativeCompositingBounds, localCompositingBounds, graphicsLayerParentLocation);
+ updateSquashingLayerGeometry(offsetFromCompositedAncestor, graphicsLayerParentLocation, m_owningLayer, m_squashedLayers, m_squashingLayer.get(), &m_squashingLayerOffsetFromTransformedAncestor, layersNeedingPaintInvalidation);
+
+ // If we have a layer that clips children, position it.
+ IntRect clippingBox;
+ if (m_childContainmentLayer)
+ clippingBox = clipBox(toRenderBox(renderer()));
+
+ updateChildContainmentLayerGeometry(clippingBox, localCompositingBounds);
+ updateChildTransformLayerGeometry();
+
+ updateMaskLayerGeometry();
+ updateTransformGeometry(snappedOffsetFromCompositedAncestor, relativeCompositingBounds);
+ updateForegroundLayerGeometry(contentsSize, clippingBox);
+ updateBackgroundLayerGeometry(contentsSize);
+ updateReflectionLayerGeometry(layersNeedingPaintInvalidation);
+ updateScrollingLayerGeometry(localCompositingBounds);
+ updateChildClippingMaskLayerGeometry();
+
+ if (m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->scrollsOverflow())
+ m_owningLayer.scrollableArea()->positionOverflowControls(IntSize());
+
+ if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
+ updateLayerBlendMode(renderer()->style());
+ updateIsRootForIsolatedGroup();
+ }
+
+ updateContentsRect();
+ updateBackgroundColor();
+ updateDrawsContent();
+ updateContentsOpaque();
+ updateAfterWidgetResize();
+ updateRenderingContext();
+ updateShouldFlattenTransform();
+ updateChildrenTransform();
+ updateScrollParent(compositor()->acceleratedCompositingForOverflowScrollEnabled() ? m_owningLayer.scrollParent() : 0);
+ registerScrollingLayers();
+
+ updateCompositingReasons();
+}
+
+void CompositedLayerMapping::updateMainGraphicsLayerGeometry(const IntRect& relativeCompositingBounds, const IntRect& localCompositingBounds, IntPoint& graphicsLayerParentLocation)
+{
+ m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
+ m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
+
+ FloatSize oldSize = m_graphicsLayer->size();
+ const IntSize& contentsSize = relativeCompositingBounds.size();
+ if (oldSize != contentsSize)
+ m_graphicsLayer->setSize(contentsSize);
+
+ // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
+ // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
+ // non-compositing visible layers.
+ bool contentsVisible = m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendant(&m_owningLayer);
+ if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && renderer()->isVideo()) {
+ HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer()->node());
+ if (mediaElement->isFullscreen())
+ contentsVisible = false;
+ }
+ m_graphicsLayer->setContentsVisible(contentsVisible);
+
+ m_graphicsLayer->setBackfaceVisibility(renderer()->style()->backfaceVisibility() == BackfaceVisibilityVisible);
+}
+
+void CompositedLayerMapping::computeGraphicsLayerParentLocation(const RenderLayer* compositingContainer, const IntRect& ancestorCompositingBounds, IntPoint& graphicsLayerParentLocation)
+{
+ if (compositingContainer && compositingContainer->compositedLayerMapping()->hasClippingLayer()) {
+ // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
+ // position relative to it.
+ IntRect clippingBox = clipBox(toRenderBox(compositingContainer->renderer()));
+ graphicsLayerParentLocation = clippingBox.location() + roundedIntSize(compositingContainer->subpixelAccumulation());
+ } else if (compositingContainer && compositingContainer->compositedLayerMapping()->childTransformLayer()) {
+ // Similarly, if the compositing ancestor has a child transform layer, we parent in that, and therefore
+ // position relative to it. It's already taken into account the contents offset, so we do not need to here.
+ graphicsLayerParentLocation = roundedIntPoint(compositingContainer->subpixelAccumulation());
+ } else if (compositingContainer) {
+ graphicsLayerParentLocation = ancestorCompositingBounds.location();
+ } else {
+ graphicsLayerParentLocation = renderer()->view()->documentRect().location();
+ }
+
+ if (compositingContainer && compositingContainer->needsCompositedScrolling()) {
+ RenderBox* renderBox = toRenderBox(compositingContainer->renderer());
+ IntSize scrollOffset = renderBox->scrolledContentOffset();
+ IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
+ graphicsLayerParentLocation = scrollOrigin - scrollOffset;
+ }
+}
+
+void CompositedLayerMapping::updateAncestorClippingLayerGeometry(const RenderLayer* compositingContainer, const IntPoint& snappedOffsetFromCompositedAncestor, IntPoint& graphicsLayerParentLocation)
+{
+ if (!compositingContainer || !m_ancestorClippingLayer)
+ return;
+
+ // FIXME: this should use cached clip rects, but this sometimes give
+ // inaccurate results (and trips the ASSERTS in RenderLayerClipper).
+ ClipRectsContext clipRectsContext(compositingContainer, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
+ IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
+ ASSERT(parentClipRect != PaintInfo::infiniteRect());
+ m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
+ m_ancestorClippingLayer->setSize(parentClipRect.size());
+
+ // backgroundRect is relative to compositingContainer, so subtract snappedOffsetFromCompositedAncestor.X/snappedOffsetFromCompositedAncestor.Y to get back to local coords.
+ m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - snappedOffsetFromCompositedAncestor);
+
+ // The primary layer is then parented in, and positioned relative to this clipping layer.
+ graphicsLayerParentLocation = parentClipRect.location();
+}
+
+void CompositedLayerMapping::updateChildContainmentLayerGeometry(const IntRect& clippingBox, const IntRect& localCompositingBounds)
+{
+ if (!m_childContainmentLayer)
+ return;
+
+ m_childContainmentLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location() + roundedIntSize(m_owningLayer.subpixelAccumulation())));
+ m_childContainmentLayer->setSize(clippingBox.size());
+ m_childContainmentLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
+ if (m_childClippingMaskLayer && !m_scrollingLayer && !renderer()->style()->clipPath()) {
+ m_childClippingMaskLayer->setPosition(m_childContainmentLayer->position());
+ m_childClippingMaskLayer->setSize(m_childContainmentLayer->size());
+ m_childClippingMaskLayer->setOffsetFromRenderer(m_childContainmentLayer->offsetFromRenderer());
+ }
+}
+
+void CompositedLayerMapping::updateChildTransformLayerGeometry()
+{
+ if (!m_childTransformLayer)
+ return;
+ const IntRect borderBox = toRenderBox(m_owningLayer.renderer())->pixelSnappedBorderBoxRect();
+ m_childTransformLayer->setSize(borderBox.size());
+ m_childTransformLayer->setPosition(FloatPoint(contentOffsetInCompositingLayer()));
+}
+
+void CompositedLayerMapping::updateMaskLayerGeometry()
+{
+ if (!m_maskLayer)
+ return;
+
+ if (m_maskLayer->size() != m_graphicsLayer->size()) {
+ m_maskLayer->setSize(m_graphicsLayer->size());
+ m_maskLayer->setNeedsDisplay();
+ }
+ m_maskLayer->setPosition(FloatPoint());
+ m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+}
+
+void CompositedLayerMapping::updateTransformGeometry(const IntPoint& snappedOffsetFromCompositedAncestor, const IntRect& relativeCompositingBounds)
+{
+ if (m_owningLayer.hasTransform()) {
+ const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
+
+ // Get layout bounds in the coords of compositingContainer to match relativeCompositingBounds.
+ IntRect layerBounds = pixelSnappedIntRect(toLayoutPoint(m_owningLayer.subpixelAccumulation()), borderBox.size());
+ layerBounds.moveBy(snappedOffsetFromCompositedAncestor);
+
+ // Update properties that depend on layer dimensions
+ FloatPoint3D transformOrigin = computeTransformOrigin(IntRect(IntPoint(), layerBounds.size()));
+
+ // |transformOrigin| is in the local space of this layer. layerBounds - relativeCompositingBounds converts to the space of the
+ // compositing bounds relative to the composited ancestor. This does not apply to the z direction, since the page is 2D.
+ FloatPoint3D compositedTransformOrigin(
+ layerBounds.x() - relativeCompositingBounds.x() + transformOrigin.x(),
+ layerBounds.y() - relativeCompositingBounds.y() + transformOrigin.y(),
+ transformOrigin.z());
+ m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
+ } else {
+ FloatPoint3D compositedTransformOrigin(
+ relativeCompositingBounds.width() * 0.5f,
+ relativeCompositingBounds.height() * 0.5f,
+ 0.f);
+ m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
+ }
+}
+
+void CompositedLayerMapping::updateReflectionLayerGeometry(Vector<RenderLayer*>& layersNeedingPaintInvalidation)
+{
+ if (!m_owningLayer.reflectionInfo() || !m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping())
+ return;
+
+ CompositedLayerMappingPtr reflectionCompositedLayerMapping = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping();
+ reflectionCompositedLayerMapping->updateGraphicsLayerGeometry(GraphicsLayerUpdater::ForceUpdate, &m_owningLayer, layersNeedingPaintInvalidation);
+}
+
+void CompositedLayerMapping::updateScrollingLayerGeometry(const IntRect& localCompositingBounds)
+{
+ if (!m_scrollingLayer)
+ return;
+
+ ASSERT(m_scrollingContentsLayer);
+ RenderBox* renderBox = toRenderBox(renderer());
+ IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
+
+ IntSize adjustedScrollOffset = m_owningLayer.scrollableArea()->adjustedScrollOffset();
+ m_scrollingLayer->setPosition(FloatPoint(clientBox.location() - localCompositingBounds.location() + roundedIntSize(m_owningLayer.subpixelAccumulation())));
+ m_scrollingLayer->setSize(clientBox.size());
+
+ IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
+ m_scrollingLayer->setOffsetFromRenderer(-toIntSize(clientBox.location()));
+
+ if (m_childClippingMaskLayer && !renderer()->style()->clipPath()) {
+ m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
+ m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
+ m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
+ }
+
+ bool clientBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
+
+ IntSize scrollSize(renderBox->scrollWidth(), renderBox->scrollHeight());
+ if (scrollSize != m_scrollingContentsLayer->size() || clientBoxOffsetChanged)
+ m_scrollingContentsLayer->setNeedsDisplay();
+
+ IntSize scrollingContentsOffset = toIntSize(clientBox.location() - adjustedScrollOffset);
+ if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) {
+ bool coordinatorHandlesOffset = compositor()->scrollingLayerDidChange(&m_owningLayer);
+ m_scrollingContentsLayer->setPosition(coordinatorHandlesOffset ? FloatPoint() : FloatPoint(-adjustedScrollOffset));
+ }
+
+ m_scrollingContentsLayer->setSize(scrollSize);
+ // FIXME: The paint offset and the scroll offset should really be separate concepts.
+ m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
+
+ if (m_foregroundLayer) {
+ if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
+ m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
+ m_foregroundLayer->setNeedsDisplay();
+ m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
+ }
+
+ updateScrollingBlockSelection();
+}
+
+void CompositedLayerMapping::updateChildClippingMaskLayerGeometry()
+{
+ if (!m_childClippingMaskLayer || !renderer()->style()->clipPath())
+ return;
+ RenderBox* renderBox = toRenderBox(renderer());
+ IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
+
+ m_childClippingMaskLayer->setPosition(m_graphicsLayer->position());
+ m_childClippingMaskLayer->setSize(m_graphicsLayer->size());
+ m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
+
+ // NOTE: also some stuff happening in updateChildContainmentLayerGeometry().
+}
+
+void CompositedLayerMapping::updateForegroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize, const IntRect& clippingBox)
+{
+ if (!m_foregroundLayer)
+ return;
+
+ FloatSize foregroundSize = relativeCompositingBoundsSize;
+ IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
+ m_foregroundLayer->setPosition(FloatPoint());
+
+ if (hasClippingLayer()) {
+ // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
+ // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
+ foregroundSize = FloatSize(clippingBox.size());
+ foregroundOffset = toIntSize(clippingBox.location());
+ } else if (m_childTransformLayer) {
+ // Things are different if we have a child transform layer rather
+ // than a clipping layer. In this case, we want to actually change
+ // the position of the layer (to compensate for our ancestor
+ // compositing layer's position) rather than leave the position the
+ // same and use offset-from-renderer + size to describe a clipped
+ // "window" onto the clipped layer.
+
+ m_foregroundLayer->setPosition(-m_childTransformLayer->position());
+ }
+
+ if (foregroundSize != m_foregroundLayer->size()) {
+ m_foregroundLayer->setSize(foregroundSize);
+ m_foregroundLayer->setNeedsDisplay();
+ }
+ m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
+
+ // NOTE: there is some more configuring going on in updateScrollingLayerGeometry().
+}
+
+void CompositedLayerMapping::updateBackgroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize)
+{
+ if (!m_backgroundLayer)
+ return;
+
+ FloatSize backgroundSize = relativeCompositingBoundsSize;
+ if (backgroundLayerPaintsFixedRootBackground()) {
+ FrameView* frameView = toRenderView(renderer())->frameView();
+ backgroundSize = frameView->visibleContentRect().size();
+ }
+ m_backgroundLayer->setPosition(FloatPoint());
+ if (backgroundSize != m_backgroundLayer->size()) {
+ m_backgroundLayer->setSize(backgroundSize);
+ m_backgroundLayer->setNeedsDisplay();
+ }
+ m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+}
+
+void CompositedLayerMapping::registerScrollingLayers()
+{
+ // Register fixed position layers and their containers with the scrolling coordinator.
+ ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
+ if (!scrollingCoordinator)
+ return;
+
+ scrollingCoordinator->updateLayerPositionConstraint(&m_owningLayer);
+
+ // Page scale is applied as a transform on the root render view layer. Because the scroll
+ // layer is further up in the hierarchy, we need to avoid marking the root render view
+ // layer as a container.
+ bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer();
+ // FIXME: we should make certain that childForSuperLayers will never be the m_squashingContainmentLayer here
+ scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(localRootForOwningLayer(), isContainer);
+}
+
+void CompositedLayerMapping::updateInternalHierarchy()
+{
+ // m_foregroundLayer has to be inserted in the correct order with child layers,
+ // so it's not inserted here.
+ if (m_ancestorClippingLayer)
+ m_ancestorClippingLayer->removeAllChildren();
+
+ m_graphicsLayer->removeFromParent();
+
+ if (m_ancestorClippingLayer)
+ m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
+
+ if (m_childContainmentLayer)
+ m_graphicsLayer->addChild(m_childContainmentLayer.get());
+ else if (m_childTransformLayer)
+ m_graphicsLayer->addChild(m_childTransformLayer.get());
+
+ if (m_scrollingLayer) {
+ GraphicsLayer* superLayer = m_graphicsLayer.get();
+
+ if (m_childContainmentLayer)
+ superLayer = m_childContainmentLayer.get();
+
+ if (m_childTransformLayer)
+ superLayer = m_childTransformLayer.get();
+
+ superLayer->addChild(m_scrollingLayer.get());
+ }
+
+ // The clip for child layers does not include space for overflow controls, so they exist as
+ // siblings of the clipping layer if we have one. Normal children of this layer are set as
+ // children of the clipping layer.
+ if (m_layerForHorizontalScrollbar)
+ m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
+ if (m_layerForVerticalScrollbar)
+ m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
+ if (m_layerForScrollCorner)
+ m_graphicsLayer->addChild(m_layerForScrollCorner.get());
+
+ // The squashing containment layer, if it exists, becomes a no-op parent.
+ if (m_squashingLayer) {
+ ASSERT(compositor()->layerSquashingEnabled());
+ ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) || (!m_ancestorClippingLayer && m_squashingContainmentLayer));
+
+ if (m_squashingContainmentLayer) {
+ m_squashingContainmentLayer->removeAllChildren();
+ m_squashingContainmentLayer->addChild(m_graphicsLayer.get());
+ m_squashingContainmentLayer->addChild(m_squashingLayer.get());
+ } else {
+ // The ancestor clipping layer is already set up and has m_graphicsLayer under it.
+ m_ancestorClippingLayer->addChild(m_squashingLayer.get());
+ }
+ }
+}
+
+void CompositedLayerMapping::updatePaintingPhases()
+{
+ m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+ if (m_scrollingContentsLayer) {
+ GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
+ if (!m_foregroundLayer)
+ paintPhase |= GraphicsLayerPaintForeground;
+ m_scrollingContentsLayer->setPaintingPhase(paintPhase);
+ m_scrollingBlockSelectionLayer->setPaintingPhase(paintPhase);
+ }
+}
+
+void CompositedLayerMapping::updateContentsRect()
+{
+ m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
+}
+
+void CompositedLayerMapping::updateScrollingBlockSelection()
+{
+ if (!m_scrollingBlockSelectionLayer)
+ return;
+
+ if (!m_scrollingContentsAreEmpty) {
+ // In this case, the selection will be painted directly into m_scrollingContentsLayer.
+ m_scrollingBlockSelectionLayer->setDrawsContent(false);
+ return;
+ }
+
+ const IntRect blockSelectionGapsBounds = m_owningLayer.blockSelectionGapsBounds();
+ const bool shouldDrawContent = !blockSelectionGapsBounds.isEmpty();
+ m_scrollingBlockSelectionLayer->setDrawsContent(shouldDrawContent);
+ if (!shouldDrawContent)
+ return;
+
+ const IntPoint position = blockSelectionGapsBounds.location() + m_owningLayer.scrollableArea()->adjustedScrollOffset();
+ if (m_scrollingBlockSelectionLayer->size() == blockSelectionGapsBounds.size() && m_scrollingBlockSelectionLayer->position() == position)
+ return;
+
+ m_scrollingBlockSelectionLayer->setPosition(position);
+ m_scrollingBlockSelectionLayer->setSize(blockSelectionGapsBounds.size());
+ m_scrollingBlockSelectionLayer->setOffsetFromRenderer(toIntSize(blockSelectionGapsBounds.location()), GraphicsLayer::SetNeedsDisplay);
+}
+
+void CompositedLayerMapping::updateDrawsContent()
+{
+ if (m_scrollingLayer) {
+ // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
+ // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
+ // m_scrollingLayer never has backing store.
+ // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
+ bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground();
+ m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
+
+ m_scrollingContentsAreEmpty = !m_owningLayer.hasVisibleContent() || !(renderer()->hasBackground() || paintsChildren());
+ m_scrollingContentsLayer->setDrawsContent(!m_scrollingContentsAreEmpty);
+
+ updateScrollingBlockSelection();
+ return;
+ }
+
+ bool hasPaintedContent = containsPaintedContent();
+ if (hasPaintedContent && isAcceleratedCanvas(renderer())) {
+ CanvasRenderingContext* context = toHTMLCanvasElement(renderer()->node())->renderingContext();
+ // Content layer may be null if context is lost.
+ if (blink::WebLayer* contentLayer = context->platformLayer()) {
+ Color bgColor(Color::transparent);
+ if (contentLayerSupportsDirectBackgroundComposition(renderer())) {
+ bgColor = rendererBackgroundColor();
+ hasPaintedContent = false;
+ }
+ contentLayer->setBackgroundColor(bgColor.rgb());
+ }
+ }
+
+ // FIXME: we could refine this to only allocate backings for one of these layers if possible.
+ m_graphicsLayer->setDrawsContent(hasPaintedContent);
+ if (m_foregroundLayer)
+ m_foregroundLayer->setDrawsContent(hasPaintedContent);
+
+ if (m_backgroundLayer)
+ m_backgroundLayer->setDrawsContent(hasPaintedContent);
+}
+
+void CompositedLayerMapping::updateChildrenTransform()
+{
+ if (GraphicsLayer* childTransformLayer = layerForChildrenTransform()) {
+ childTransformLayer->setTransform(owningLayer().perspectiveTransform());
+ childTransformLayer->setTransformOrigin(FloatPoint3D(childTransformLayer->size().width() * 0.5f, childTransformLayer->size().height() * 0.5f, 0.f));
+ bool hasPerspective = false;
+ if (RenderStyle* style = m_owningLayer.renderer()->style())
+ hasPerspective = style->hasPerspective();
+ if (hasPerspective)
+ childTransformLayer->setShouldFlattenTransform(false);
+
+ // Note, if the target is the scrolling layer, we need to ensure that the
+ // scrolling content layer doesn't flatten the transform. (It would be nice
+ // if we could apply transform to the scrolling content layer, but that's
+ // too late, we need the children transform to be applied _before_ the
+ // scrolling offset.)
+ if (childTransformLayer == m_scrollingLayer.get())
+ m_scrollingContentsLayer->setShouldFlattenTransform(false);
+ }
+}
+
+// Return true if the layers changed.
+bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
+{
+ bool layersChanged = false;
+
+ if (needsAncestorClip) {
+ if (!m_ancestorClippingLayer) {
+ m_ancestorClippingLayer = createGraphicsLayer(CompositingReasonLayerForAncestorClip);
+ m_ancestorClippingLayer->setMasksToBounds(true);
+ layersChanged = true;
+ }
+ } else if (m_ancestorClippingLayer) {
+ m_ancestorClippingLayer->removeFromParent();
+ m_ancestorClippingLayer = nullptr;
+ layersChanged = true;
+ }
+
+ if (needsDescendantClip) {
+ // We don't need a child containment layer if we're the main frame render view
+ // layer. It's redundant as the frame clip above us will handle this clipping.
+ if (!m_childContainmentLayer && !m_isMainFrameRenderViewLayer) {
+ m_childContainmentLayer = createGraphicsLayer(CompositingReasonLayerForDescendantClip);
+ m_childContainmentLayer->setMasksToBounds(true);
+ layersChanged = true;
+ }
+ } else if (hasClippingLayer()) {
+ m_childContainmentLayer->removeFromParent();
+ m_childContainmentLayer = nullptr;
+ layersChanged = true;
+ }
+
+ return layersChanged;
+}
+
+bool CompositedLayerMapping::updateChildTransformLayer(bool needsChildTransformLayer)
+{
+ bool layersChanged = false;
+
+ if (needsChildTransformLayer) {
+ if (!m_childTransformLayer) {
+ m_childTransformLayer = createGraphicsLayer(CompositingReasonLayerForPerspective);
+ m_childTransformLayer->setDrawsContent(false);
+ m_childTransformLayer->setShouldFlattenTransform(false);
+ layersChanged = true;
+ }
+ } else if (m_childTransformLayer) {
+ m_childTransformLayer->removeFromParent();
+ m_childTransformLayer = nullptr;
+ layersChanged = true;
+ }
+
+ return layersChanged;
+}
+
+void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
+{
+ m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
+}
+
+// Only a member function so it can call createGraphicsLayer.
+bool CompositedLayerMapping::toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer>& layer, bool needsLayer, CompositingReasons reason)
+{
+ if (needsLayer == !!layer)
+ return false;
+ layer = needsLayer ? createGraphicsLayer(reason) : nullptr;
+ return true;
+}
+
+bool CompositedLayerMapping::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
+{
+ bool horizontalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForHorizontalScrollbar, needsHorizontalScrollbarLayer, CompositingReasonLayerForHorizontalScrollbar);
+ bool verticalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForVerticalScrollbar, needsVerticalScrollbarLayer, CompositingReasonLayerForVerticalScrollbar);
+ bool scrollCornerLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForScrollCorner, needsScrollCornerLayer, CompositingReasonLayerForScrollCorner);
+
+ if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
+ if (horizontalScrollbarLayerChanged)
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), HorizontalScrollbar);
+ if (verticalScrollbarLayerChanged)
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), VerticalScrollbar);
+ }
+
+ return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
+}
+
+void CompositedLayerMapping::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
+{
+ IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer() - roundedIntSize(m_owningLayer.subpixelAccumulation());
+ if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+ Scrollbar* hBar = m_owningLayer.scrollableArea()->horizontalScrollbar();
+ if (hBar) {
+ layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
+ layer->setSize(hBar->frameRect().size());
+ if (layer->hasContentsLayer())
+ layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
+ }
+ layer->setDrawsContent(hBar && !layer->hasContentsLayer());
+ }
+
+ if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+ Scrollbar* vBar = m_owningLayer.scrollableArea()->verticalScrollbar();
+ if (vBar) {
+ layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
+ layer->setSize(vBar->frameRect().size());
+ if (layer->hasContentsLayer())
+ layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
+ }
+ layer->setDrawsContent(vBar && !layer->hasContentsLayer());
+ }
+
+ if (GraphicsLayer* layer = layerForScrollCorner()) {
+ const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
+ layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
+ layer->setSize(scrollCornerAndResizer.size());
+ layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
+ }
+}
+
+bool CompositedLayerMapping::hasUnpositionedOverflowControlsLayers() const
+{
+ if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+ if (!layer->drawsContent())
+ return true;
+ }
+
+ if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+ if (!layer->drawsContent())
+ return true;
+ }
+
+ if (GraphicsLayer* layer = layerForScrollCorner()) {
+ if (!layer->drawsContent())
+ return true;
+ }
+
+ return false;
+}
+
+enum ApplyToGraphicsLayersModeFlags {
+ ApplyToCoreLayers = (1 << 0),
+ ApplyToSquashingLayer = (1 << 1),
+ ApplyToScrollbarLayers = (1 << 2),
+ ApplyToBackgroundLayer = (1 << 3),
+ ApplyToMaskLayers = (1 << 4),
+ ApplyToContentLayers = (1 << 5),
+ ApplyToAllGraphicsLayers = (ApplyToSquashingLayer | ApplyToScrollbarLayers | ApplyToBackgroundLayer | ApplyToMaskLayers | ApplyToCoreLayers | ApplyToContentLayers)
+};
+typedef unsigned ApplyToGraphicsLayersMode;
+
+template <typename Func>
+static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping, const Func& f, ApplyToGraphicsLayersMode mode)
+{
+ ASSERT(mode);
+
+ if ((mode & ApplyToCoreLayers) && mapping->squashingContainmentLayer())
+ f(mapping->squashingContainmentLayer());
+ if ((mode & ApplyToCoreLayers) && mapping->childTransformLayer())
+ f(mapping->childTransformLayer());
+ if ((mode & ApplyToCoreLayers) && mapping->ancestorClippingLayer())
+ f(mapping->ancestorClippingLayer());
+ if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->mainGraphicsLayer())
+ f(mapping->mainGraphicsLayer());
+ if ((mode & ApplyToCoreLayers) && mapping->clippingLayer())
+ f(mapping->clippingLayer());
+ if ((mode & ApplyToCoreLayers) && mapping->scrollingLayer())
+ f(mapping->scrollingLayer());
+ if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->scrollingContentsLayer())
+ f(mapping->scrollingContentsLayer());
+ if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->foregroundLayer())
+ f(mapping->foregroundLayer());
+
+ if ((mode & ApplyToSquashingLayer) && mapping->squashingLayer())
+ f(mapping->squashingLayer());
+
+ if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->maskLayer())
+ f(mapping->maskLayer());
+ if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->childClippingMaskLayer())
+ f(mapping->childClippingMaskLayer());
+
+ if (((mode & ApplyToBackgroundLayer) || (mode & ApplyToContentLayers)) && mapping->backgroundLayer())
+ f(mapping->backgroundLayer());
+
+ if ((mode & ApplyToScrollbarLayers) && mapping->layerForHorizontalScrollbar())
+ f(mapping->layerForHorizontalScrollbar());
+ if ((mode & ApplyToScrollbarLayers) && mapping->layerForVerticalScrollbar())
+ f(mapping->layerForVerticalScrollbar());
+ if ((mode & ApplyToScrollbarLayers) && mapping->layerForScrollCorner())
+ f(mapping->layerForScrollCorner());
+}
+
+struct UpdateRenderingContextFunctor {
+ void operator() (GraphicsLayer* layer) const { layer->setRenderingContext(renderingContext); }
+ int renderingContext;
+};
+
+void CompositedLayerMapping::updateRenderingContext()
+{
+ // All layers but the squashing layer (which contains 'alien' content) should be included in this
+ // rendering context.
+ int id = 0;
+
+ // NB, it is illegal at this point to query an ancestor's compositing state. Some compositing
+ // reasons depend on the compositing state of ancestors. So if we want a rendering context id
+ // for the context root, we cannot ask for the id of its associated WebLayer now; it may not have
+ // one yet. We could do a second past after doing the compositing updates to get these ids,
+ // but this would actually be harmful. We do not want to attach any semantic meaning to
+ // the context id other than the fact that they group a number of layers together for the
+ // sake of 3d sorting. So instead we will ask the compositor to vend us an arbitrary, but
+ // consistent id.
+ if (RenderLayer* root = m_owningLayer.renderingContextRoot()) {
+ if (Node* node = root->renderer()->node())
+ id = static_cast<int>(WTF::PtrHash<Node*>::hash(node));
+ }
+
+ UpdateRenderingContextFunctor functor = { id };
+ ApplyToGraphicsLayersMode mode = ApplyToAllGraphicsLayers & ~ApplyToSquashingLayer;
+ ApplyToGraphicsLayers<UpdateRenderingContextFunctor>(this, functor, mode);
+}
+
+struct UpdateShouldFlattenTransformFunctor {
+ void operator() (GraphicsLayer* layer) const { layer->setShouldFlattenTransform(shouldFlatten); }
+ bool shouldFlatten;
+};
+
+void CompositedLayerMapping::updateShouldFlattenTransform()
+{
+ // All CLM-managed layers that could affect a descendant layer should update their
+ // should-flatten-transform value (the other layers' transforms don't matter here).
+ UpdateShouldFlattenTransformFunctor functor = { !m_owningLayer.shouldPreserve3D() };
+ ApplyToGraphicsLayersMode mode = ApplyToCoreLayers;
+ ApplyToGraphicsLayers(this, functor, mode);
+}
+
+bool CompositedLayerMapping::updateForegroundLayer(bool needsForegroundLayer)
+{
+ bool layerChanged = false;
+ if (needsForegroundLayer) {
+ if (!m_foregroundLayer) {
+ m_foregroundLayer = createGraphicsLayer(CompositingReasonLayerForForeground);
+ m_foregroundLayer->setDrawsContent(true);
+ m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
+ layerChanged = true;
+ }
+ } else if (m_foregroundLayer) {
+ FloatRect repaintRect(FloatPoint(), m_foregroundLayer->size());
+ m_foregroundLayer->removeFromParent();
+ m_foregroundLayer = nullptr;
+ layerChanged = true;
+ }
+
+ return layerChanged;
+}
+
+bool CompositedLayerMapping::updateBackgroundLayer(bool needsBackgroundLayer)
+{
+ bool layerChanged = false;
+ if (needsBackgroundLayer) {
+ if (!m_backgroundLayer) {
+ m_backgroundLayer = createGraphicsLayer(CompositingReasonLayerForBackground);
+ m_backgroundLayer->setDrawsContent(true);
+ m_backgroundLayer->setTransformOrigin(FloatPoint3D());
+ m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
+#if !OS(ANDROID)
+ m_backgroundLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
+ m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(false);
+#endif
+ layerChanged = true;
+ }
+ } else {
+ if (m_backgroundLayer) {
+ m_backgroundLayer->removeFromParent();
+ m_backgroundLayer = nullptr;
+#if !OS(ANDROID)
+ m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
+#endif
+ layerChanged = true;
+ }
+ }
+
+ if (layerChanged && !m_owningLayer.renderer()->documentBeingDestroyed())
+ compositor()->rootFixedBackgroundsChanged();
+
+ return layerChanged;
+}
+
+bool CompositedLayerMapping::updateMaskLayer(bool needsMaskLayer)
+{
+ bool layerChanged = false;
+ if (needsMaskLayer) {
+ if (!m_maskLayer) {
+ m_maskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
+ m_maskLayer->setDrawsContent(true);
+ m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
+ layerChanged = true;
+ }
+ } else if (m_maskLayer) {
+ m_maskLayer = nullptr;
+ layerChanged = true;
+ }
+
+ return layerChanged;
+}
+
+bool CompositedLayerMapping::updateClippingMaskLayers(bool needsChildClippingMaskLayer)
+{
+ bool layerChanged = false;
+ if (needsChildClippingMaskLayer) {
+ if (!m_childClippingMaskLayer) {
+ m_childClippingMaskLayer = createGraphicsLayer(CompositingReasonLayerForClippingMask);
+ m_childClippingMaskLayer->setDrawsContent(true);
+ m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
+ layerChanged = true;
+ }
+ } else if (m_childClippingMaskLayer) {
+ m_childClippingMaskLayer = nullptr;
+ layerChanged = true;
+ }
+ return layerChanged;
+}
+
+bool CompositedLayerMapping::updateScrollingLayers(bool needsScrollingLayers)
+{
+ ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
+
+ bool layerChanged = false;
+ if (needsScrollingLayers) {
+ if (!m_scrollingLayer) {
+ // Outer layer which corresponds with the scroll view.
+ m_scrollingLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContainer);
+ m_scrollingLayer->setDrawsContent(false);
+ m_scrollingLayer->setMasksToBounds(true);
+
+ // Inner layer which renders the content that scrolls.
+ m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContents);
+ m_scrollingContentsLayer->setDrawsContent(true);
+ m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
+
+ m_scrollingBlockSelectionLayer = createGraphicsLayer(CompositingReasonLayerForScrollingBlockSelection);
+ m_scrollingBlockSelectionLayer->setDrawsContent(true);
+ m_scrollingContentsLayer->addChild(m_scrollingBlockSelectionLayer.get());
+
+ layerChanged = true;
+ if (scrollingCoordinator)
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
+ }
+ } else if (m_scrollingLayer) {
+ m_scrollingLayer = nullptr;
+ m_scrollingContentsLayer = nullptr;
+ m_scrollingBlockSelectionLayer = nullptr;
+ layerChanged = true;
+ if (scrollingCoordinator)
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
+ }
+
+ return layerChanged;
+}
+
+static void updateScrollParentForGraphicsLayer(GraphicsLayer* layer, GraphicsLayer* topmostLayer, RenderLayer* scrollParent, ScrollingCoordinator* scrollingCoordinator)
+{
+ if (!layer)
+ return;
+
+ // Only the topmost layer has a scroll parent. All other layers have a null scroll parent.
+ if (layer != topmostLayer)
+ scrollParent = 0;
+
+ scrollingCoordinator->updateScrollParentForGraphicsLayer(layer, scrollParent);
+}
+
+void CompositedLayerMapping::updateScrollParent(RenderLayer* scrollParent)
+{
+ if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
+ GraphicsLayer* topmostLayer = childForSuperlayers();
+ updateScrollParentForGraphicsLayer(m_squashingContainmentLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
+ updateScrollParentForGraphicsLayer(m_ancestorClippingLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
+ updateScrollParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
+ }
+}
+
+void CompositedLayerMapping::updateClipParent(RenderLayer* clipParent)
+{
+ if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer))
+ scrollingCoordinator->updateClipParentForGraphicsLayer(m_graphicsLayer.get(), clipParent);
+}
+
+bool CompositedLayerMapping::updateSquashingLayers(bool needsSquashingLayers)
+{
+ bool layersChanged = false;
+
+ if (needsSquashingLayers) {
+ ASSERT(compositor()->layerSquashingEnabled());
+
+ if (!m_squashingLayer) {
+ m_squashingLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContents);
+ m_squashingLayer->setDrawsContent(true);
+ layersChanged = true;
+ }
+
+ if (m_ancestorClippingLayer) {
+ if (m_squashingContainmentLayer) {
+ m_squashingContainmentLayer->removeFromParent();
+ m_squashingContainmentLayer = nullptr;
+ layersChanged = true;
+ }
+ } else {
+ if (!m_squashingContainmentLayer) {
+ m_squashingContainmentLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContainer);
+ layersChanged = true;
+ }
+ }
+
+ ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) || (!m_ancestorClippingLayer && m_squashingContainmentLayer));
+ ASSERT(m_squashingLayer);
+ } else {
+ if (m_squashingLayer) {
+ m_squashingLayer->removeFromParent();
+ m_squashingLayer = nullptr;
+ layersChanged = true;
+ }
+ if (m_squashingContainmentLayer) {
+ m_squashingContainmentLayer->removeFromParent();
+ m_squashingContainmentLayer = nullptr;
+ layersChanged = true;
+ }
+ ASSERT(!m_squashingLayer && !m_squashingContainmentLayer);
+ }
+
+ return layersChanged;
+}
+
+GraphicsLayerPaintingPhase CompositedLayerMapping::paintingPhaseForPrimaryLayer() const
+{
+ unsigned phase = 0;
+ if (!m_backgroundLayer)
+ phase |= GraphicsLayerPaintBackground;
+ if (!m_foregroundLayer)
+ phase |= GraphicsLayerPaintForeground;
+ if (!m_maskLayer)
+ phase |= GraphicsLayerPaintMask;
+
+ if (m_scrollingContentsLayer) {
+ phase &= ~GraphicsLayerPaintForeground;
+ phase |= GraphicsLayerPaintCompositedScroll;
+ }
+
+ return static_cast<GraphicsLayerPaintingPhase>(phase);
+}
+
+float CompositedLayerMapping::compositingOpacity(float rendererOpacity) const
+{
+ float finalOpacity = rendererOpacity;
+
+ for (RenderLayer* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
+ // We only care about parents that are stacking contexts.
+ // Recall that opacity creates stacking context.
+ if (!curr->stackingNode()->isStackingContext())
+ continue;
+
+ // If we found a composited layer, regardless of whether it actually
+ // paints into it, we want to compute opacity relative to it. So we can
+ // break here.
+ //
+ // FIXME: with grouped backings, a composited descendant will have to
+ // continue past the grouped (squashed) layers that its parents may
+ // contribute to. This whole confusion can be avoided by specifying
+ // explicitly the composited ancestor where we would stop accumulating
+ // opacity.
+ if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == HasOwnBackingButPaintsIntoAncestor)
+ break;
+
+ finalOpacity *= curr->renderer()->opacity();
+ }
+
+ return finalOpacity;
+}
+
+Color CompositedLayerMapping::rendererBackgroundColor() const
+{
+ RenderObject* backgroundRenderer = renderer();
+ if (backgroundRenderer->isDocumentElement())
+ backgroundRenderer = backgroundRenderer->rendererForRootBackground();
+
+ return backgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
+}
+
+void CompositedLayerMapping::updateBackgroundColor()
+{
+ m_graphicsLayer->setBackgroundColor(rendererBackgroundColor());
+}
+
+bool CompositedLayerMapping::paintsChildren() const
+{
+ if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers())
+ return true;
+
+ if (hasVisibleNonCompositingDescendant(&m_owningLayer))
+ return true;
+
+ return false;
+}
+
+static bool isCompositedPlugin(RenderObject* renderer)
+{
+ return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing();
+}
+
+bool CompositedLayerMapping::hasVisibleNonCompositingDescendant(RenderLayer* parent)
+{
+ if (!parent->hasVisibleDescendant())
+ return false;
+
+ // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
+ parent->stackingNode()->updateLayerListsIfNeeded();
+
+#if ASSERT_ENABLED
+ LayerListMutationDetector mutationChecker(parent->stackingNode());
+#endif
+
+ RenderLayerStackingNodeIterator normalFlowIterator(*parent->stackingNode(), AllChildren);
+ while (RenderLayerStackingNode* curNode = normalFlowIterator.next()) {
+ RenderLayer* curLayer = curNode->layer();
+ if (curLayer->hasCompositedLayerMapping())
+ continue;
+ if (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))
+ return true;
+ }
+
+ return false;
+}
+
+bool CompositedLayerMapping::containsPaintedContent() const
+{
+ if (paintsIntoCompositedAncestor() || m_owningLayer.isReflection())
+ return false;
+
+ if (isDirectlyCompositedImage())
+ return false;
+
+ RenderObject* renderObject = renderer();
+ // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
+ // and set background color on the layer in that case, instead of allocating backing store and painting.
+ if (renderObject->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
+ return m_owningLayer.hasBoxDecorationsOrBackground();
+
+ if (m_owningLayer.hasVisibleBoxDecorations())
+ return true;
+
+ if (renderObject->hasMask()) // masks require special treatment
+ return true;
+
+ if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
+ return true;
+
+ if (renderObject->isRenderRegion())
+ 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() ? renderObject->document().documentElement()->renderer() : 0;
+ // Reject anything that has a border, a border-radius or outline,
+ // or is not a simple background (no background, or solid color).
+ if (rootObject && hasBoxDecorationsOrBackgroundImage(rootObject->style()))
+ return true;
+
+ // Now look at the body's renderer.
+ HTMLElement* body = renderObject->document().body();
+ RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
+ if (bodyObject && hasBoxDecorationsOrBackgroundImage(bodyObject->style()))
+ return true;
+ }
+
+ // FIXME: it's O(n^2). A better solution is needed.
+ return paintsChildren();
+}
+
+// An image can be directly compositing if it's the sole content of the layer, and has no box decorations
+// that require painting. Direct compositing saves backing store.
+bool CompositedLayerMapping::isDirectlyCompositedImage() const
+{
+ RenderObject* renderObject = renderer();
+
+ if (!renderObject->isImage() || m_owningLayer.hasBoxDecorationsOrBackground() || renderObject->hasClip())
+ return false;
+
+ RenderImage* imageRenderer = toRenderImage(renderObject);
+ if (ImageResource* cachedImage = imageRenderer->cachedImage()) {
+ if (!cachedImage->hasImage())
+ return false;
+
+ Image* image = cachedImage->imageForRenderer(imageRenderer);
+ return image->isBitmapImage();
+ }
+
+ return false;
+}
+
+void CompositedLayerMapping::contentChanged(ContentChangeType changeType)
+{
+ if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
+ updateImageContents();
+ return;
+ }
+
+ if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
+ m_graphicsLayer->setContentsNeedsDisplay();
+ return;
+ }
+}
+
+void CompositedLayerMapping::updateImageContents()
+{
+ ASSERT(renderer()->isImage());
+ RenderImage* imageRenderer = toRenderImage(renderer());
+
+ ImageResource* cachedImage = imageRenderer->cachedImage();
+ if (!cachedImage)
+ return;
+
+ Image* image = cachedImage->imageForRenderer(imageRenderer);
+ if (!image)
+ return;
+
+ // We have to wait until the image is fully loaded before setting it on the layer.
+ if (!cachedImage->isLoaded())
+ return;
+
+ // This is a no-op if the layer doesn't have an inner layer for the image.
+ m_graphicsLayer->setContentsToImage(image);
+ updateDrawsContent();
+
+ // Image animation is "lazy", in that it automatically stops unless someone is drawing
+ // the image. So we have to kick the animation each time; this has the downside that the
+ // image will keep animating, even if its layer is not visible.
+ image->startAnimation();
+}
+
+FloatPoint3D CompositedLayerMapping::computeTransformOrigin(const IntRect& borderBox) const
+{
+ RenderStyle* style = renderer()->style();
+
+ FloatPoint3D origin;
+ origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
+ origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
+ origin.setZ(style->transformOriginZ());
+
+ return origin;
+}
+
+// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
+LayoutSize CompositedLayerMapping::contentOffsetInCompositingLayer() const
+{
+ return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y());
+}
+
+LayoutRect CompositedLayerMapping::contentsBox() const
+{
+ LayoutRect contentsBox = contentsRect(renderer());
+ contentsBox.move(contentOffsetInCompositingLayer());
+ return contentsBox;
+}
+
+GraphicsLayer* CompositedLayerMapping::parentForSublayers() const
+{
+ if (m_scrollingBlockSelectionLayer)
+ return m_scrollingBlockSelectionLayer.get();
+
+ if (m_scrollingContentsLayer)
+ return m_scrollingContentsLayer.get();
+
+ if (m_childContainmentLayer)
+ return m_childContainmentLayer.get();
+
+ if (m_childTransformLayer)
+ return m_childTransformLayer.get();
+
+ return m_graphicsLayer.get();
+}
+
+GraphicsLayer* CompositedLayerMapping::localRootForOwningLayer() const
+{
+ if (m_ancestorClippingLayer)
+ return m_ancestorClippingLayer.get();
+
+ return m_graphicsLayer.get();
+}
+
+GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const
+{
+ if (m_squashingContainmentLayer)
+ return m_squashingContainmentLayer.get();
+
+ return localRootForOwningLayer();
+}
+
+GraphicsLayer* CompositedLayerMapping::layerForChildrenTransform() const
+{
+ if (GraphicsLayer* clipLayer = clippingLayer())
+ return clipLayer;
+ if (m_scrollingLayer)
+ return m_scrollingLayer.get();
+ return m_childTransformLayer.get();
+}
+
+bool CompositedLayerMapping::updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer* compositingAncestorLayer)
+{
+ unsigned previousRequiresOwnBackingStoreForAncestorReasons = m_requiresOwnBackingStoreForAncestorReasons;
+ bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
+ bool canPaintIntoAncestor = compositingAncestorLayer
+ && (compositingAncestorLayer->compositedLayerMapping()->mainGraphicsLayer()->drawsContent()
+ || compositingAncestorLayer->compositedLayerMapping()->paintsIntoCompositedAncestor());
+ m_requiresOwnBackingStoreForAncestorReasons = !canPaintIntoAncestor;
+
+ if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
+ paintsIntoCompositedAncestorChanged();
+ return m_requiresOwnBackingStoreForAncestorReasons != previousRequiresOwnBackingStoreForAncestorReasons;
+}
+
+bool CompositedLayerMapping::updateRequiresOwnBackingStoreForIntrinsicReasons()
+{
+ unsigned previousRequiresOwnBackingStoreForIntrinsicReasons = m_requiresOwnBackingStoreForIntrinsicReasons;
+ bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
+ RenderObject* renderer = m_owningLayer.renderer();
+ m_requiresOwnBackingStoreForIntrinsicReasons = m_owningLayer.isRootLayer()
+ || (m_owningLayer.compositingReasons() & CompositingReasonComboReasonsThatRequireOwnBacking)
+ || m_owningLayer.transform()
+ || m_owningLayer.clipsCompositingDescendantsWithBorderRadius() // FIXME: Revisit this if the paintsIntoCompositedAncestor state is removed.
+ || renderer->isTransparent()
+ || renderer->hasMask()
+ || renderer->hasReflection()
+ || renderer->hasFilter();
+
+ if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
+ paintsIntoCompositedAncestorChanged();
+ return m_requiresOwnBackingStoreForIntrinsicReasons != previousRequiresOwnBackingStoreForIntrinsicReasons;
+}
+
+void CompositedLayerMapping::paintsIntoCompositedAncestorChanged()
+{
+ // The answer to paintsIntoCompositedAncestor() affects cached clip rects, so when
+ // it changes we have to clear clip rects on descendants.
+ m_owningLayer.clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
+ m_owningLayer.repainter().computeRepaintRectsIncludingNonCompositingDescendants();
+
+ compositor()->repaintInCompositedAncestor(&m_owningLayer, compositedBounds());
+}
+
+void CompositedLayerMapping::setBlendMode(blink::WebBlendMode blendMode)
+{
+ if (m_ancestorClippingLayer) {
+ m_ancestorClippingLayer->setBlendMode(blendMode);
+ m_graphicsLayer->setBlendMode(blink::WebBlendModeNormal);
+ } else {
+ m_graphicsLayer->setBlendMode(blendMode);
+ }
+}
+
+GraphicsLayerUpdater::UpdateType CompositedLayerMapping::updateTypeForChildren(GraphicsLayerUpdater::UpdateType updateType) const
+{
+ if (m_pendingUpdateScope >= GraphicsLayerUpdateSubtree)
+ return GraphicsLayerUpdater::ForceUpdate;
+ return updateType;
+}
+
+struct SetContentsNeedsDisplayFunctor {
+ void operator() (GraphicsLayer* layer) const
+ {
+ if (layer->drawsContent())
+ layer->setNeedsDisplay();
+ }
+};
+
+void CompositedLayerMapping::setSquashingContentsNeedDisplay()
+{
+ ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToSquashingLayer);
+}
+
+void CompositedLayerMapping::setContentsNeedDisplay()
+{
+ // FIXME: need to split out repaints for the background.
+ ASSERT(!paintsIntoCompositedAncestor());
+ ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToContentLayers);
+}
+
+struct SetContentsNeedsDisplayInRectFunctor {
+ void operator() (GraphicsLayer* layer) const
+ {
+ if (layer->drawsContent()) {
+ IntRect layerDirtyRect = r;
+ layerDirtyRect.move(-layer->offsetFromRenderer());
+ layer->setNeedsDisplayInRect(layerDirtyRect);
+ }
+ }
+
+ IntRect r;
+};
+
+// r is in the coordinate space of the layer's render object
+void CompositedLayerMapping::setContentsNeedDisplayInRect(const IntRect& r)
+{
+ // FIXME: need to split out repaints for the background.
+ ASSERT(!paintsIntoCompositedAncestor());
+ SetContentsNeedsDisplayInRectFunctor functor = { r };
+ ApplyToGraphicsLayers(this, functor, ApplyToContentLayers);
+}
+
+const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject, const Vector<GraphicsLayerPaintInfo>& layers)
+{
+ for (size_t i = 0; i < layers.size(); ++i) {
+ if (renderObject->isDescendantOf(layers[i].renderLayer->renderer())) {
+ return &layers[i];
+ break;
+ }
+ }
+ return 0;
+}
+
+const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject)
+{
+ return CompositedLayerMapping::containingSquashedLayer(renderObject, m_squashedLayers);
+}
+
+IntRect CompositedLayerMapping::localClipRectForSquashedLayer(const RenderLayer& referenceLayer, const GraphicsLayerPaintInfo& paintInfo, const Vector<GraphicsLayerPaintInfo>& layers)
+{
+ const RenderObject* clippingContainer = paintInfo.renderLayer->renderer()->clippingContainer();
+ if (clippingContainer == referenceLayer.renderer()->clippingContainer())
+ return PaintInfo::infiniteRect();
+
+ ASSERT(clippingContainer);
+
+ const GraphicsLayerPaintInfo* ancestorPaintInfo = containingSquashedLayer(clippingContainer, layers);
+ // Must be there, otherwise CompositingLayerAssigner::canSquashIntoCurrentSquashingOwner would have disallowed squashing.
+ ASSERT(ancestorPaintInfo);
+
+ // FIXME: this is a potential performance issue. We shoudl consider caching these clip rects or otherwise optimizing.
+ ClipRectsContext clipRectsContext(ancestorPaintInfo->renderLayer, TemporaryClipRects);
+ IntRect parentClipRect = pixelSnappedIntRect(paintInfo.renderLayer->clipper().backgroundClipRect(clipRectsContext).rect());
+ ASSERT(parentClipRect != PaintInfo::infiniteRect());
+
+ // Convert from ancestor to local coordinates.
+ IntSize ancestorToLocalOffset = paintInfo.offsetFromRenderer - ancestorPaintInfo->offsetFromRenderer;
+ parentClipRect.move(ancestorToLocalOffset);
+ return parentClipRect;
+}
+
+void CompositedLayerMapping::doPaintTask(GraphicsLayerPaintInfo& paintInfo, GraphicsContext* context,
+ const IntRect& clip) // In the coords of rootLayer.
+{
+ if (paintsIntoCompositedAncestor()) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ FontCachePurgePreventer fontCachePurgePreventer;
+
+ PaintLayerFlags paintFlags = 0;
+ if (paintInfo.paintingPhase & GraphicsLayerPaintBackground)
+ paintFlags |= PaintLayerPaintingCompositingBackgroundPhase;
+ if (paintInfo.paintingPhase & GraphicsLayerPaintForeground)
+ paintFlags |= PaintLayerPaintingCompositingForegroundPhase;
+ if (paintInfo.paintingPhase & GraphicsLayerPaintMask)
+ paintFlags |= PaintLayerPaintingCompositingMaskPhase;
+ if (paintInfo.paintingPhase & GraphicsLayerPaintChildClippingMask)
+ paintFlags |= PaintLayerPaintingChildClippingMaskPhase;
+ if (paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)
+ paintFlags |= PaintLayerPaintingOverflowContents;
+ if (paintInfo.paintingPhase & GraphicsLayerPaintCompositedScroll)
+ paintFlags |= PaintLayerPaintingCompositingScrollingPhase;
+
+ if (paintInfo.isBackgroundLayer)
+ paintFlags |= (PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
+ else if (compositor()->fixedRootBackgroundLayer())
+ paintFlags |= PaintLayerPaintingSkipRootBackground;
+
+ // Note carefully: in theory it is appropriate to invoke context->save() here
+ // and restore the context after painting. For efficiency, we are assuming that
+ // it is equivalent to manually undo this offset translation, which means we are
+ // assuming that the context's space was not affected by the RenderLayer
+ // painting code.
+
+ IntSize offset = paintInfo.offsetFromRenderer;
+ context->translate(-offset.width(), -offset.height());
+
+ // The dirtyRect is in the coords of the painting root.
+ IntRect dirtyRect(clip);
+ dirtyRect.move(offset);
+
+ if (!(paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)) {
+ LayoutRect bounds = paintInfo.compositedBounds;
+ bounds.move(paintInfo.renderLayer->subpixelAccumulation());
+ dirtyRect.intersect(pixelSnappedIntRect(bounds));
+ } else {
+ dirtyRect.move(roundedIntSize(paintInfo.renderLayer->subpixelAccumulation()));
+ }
+
+#ifndef NDEBUG
+ paintInfo.renderLayer->renderer()->assertSubtreeIsLaidOut();
+#endif
+
+ if (paintInfo.renderLayer->compositingState() != PaintsIntoGroupedBacking) {
+ // FIXME: GraphicsLayers need a way to split for RenderRegions.
+ LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.renderLayer->subpixelAccumulation());
+ paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags);
+
+ ASSERT(!paintInfo.isBackgroundLayer || paintFlags & PaintLayerPaintingRootBackgroundOnly);
+
+ if (paintInfo.renderLayer->containsDirtyOverlayScrollbars())
+ paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags | PaintLayerPaintingOverlayScrollbars);
+ } else {
+ ASSERT(compositor()->layerSquashingEnabled());
+ LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.renderLayer->subpixelAccumulation());
+
+ // RenderLayer::paintLayer assumes that the caller clips to the passed rect. Squashed layers need to do this clipping in software,
+ // since there is no graphics layer to clip them precisely. Furthermore, in some cases we squash layers that need clipping in software
+ // from clipping ancestors (see CompositedLayerMapping::localClipRectForSquashedLayer()).
+ context->save();
+ dirtyRect.intersect(paintInfo.localClipRectForSquashedLayer);
+ context->clip(dirtyRect);
+ paintInfo.renderLayer->paintLayer(context, paintingInfo, paintFlags);
+ context->restore();
+ }
+
+ ASSERT(!paintInfo.renderLayer->usedTransparency());
+
+ // Manually restore the context to its original state by applying the opposite translation.
+ context->translate(offset.width(), offset.height());
+}
+
+static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
+{
+ if (!scrollbar)
+ return;
+
+ context.save();
+ const IntRect& scrollbarRect = scrollbar->frameRect();
+ context.translate(-scrollbarRect.x(), -scrollbarRect.y());
+ IntRect transformedClip = clip;
+ transformedClip.moveBy(scrollbarRect.location());
+ scrollbar->paint(&context, transformedClip);
+ context.restore();
+}
+
+// Up-call from compositing layer drawing callback.
+void CompositedLayerMapping::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
+{
+ // https://code.google.com/p/chromium/issues/detail?id=343772
+ DisableCompositingQueryAsserts disabler;
+#ifndef NDEBUG
+ // FIXME: once the state machine is ready, this can be removed and we can refer to that instead.
+ if (Page* page = renderer()->frame()->page())
+ page->setIsPainting(true);
+#endif
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(m_owningLayer.renderer(), clip, graphicsLayer));
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
+ // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
+ InspectorInstrumentation::willPaint(m_owningLayer.renderer(), graphicsLayer);
+
+ if (graphicsLayer == m_graphicsLayer.get()
+ || graphicsLayer == m_foregroundLayer.get()
+ || graphicsLayer == m_backgroundLayer.get()
+ || graphicsLayer == m_maskLayer.get()
+ || graphicsLayer == m_childClippingMaskLayer.get()
+ || graphicsLayer == m_scrollingContentsLayer.get()
+ || graphicsLayer == m_scrollingBlockSelectionLayer.get()) {
+
+ GraphicsLayerPaintInfo paintInfo;
+ paintInfo.renderLayer = &m_owningLayer;
+ paintInfo.compositedBounds = compositedBounds();
+ paintInfo.offsetFromRenderer = graphicsLayer->offsetFromRenderer();
+ paintInfo.paintingPhase = paintingPhase;
+ paintInfo.isBackgroundLayer = (graphicsLayer == m_backgroundLayer);
+
+ // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
+ doPaintTask(paintInfo, &context, clip);
+ } else if (graphicsLayer == m_squashingLayer.get()) {
+ ASSERT(compositor()->layerSquashingEnabled());
+ for (size_t i = 0; i < m_squashedLayers.size(); ++i)
+ doPaintTask(m_squashedLayers[i], &context, clip);
+ } else if (graphicsLayer == layerForHorizontalScrollbar()) {
+ paintScrollbar(m_owningLayer.scrollableArea()->horizontalScrollbar(), context, clip);
+ } else if (graphicsLayer == layerForVerticalScrollbar()) {
+ paintScrollbar(m_owningLayer.scrollableArea()->verticalScrollbar(), context, clip);
+ } else if (graphicsLayer == layerForScrollCorner()) {
+ const IntRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
+ context.save();
+ context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
+ IntRect transformedClip = clip;
+ transformedClip.moveBy(scrollCornerAndResizer.location());
+ m_owningLayer.scrollableArea()->paintScrollCorner(&context, IntPoint(), transformedClip);
+ m_owningLayer.scrollableArea()->paintResizer(&context, IntPoint(), transformedClip);
+ context.restore();
+ }
+ InspectorInstrumentation::didPaint(m_owningLayer.renderer(), graphicsLayer, &context, clip);
+#ifndef NDEBUG
+ if (Page* page = renderer()->frame()->page())
+ page->setIsPainting(false);
+#endif
+}
+
+bool CompositedLayerMapping::isTrackingRepaints() const
+{
+ GraphicsLayerClient* client = compositor();
+ return client ? client->isTrackingRepaints() : false;
+}
+
+struct CollectTrackedRepaintRectsFunctor {
+ void operator() (GraphicsLayer* layer) const { layer->collectTrackedRepaintRects(*rects); }
+ Vector<FloatRect>* rects;
+};
+
+PassOwnPtr<Vector<FloatRect> > CompositedLayerMapping::collectTrackedRepaintRects() const
+{
+ OwnPtr<Vector<FloatRect> > rects = adoptPtr(new Vector<FloatRect>);
+ CollectTrackedRepaintRectsFunctor functor = { rects.get() };
+ ApplyToGraphicsLayers(this, functor, ApplyToAllGraphicsLayers);
+ return rects.release();
+}
+
+#ifndef NDEBUG
+void CompositedLayerMapping::verifyNotPainting()
+{
+ ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
+}
+#endif
+
+void CompositedLayerMapping::notifyAnimationStarted(const GraphicsLayer*, double monotonicTime)
+{
+ renderer()->node()->document().compositorPendingAnimations().notifyCompositorAnimationStarted(monotonicTime);
+}
+
+IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const
+{
+ LayoutRect bounds = m_compositedBounds;
+ bounds.move(m_owningLayer.subpixelAccumulation());
+ return pixelSnappedIntRect(bounds);
+}
+
+bool CompositedLayerMapping::updateSquashingLayerAssignment(RenderLayer* squashedLayer, const RenderLayer& owningLayer, size_t nextSquashedLayerIndex)
+{
+ ASSERT(compositor()->layerSquashingEnabled());
+
+ GraphicsLayerPaintInfo paintInfo;
+ paintInfo.renderLayer = squashedLayer;
+ // NOTE: composited bounds are updated elsewhere
+ // NOTE: offsetFromRenderer is updated elsewhere
+ paintInfo.paintingPhase = GraphicsLayerPaintAllWithOverflowClip;
+ paintInfo.isBackgroundLayer = false;
+
+ // Change tracking on squashing layers: at the first sign of something changed, just invalidate the layer.
+ // FIXME: Perhaps we can find a tighter more clever mechanism later.
+ bool updatedAssignment = false;
+ if (nextSquashedLayerIndex < m_squashedLayers.size()) {
+ if (!paintInfo.isEquivalentForSquashing(m_squashedLayers[nextSquashedLayerIndex])) {
+ compositor()->repaintOnCompositingChange(squashedLayer);
+ updatedAssignment = true;
+ m_squashedLayers[nextSquashedLayerIndex] = paintInfo;
+ }
+ } else {
+ compositor()->repaintOnCompositingChange(squashedLayer);
+ m_squashedLayers.append(paintInfo);
+ updatedAssignment = true;
+ }
+ squashedLayer->setGroupedMapping(this);
+ return updatedAssignment;
+}
+
+void CompositedLayerMapping::removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer* layer)
+{
+ size_t layerIndex = kNotFound;
+
+ for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
+ if (m_squashedLayers[i].renderLayer == layer) {
+ layerIndex = i;
+ break;
+ }
+ }
+
+ if (layerIndex == kNotFound)
+ return;
+
+ m_squashedLayers.remove(layerIndex);
+}
+
+void CompositedLayerMapping::finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex)
+{
+ ASSERT(compositor()->layerSquashingEnabled());
+
+ // Any additional squashed RenderLayers in the array no longer exist, and removing invalidates the squashingLayer contents.
+ if (nextSquashedLayerIndex < m_squashedLayers.size())
+ m_squashedLayers.remove(nextSquashedLayerIndex, m_squashedLayers.size() - nextSquashedLayerIndex);
+}
+
+String CompositedLayerMapping::debugName(const GraphicsLayer* graphicsLayer)
+{
+ String name;
+ if (graphicsLayer == m_graphicsLayer.get()) {
+ name = m_owningLayer.debugName();
+ } else if (graphicsLayer == m_squashingContainmentLayer.get()) {
+ name = "Squashing Containment Layer";
+ } else if (graphicsLayer == m_squashingLayer.get()) {
+ name = "Squashing Layer";
+ } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
+ name = "Ancestor Clipping Layer";
+ } else if (graphicsLayer == m_foregroundLayer.get()) {
+ name = m_owningLayer.debugName() + " (foreground) Layer";
+ } else if (graphicsLayer == m_backgroundLayer.get()) {
+ name = m_owningLayer.debugName() + " (background) Layer";
+ } else if (graphicsLayer == m_childContainmentLayer.get()) {
+ name = "Child Containment Layer";
+ } else if (graphicsLayer == m_childTransformLayer.get()) {
+ name = "Child Transform Layer";
+ } else if (graphicsLayer == m_maskLayer.get()) {
+ name = "Mask Layer";
+ } else if (graphicsLayer == m_childClippingMaskLayer.get()) {
+ name = "Child Clipping Mask Layer";
+ } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
+ name = "Horizontal Scrollbar Layer";
+ } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
+ name = "Vertical Scrollbar Layer";
+ } else if (graphicsLayer == m_layerForScrollCorner.get()) {
+ name = "Scroll Corner Layer";
+ } else if (graphicsLayer == m_scrollingLayer.get()) {
+ name = "Scrolling Layer";
+ } else if (graphicsLayer == m_scrollingContentsLayer.get()) {
+ name = "Scrolling Contents Layer";
+ } else if (graphicsLayer == m_scrollingBlockSelectionLayer.get()) {
+ name = "Scrolling Block Selection Layer";
+ } else {
+ ASSERT_NOT_REACHED();
+ }
+
+ return name;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.h
index b0f85e44d0e..22a0d75a125 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMapping.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMapping.h
@@ -27,40 +27,51 @@
#define CompositedLayerMapping_h
#include "core/rendering/RenderLayer.h"
+#include "core/rendering/compositing/GraphicsLayerUpdater.h"
#include "platform/geometry/FloatPoint.h"
#include "platform/geometry/FloatPoint3D.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/graphics/GraphicsLayerClient.h"
-#include "platform/transforms/TransformationMatrix.h"
namespace WebCore {
-class KeyframeList;
class RenderLayerCompositor;
-class WebAnimationProvider;
-
-enum CompositingLayerType {
- NormalCompositingLayer, // non-tiled layer with backing store
- MediaCompositingLayer, // layer that contains an image, video, webGL or plugin
- ContainerCompositingLayer // layer with no backing store
-};
-
// A GraphicsLayerPaintInfo contains all the info needed to paint a partial subtree of RenderLayers into a GraphicsLayer.
struct GraphicsLayerPaintInfo {
RenderLayer* renderLayer;
- IntRect compositedBounds;
+ LayoutRect compositedBounds;
- // A temporary offset used for squashing layers, when the origin of the
- // squashing layer is not yet known.
- IntSize offsetFromBackingRoot;
+ // The clip rect to apply, in the local coordinate space of the squashed layer, when painting it.
+ IntRect localClipRectForSquashedLayer;
+ // Offset describing where this squashed RenderLayer paints into the shared GraphicsLayer backing.
IntSize offsetFromRenderer;
+ bool offsetFromRendererSet;
+
+ LayoutSize subpixelAccumulation;
GraphicsLayerPaintingPhase paintingPhase;
bool isBackgroundLayer;
+
+ GraphicsLayerPaintInfo() : renderLayer(0), offsetFromRendererSet(false), isBackgroundLayer(false) { }
+
+ bool isEquivalentForSquashing(const GraphicsLayerPaintInfo& other)
+ {
+ // FIXME: offsetFromRenderer and compositedBounds should not be checked here, because
+ // they are not yet fixed at the time this function is used.
+ return renderLayer == other.renderLayer
+ && paintingPhase == other.paintingPhase
+ && isBackgroundLayer == other.isBackgroundLayer;
+ }
+};
+
+enum GraphicsLayerUpdateScope {
+ GraphicsLayerUpdateNone,
+ GraphicsLayerUpdateLocal,
+ GraphicsLayerUpdateSubtree,
};
// CompositedLayerMapping keeps track of how RenderLayers of the render tree correspond to
@@ -70,26 +81,20 @@ struct GraphicsLayerPaintInfo {
//
// Currently (Oct. 2013) there is one CompositedLayerMapping for each RenderLayer,
// but this is likely to evolve soon.
-class CompositedLayerMapping : public GraphicsLayerClient {
+class CompositedLayerMapping FINAL : public GraphicsLayerClient {
WTF_MAKE_NONCOPYABLE(CompositedLayerMapping); WTF_MAKE_FAST_ALLOCATED;
public:
- explicit CompositedLayerMapping(RenderLayer*);
- ~CompositedLayerMapping();
-
- RenderLayer* owningLayer() const { return m_owningLayer; }
+ explicit CompositedLayerMapping(RenderLayer&);
+ virtual ~CompositedLayerMapping();
- enum UpdateAfterLayoutFlag {
- CompositingChildrenOnly = 1 << 0,
- NeedsFullRepaint = 1 << 1,
- IsUpdateRoot = 1 << 2
- };
- typedef unsigned UpdateAfterLayoutFlags;
- void updateAfterLayout(UpdateAfterLayoutFlags);
+ RenderLayer& owningLayer() const { return m_owningLayer; }
// Returns true if layer configuration changed.
- bool updateGraphicsLayerConfiguration();
+ bool updateGraphicsLayerConfiguration(GraphicsLayerUpdater::UpdateType);
// Update graphics layer position and bounds.
- void updateGraphicsLayerGeometry(); // make private
+
+ void updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType, const RenderLayer* compositingContainer, Vector<RenderLayer*>& layersNeedingPaintInvalidation);
+
// Update whether layer needs blending.
void updateContentsOpaque();
@@ -112,14 +117,25 @@ public:
bool hasScrollingLayer() const { return m_scrollingLayer; }
GraphicsLayer* scrollingLayer() const { return m_scrollingLayer.get(); }
GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
+ GraphicsLayer* scrollingBlockSelectionLayer() const { return m_scrollingBlockSelectionLayer.get(); }
bool hasMaskLayer() const { return m_maskLayer; }
+ GraphicsLayer* maskLayer() const { return m_maskLayer.get(); }
+
bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer; }
+ GraphicsLayer* childClippingMaskLayer() const { return m_childClippingMaskLayer.get(); }
GraphicsLayer* parentForSublayers() const;
GraphicsLayer* childForSuperlayers() const;
+ // localRootForOwningLayer does not include the m_squashingContainmentLayer, which is technically not associated with this CLM's owning layer.
+ GraphicsLayer* localRootForOwningLayer() const;
+
+ GraphicsLayer* childTransformLayer() const { return m_childTransformLayer.get(); }
+ GraphicsLayer* squashingContainmentLayer() const { return m_squashingContainmentLayer.get(); }
GraphicsLayer* squashingLayer() const { return m_squashingLayer.get(); }
+ // Contains the bottommost layer in the hierarchy that can contain the children transform.
+ GraphicsLayer* layerForChildrenTransform() const;
// Returns true for a composited layer that has no backing store of its own, so
// paints into some ancestor layer.
@@ -134,6 +150,7 @@ public:
// a backing store changed.
bool updateRequiresOwnBackingStoreForIntrinsicReasons();
+ void setSquashingContentsNeedDisplay();
void setContentsNeedDisplay();
// r is in the coordinate space of the layer's render object
void setContentsNeedDisplayInRect(const IntRect&);
@@ -141,47 +158,33 @@ public:
// Notification from the renderer that its content changed.
void contentChanged(ContentChangeType);
- // Interface to start, finish, suspend and resume animations and transitions
- bool startTransition(double, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle);
- void transitionPaused(double timeOffset, CSSPropertyID);
- void transitionFinished(CSSPropertyID);
-
- bool startAnimation(double timeOffset, const CSSAnimationData*, const KeyframeList& keyframes);
- void animationPaused(double timeOffset, const String& name);
- void animationFinished(const String& name);
+ LayoutRect compositedBounds() const { return m_compositedBounds; }
+ IntRect pixelSnappedCompositedBounds() const;
+ void updateCompositedBounds(GraphicsLayerUpdater::UpdateType);
- IntRect compositedBounds() const;
- void setCompositedBounds(const IntRect&);
- void updateCompositedBounds();
-
- void updateAfterWidgetResize();
void positionOverflowControlsLayers(const IntSize& offsetFromRoot);
bool hasUnpositionedOverflowControlsLayers() const;
- void addRenderLayerToSquashingGraphicsLayer(RenderLayer*, IntSize offsetFromTargetBacking, size_t nextSquashedLayerIndex);
+ // Returns true if the assignment actually changed the assigned squashing layer.
+ bool updateSquashingLayerAssignment(RenderLayer* squashedLayer, const RenderLayer& owningLayer, size_t nextSquashedLayerIndex);
+ void removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer*);
+
void finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex);
+ void updateRenderingContext();
+ void updateShouldFlattenTransform();
// GraphicsLayerClient interface
- virtual void notifyAnimationStarted(const GraphicsLayer*, double wallClockTime, double monotonicTime) OVERRIDE;
-
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) OVERRIDE;
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip) OVERRIDE;
-
- virtual void didCommitChangesForLayer(const GraphicsLayer*) const OVERRIDE;
- virtual bool getCurrentTransform(const GraphicsLayer*, TransformationMatrix&) const OVERRIDE;
-
virtual bool isTrackingRepaints() const OVERRIDE;
PassOwnPtr<Vector<FloatRect> > collectTrackedRepaintRects() const;
#ifndef NDEBUG
- virtual void verifyNotPainting();
+ virtual void verifyNotPainting() OVERRIDE;
#endif
- IntRect contentsBox() const;
- IntRect backgroundBox() const;
-
- // For informative purposes only.
- CompositingLayerType compositingLayerType() const;
+ LayoutRect contentsBox() const;
GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
@@ -190,48 +193,88 @@ public:
void updateFilters(const RenderStyle*);
bool canCompositeFilters() const { return m_canCompositeFilters; }
- // Return an estimate of the backing store area (in pixels) allocated by this object's GraphicsLayers.
- double backingStoreMemoryEstimate() const;
-
void setBlendMode(blink::WebBlendMode);
+ void setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateScope scope) { m_pendingUpdateScope = std::max(static_cast<GraphicsLayerUpdateScope>(m_pendingUpdateScope), scope); }
+ void clearNeedsGraphicsLayerUpdate() { m_pendingUpdateScope = GraphicsLayerUpdateNone; }
+
+ bool shouldUpdateGraphicsLayer(GraphicsLayerUpdater::UpdateType updateType) const { return m_pendingUpdateScope > GraphicsLayerUpdateNone || updateType == GraphicsLayerUpdater::ForceUpdate; }
+ GraphicsLayerUpdater::UpdateType updateTypeForChildren(GraphicsLayerUpdater::UpdateType) const;
+
+#if ASSERT_ENABLED
+ void assertNeedsToUpdateGraphicsLayerBitsCleared() { ASSERT(m_pendingUpdateScope == GraphicsLayerUpdateNone); }
+#endif
+
virtual String debugName(const GraphicsLayer*) OVERRIDE;
+ LayoutSize contentOffsetInCompositingLayer() const;
+
+ LayoutPoint squashingOffsetFromTransformedAncestor()
+ {
+ return m_squashingLayerOffsetFromTransformedAncestor;
+ }
+
+ // If there is a squashed layer painting into this CLM that is an ancestor of the given RenderObject, return it. Otherwise return 0.
+ const GraphicsLayerPaintInfo* containingSquashedLayer(const RenderObject*);
+
+ void updateScrollingBlockSelection();
+
private:
+ static const GraphicsLayerPaintInfo* containingSquashedLayer(const RenderObject*, const Vector<GraphicsLayerPaintInfo>& layers);
+
+ // Helper methods to updateGraphicsLayerGeometry:
+ void computeGraphicsLayerParentLocation(const RenderLayer* compositingContainer, const IntRect& ancestorCompositingBounds, IntPoint& graphicsLayerParentLocation);
+ void updateSquashingLayerGeometry(const LayoutPoint& offsetFromCompositedAncestor, const IntPoint& graphicsLayerParentLocation, const RenderLayer& referenceLayer, Vector<GraphicsLayerPaintInfo>& layers, GraphicsLayer*, LayoutPoint* offsetFromTransformedAncestor, Vector<RenderLayer*>& layersNeedingPaintInvalidation);
+ void updateMainGraphicsLayerGeometry(const IntRect& relativeCompositingBounds, const IntRect& localCompositingBounds, IntPoint& graphicsLayerParentLocation);
+ void updateAncestorClippingLayerGeometry(const RenderLayer* compositingContainer, const IntPoint& snappedOffsetFromCompositedAncestor, IntPoint& graphicsLayerParentLocation);
+ void updateChildContainmentLayerGeometry(const IntRect& clippingBox, const IntRect& localCompositingBounds);
+ void updateChildTransformLayerGeometry();
+ void updateMaskLayerGeometry();
+ void updateTransformGeometry(const IntPoint& snappedOffsetFromCompositedAncestor, const IntRect& relativeCompositingBounds);
+ void updateForegroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize, const IntRect& clippingBox);
+ void updateBackgroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize);
+ void updateReflectionLayerGeometry(Vector<RenderLayer*>& layersNeedingPaintInvalidation);
+ void updateScrollingLayerGeometry(const IntRect& localCompositingBounds);
+ void updateChildClippingMaskLayerGeometry();
+
void createPrimaryGraphicsLayer();
void destroyGraphicsLayers();
PassOwnPtr<GraphicsLayer> createGraphicsLayer(CompositingReasons);
+ bool toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer>&, bool needsLayer, CompositingReasons);
- RenderLayerModelObject* renderer() const { return m_owningLayer->renderer(); }
- RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); }
+ RenderLayerModelObject* renderer() const { return m_owningLayer.renderer(); }
+ RenderLayerCompositor* compositor() const { return m_owningLayer.compositor(); }
void updateInternalHierarchy();
+ void updatePaintingPhases();
bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
+ bool updateChildTransformLayer(bool needsChildTransformLayer);
bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer);
bool updateForegroundLayer(bool needsForegroundLayer);
bool updateBackgroundLayer(bool needsBackgroundLayer);
bool updateMaskLayer(bool needsMaskLayer);
bool updateClippingMaskLayers(bool needsChildClippingMaskLayer);
- bool requiresHorizontalScrollbarLayer() const { return m_owningLayer->scrollableArea() && m_owningLayer->scrollableArea()->horizontalScrollbar(); }
- bool requiresVerticalScrollbarLayer() const { return m_owningLayer->scrollableArea() && m_owningLayer->scrollableArea()->verticalScrollbar(); }
- bool requiresScrollCornerLayer() const { return m_owningLayer->scrollableArea() && !m_owningLayer->scrollableArea()->scrollCornerAndResizerRect().isEmpty(); }
+ bool requiresHorizontalScrollbarLayer() const { return m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->horizontalScrollbar(); }
+ bool requiresVerticalScrollbarLayer() const { return m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->verticalScrollbar(); }
+ bool requiresScrollCornerLayer() const { return m_owningLayer.scrollableArea() && !m_owningLayer.scrollableArea()->scrollCornerAndResizerRect().isEmpty(); }
bool updateScrollingLayers(bool scrollingLayers);
void updateScrollParent(RenderLayer*);
void updateClipParent(RenderLayer*);
bool updateSquashingLayers(bool needsSquashingLayers);
- void updateDrawsContent(bool isSimpleContainer);
+ void updateDrawsContent();
+ void updateChildrenTransform();
void registerScrollingLayers();
+ // Also sets subpixelAccumulation on the layer.
+ void computeBoundsOfOwningLayer(const RenderLayer* compositedAncestor, IntRect& localCompositingBounds, IntRect& compositingBoundsRelativeToCompositedAncestor, LayoutPoint& offsetFromCompositedAncestor, IntPoint& snappedOffsetFromCompositedAncestor);
+
void setBackgroundLayerPaintsFixedRootBackground(bool);
GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
- IntSize contentOffsetInCompostingLayer() const;
// Result is transform origin in pixels.
FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const;
- // Result is perspective origin in pixels.
- FloatPoint computePerspectiveOrigin(const IntRect& borderBox) const;
void updateOpacity(const RenderStyle*);
void updateTransform(const RenderStyle*);
@@ -242,39 +285,42 @@ 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.
- bool containsPaintedContent(bool isSimpleContainer) const;
+ bool containsPaintedContent() const;
// Returns true if the RenderLayer just contains an image that we can composite directly.
bool isDirectlyCompositedImage() const;
void updateImageContents();
Color rendererBackgroundColor() const;
- void updateBackgroundColor(bool isSimpleContainer);
- void updateContentsRect(bool isSimpleContainer);
-
+ void updateBackgroundColor();
+ void updateContentsRect();
+ void updateAfterWidgetResize();
void updateCompositingReasons();
- bool hasVisibleNonCompositingDescendantLayers() const;
-
- bool shouldClipCompositedBounds() const;
+ static bool hasVisibleNonCompositingDescendant(RenderLayer* parent);
void paintsIntoCompositedAncestorChanged();
void doPaintTask(GraphicsLayerPaintInfo&, GraphicsContext*, const IntRect& clip);
- RenderLayer* m_owningLayer;
+ // Computes the background clip rect for the given squashed layer, up to any containing layer that is squashed into the
+ // same squashing layer and contains this squashed layer's clipping ancestor.
+ // The clip rect is returned in the coordinate space of the given squashed layer.
+ // If there is no such containing layer, returns the infinite rect.
+ // FIXME: unify this code with the code that sets up m_ancestorClippingLayer. They are doing very similar things.
+ static IntRect localClipRectForSquashedLayer(const RenderLayer& referenceLayer, const GraphicsLayerPaintInfo&, const Vector<GraphicsLayerPaintInfo>& layers);
+
+ RenderLayer& m_owningLayer;
// The hierarchy of layers that is maintained by the CompositedLayerMapping looks like this:
//
// + m_ancestorClippingLayer [OPTIONAL]
// + m_graphicsLayer
- // + m_childContainmentLayer [OPTIONAL] <-OR-> m_scrollingLayer [OPTIONAL]
- // + m_scrollingContentsLayer [OPTIONAL]
+ // + m_childContainmentLayer [OPTIONAL] <-OR-> m_scrollingLayer [OPTIONAL] <-OR-> m_childTransformLayer
+ // + m_scrollingContentsLayer [Present iff m_scrollingLayer is present]
+ // + m_scrollingBlockSelectionLayer [Present iff m_scrollingLayer is present]
//
// We need an ancestor clipping layer if our clipping ancestor is not our ancestor in the
// clipping tree. Here's what that might look like.
@@ -299,8 +345,10 @@ private:
OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // Only used if we are clipped by an ancestor which is not a stacking context.
OwnPtr<GraphicsLayer> m_graphicsLayer;
OwnPtr<GraphicsLayer> m_childContainmentLayer; // Only used if we have clipping on a stacking context with compositing children.
+ OwnPtr<GraphicsLayer> m_childTransformLayer; // Only used if we have perspective and no m_childContainmentLayer.
OwnPtr<GraphicsLayer> m_scrollingLayer; // Only used if the layer is using composited scrolling.
OwnPtr<GraphicsLayer> m_scrollingContentsLayer; // Only used if the layer is using composited scrolling.
+ OwnPtr<GraphicsLayer> m_scrollingBlockSelectionLayer; // Only used if the layer is using composited scrolling, but has no scrolling contents apart from block selection gaps.
// This layer is also added to the hierarchy by the RLB, but in a different way than
// the layers above. It's added to m_graphicsLayer as its mask layer (naturally) if
@@ -337,21 +385,33 @@ private:
OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
OwnPtr<GraphicsLayer> m_layerForScrollCorner;
- OwnPtr<WebAnimationProvider> m_animationProvider;
-
- OwnPtr<GraphicsLayer> m_squashingContainmentLayer; // Only used if any squashed layers exist, to contain the squashed layers as siblings to the rest of the GraphicsLayer tree chunk.
+ // A squashing CLM has two possible squashing-related structures.
+ //
+ // If m_ancestorClippingLayer is present:
+ //
+ // m_ancestorClippingLayer
+ // + m_graphicsLayer
+ // + m_squashingLayer
+ //
+ // If not:
+ //
+ // m_squashingContainmentLayer
+ // + m_graphicsLayer
+ // + m_squashingLayer
+ OwnPtr<GraphicsLayer> m_squashingContainmentLayer; // Only used if any squashed layers exist and m_squashingContainmentLayer is not present, to contain the squashed layers as siblings to the rest of the GraphicsLayer tree chunk.
OwnPtr<GraphicsLayer> m_squashingLayer; // Only used if any squashed layers exist, this is the backing that squashed layers paint into.
Vector<GraphicsLayerPaintInfo> m_squashedLayers;
+ LayoutPoint m_squashingLayerOffsetFromTransformedAncestor;
- IntRect m_compositedBounds;
+ LayoutRect m_compositedBounds;
- bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work
- bool m_boundsConstrainedByClipping;
- bool m_isMainFrameRenderViewLayer;
- bool m_requiresOwnBackingStoreForIntrinsicReasons;
- bool m_requiresOwnBackingStoreForAncestorReasons;
- bool m_canCompositeFilters;
- bool m_backgroundLayerPaintsFixedRootBackground;
+ unsigned m_pendingUpdateScope : 2;
+ unsigned m_isMainFrameRenderViewLayer : 1;
+ unsigned m_requiresOwnBackingStoreForIntrinsicReasons : 1;
+ unsigned m_requiresOwnBackingStoreForAncestorReasons : 1;
+ unsigned m_canCompositeFilters : 1;
+ unsigned m_backgroundLayerPaintsFixedRootBackground : 1;
+ unsigned m_scrollingContentsAreEmpty : 1;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMappingPtr.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMappingPtr.h
index 27cb68581d5..27cb68581d5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/CompositedLayerMappingPtr.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositedLayerMappingPtr.h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.cpp
new file mode 100644
index 00000000000..af8ea1f0973
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.cpp
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/rendering/compositing/CompositingInputsUpdater.h"
+
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+
+namespace WebCore {
+
+CompositingInputsUpdater::CompositingInputsUpdater(RenderLayer* rootRenderLayer)
+ : m_geometryMap(UseTransforms)
+ , m_rootRenderLayer(rootRenderLayer)
+{
+ rootRenderLayer->updateDescendantDependentFlags();
+}
+
+CompositingInputsUpdater::~CompositingInputsUpdater()
+{
+}
+
+void CompositingInputsUpdater::update(RenderLayer* layer, UpdateType updateType, AncestorInfo info)
+{
+ if (!layer->childNeedsCompositingInputsUpdate() && updateType != ForceUpdate)
+ return;
+
+ m_geometryMap.pushMappingsToAncestor(layer, layer->parent());
+
+ if (layer->hasCompositedLayerMapping())
+ info.enclosingCompositedLayer = layer;
+
+ if (layer->needsCompositingInputsUpdate()) {
+ if (info.enclosingCompositedLayer)
+ info.enclosingCompositedLayer->compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+ updateType = ForceUpdate;
+ }
+
+ if (updateType == ForceUpdate) {
+ RenderLayer::CompositingInputs properties;
+
+ if (!layer->isRootLayer()) {
+ properties.clippedAbsoluteBoundingBox = enclosingIntRect(m_geometryMap.absoluteRect(layer->boundingBoxForCompositingOverlapTest()));
+ // FIXME: Setting the absBounds to 1x1 instead of 0x0 makes very little sense,
+ // but removing this code will make JSGameBench sad.
+ // See https://codereview.chromium.org/13912020/
+ if (properties.clippedAbsoluteBoundingBox.isEmpty())
+ properties.clippedAbsoluteBoundingBox.setSize(IntSize(1, 1));
+
+ IntRect clipRect = pixelSnappedIntRect(layer->clipper().backgroundClipRect(ClipRectsContext(m_rootRenderLayer, AbsoluteClipRects)).rect());
+ properties.clippedAbsoluteBoundingBox.intersect(clipRect);
+
+ const RenderLayer* parent = layer->parent();
+ properties.opacityAncestor = parent->isTransparent() ? parent : parent->compositingInputs().opacityAncestor;
+ properties.transformAncestor = parent->transform() ? parent : parent->compositingInputs().transformAncestor;
+ properties.filterAncestor = parent->hasFilter() ? parent : parent->compositingInputs().filterAncestor;
+
+ if (layer->renderer()->isOutOfFlowPositioned() && info.ancestorScrollingLayer && !layer->subtreeIsInvisible()) {
+ const RenderObject* container = layer->renderer()->containingBlock();
+ const RenderObject* scroller = info.ancestorScrollingLayer->renderer();
+ properties.isUnclippedDescendant = scroller != container && scroller->isDescendantOf(container);
+ }
+ }
+
+ layer->updateCompositingInputs(properties);
+ }
+
+ if (layer->scrollsOverflow())
+ info.ancestorScrollingLayer = layer;
+
+ for (RenderLayer* child = layer->firstChild(); child; child = child->nextSibling())
+ update(child, updateType, info);
+
+ m_geometryMap.popMappingsToAncestor(layer->parent());
+
+ layer->clearChildNeedsCompositingInputsUpdate();
+}
+
+#if ASSERT_ENABLED
+
+void CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(RenderLayer* layer)
+{
+ ASSERT(!layer->childNeedsCompositingInputsUpdate());
+ ASSERT(!layer->needsCompositingInputsUpdate());
+
+ for (RenderLayer* child = layer->firstChild(); child; child = child->nextSibling())
+ assertNeedsCompositingInputsUpdateBitsCleared(child);
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.h
new file mode 100644
index 00000000000..49086287061
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingInputsUpdater.h
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CompositingInputsUpdater_h
+#define CompositingInputsUpdater_h
+
+#include "core/rendering/RenderGeometryMap.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+class CompositingInputsUpdater {
+private:
+ struct AncestorInfo {
+ AncestorInfo()
+ : enclosingCompositedLayer(0)
+ , ancestorScrollingLayer(0)
+ {
+ }
+
+ RenderLayer* enclosingCompositedLayer;
+ RenderLayer* ancestorScrollingLayer;
+ };
+
+public:
+ explicit CompositingInputsUpdater(RenderLayer* rootRenderLayer);
+ ~CompositingInputsUpdater();
+
+ enum UpdateType {
+ DoNotForceUpdate,
+ ForceUpdate,
+ };
+
+ void update(RenderLayer*, UpdateType = DoNotForceUpdate, AncestorInfo = AncestorInfo());
+
+#if ASSERT_ENABLED
+ static void assertNeedsCompositingInputsUpdateBitsCleared(RenderLayer*);
+#endif
+
+private:
+ RenderGeometryMap m_geometryMap;
+ RenderLayer* m_rootRenderLayer;
+};
+
+} // namespace WebCore
+
+#endif // CompositingInputsUpdater_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.cpp
new file mode 100644
index 00000000000..e3d944fef94
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 "core/rendering/compositing/CompositingLayerAssigner.h"
+
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+
+namespace WebCore {
+
+// We will only allow squashing if the bbox-area:squashed-area doesn't exceed
+// the ratio |gSquashingSparsityTolerance|:1.
+static uint64_t gSquashingSparsityTolerance = 6;
+
+CompositingLayerAssigner::CompositingLayerAssigner(RenderLayerCompositor* compositor)
+ : m_compositor(compositor)
+ , m_layerSquashingEnabled(compositor->layerSquashingEnabled())
+{
+}
+
+CompositingLayerAssigner::~CompositingLayerAssigner()
+{
+}
+
+void CompositingLayerAssigner::assign(RenderLayer* updateRoot, bool& layersChanged, Vector<RenderLayer*>& layersNeedingRepaint)
+{
+ SquashingState squashingState;
+ assignLayersToBackingsInternal(updateRoot, squashingState, layersChanged, layersNeedingRepaint);
+ if (squashingState.hasMostRecentMapping)
+ squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex);
+}
+
+void CompositingLayerAssigner::SquashingState::updateSquashingStateForNewMapping(CompositedLayerMappingPtr newCompositedLayerMapping, bool hasNewCompositedLayerMapping)
+{
+ // The most recent backing is done accumulating any more squashing layers.
+ if (hasMostRecentMapping)
+ mostRecentMapping->finishAccumulatingSquashingLayers(nextSquashedLayerIndex);
+
+ nextSquashedLayerIndex = 0;
+ boundingRect = IntRect();
+ mostRecentMapping = newCompositedLayerMapping;
+ hasMostRecentMapping = hasNewCompositedLayerMapping;
+ haveAssignedBackingsToEntireSquashingLayerSubtree = false;
+}
+
+bool CompositingLayerAssigner::squashingWouldExceedSparsityTolerance(const RenderLayer* candidate, const CompositingLayerAssigner::SquashingState& squashingState)
+{
+ IntRect bounds = candidate->compositingInputs().clippedAbsoluteBoundingBox;
+ IntRect newBoundingRect = squashingState.boundingRect;
+ newBoundingRect.unite(bounds);
+ const uint64_t newBoundingRectArea = newBoundingRect.size().area();
+ const uint64_t newSquashedArea = squashingState.totalAreaOfSquashedRects + bounds.size().area();
+ return newBoundingRectArea > gSquashingSparsityTolerance * newSquashedArea;
+}
+
+bool CompositingLayerAssigner::needsOwnBacking(const RenderLayer* layer) const
+{
+ if (!m_compositor->canBeComposited(layer))
+ return false;
+
+ // If squashing is disabled, then layers that would have been squashed should just be separately composited.
+ bool needsOwnBackingForDisabledSquashing = !m_layerSquashingEnabled && requiresSquashing(layer->compositingReasons());
+
+ return requiresCompositing(layer->compositingReasons()) || needsOwnBackingForDisabledSquashing || (m_compositor->staleInCompositingMode() && layer->isRootLayer());
+}
+
+CompositingStateTransitionType CompositingLayerAssigner::computeCompositedLayerUpdate(RenderLayer* layer)
+{
+ CompositingStateTransitionType update = NoCompositingStateChange;
+ if (needsOwnBacking(layer)) {
+ if (!layer->hasCompositedLayerMapping()) {
+ update = AllocateOwnCompositedLayerMapping;
+ }
+ } else {
+ if (layer->hasCompositedLayerMapping())
+ update = RemoveOwnCompositedLayerMapping;
+
+ if (m_layerSquashingEnabled) {
+ if (!layer->subtreeIsInvisible() && requiresSquashing(layer->compositingReasons())) {
+ // We can't compute at this time whether the squashing layer update is a no-op,
+ // since that requires walking the render layer tree.
+ update = PutInSquashingLayer;
+ } else if (layer->groupedMapping() || layer->lostGroupedMapping()) {
+ update = RemoveFromSquashingLayer;
+ }
+ }
+ }
+ return update;
+}
+
+CompositingReasons CompositingLayerAssigner::getReasonsPreventingSquashing(const RenderLayer* layer, const CompositingLayerAssigner::SquashingState& squashingState)
+{
+ if (!squashingState.haveAssignedBackingsToEntireSquashingLayerSubtree)
+ return CompositingReasonSquashingWouldBreakPaintOrder;
+
+ // FIXME: this special case for video exists only to deal with corner cases
+ // where a RenderVideo does not report that it needs to be directly composited.
+ // Video does not currently support sharing a backing, but this could be
+ // generalized in the future. The following layout tests fail if we permit the
+ // video to share a backing with other layers.
+ //
+ // compositing/video/video-controls-layer-creation.html
+ // virtual/softwarecompositing/video/video-controls-layer-creation.html
+ if (layer->renderer()->isVideo())
+ return CompositingReasonSquashingVideoIsDisallowed;
+
+ if (squashingWouldExceedSparsityTolerance(layer, squashingState))
+ return CompositingReasonSquashingSparsityExceeded;
+
+ // FIXME: this is not efficient, since it walks up the tree . We should store these values on the CompositingInputsCache.
+ ASSERT(squashingState.hasMostRecentMapping);
+ const RenderLayer& squashingLayer = squashingState.mostRecentMapping->owningLayer();
+
+ if (layer->renderer()->clippingContainer() != squashingLayer.renderer()->clippingContainer()) {
+ if (!squashingLayer.compositedLayerMapping()->containingSquashedLayer(layer->renderer()->clippingContainer()))
+ return CompositingReasonSquashingClippingContainerMismatch;
+ }
+
+ // Composited descendants need to be clipped by a child containment graphics layer, which would not be available if the layer is
+ // squashed (and therefore has no CLM nor a child containment graphics layer).
+ if (m_compositor->clipsCompositingDescendants(layer))
+ return CompositingReasonSquashedLayerClipsCompositingDescendants;
+
+ if (layer->scrollsWithRespectTo(&squashingLayer))
+ return CompositingReasonScrollsWithRespectToSquashingLayer;
+
+ const RenderLayer::CompositingInputs& compositingInputs = layer->compositingInputs();
+ const RenderLayer::CompositingInputs& squashingLayerCompositingInputs = squashingLayer.compositingInputs();
+
+ if (compositingInputs.opacityAncestor != squashingLayerCompositingInputs.opacityAncestor)
+ return CompositingReasonSquashingOpacityAncestorMismatch;
+
+ if (compositingInputs.transformAncestor != squashingLayerCompositingInputs.transformAncestor)
+ return CompositingReasonSquashingTransformAncestorMismatch;
+
+ if (compositingInputs.filterAncestor != squashingLayerCompositingInputs.filterAncestor)
+ return CompositingReasonSquashingFilterAncestorMismatch;
+
+ return CompositingReasonNone;
+}
+
+bool CompositingLayerAssigner::updateSquashingAssignment(RenderLayer* layer, SquashingState& squashingState, const CompositingStateTransitionType compositedLayerUpdate,
+ Vector<RenderLayer*>& layersNeedingRepaint)
+{
+ // NOTE: In the future as we generalize this, the background of this layer may need to be assigned to a different backing than
+ // the squashed RenderLayer's own primary contents. This would happen when we have a composited negative z-index element that needs
+ // to paint on top of the background, but below the layer's main contents. For now, because we always composite layers
+ // when they have a composited negative z-index child, such layers will never need squashing so it is not yet an issue.
+ if (compositedLayerUpdate == PutInSquashingLayer) {
+ // A layer that is squashed with other layers cannot have its own CompositedLayerMapping.
+ ASSERT(!layer->hasCompositedLayerMapping());
+ ASSERT(squashingState.hasMostRecentMapping);
+
+ bool changedSquashingLayer =
+ squashingState.mostRecentMapping->updateSquashingLayerAssignment(layer, squashingState.mostRecentMapping->owningLayer(), squashingState.nextSquashedLayerIndex);
+ if (!changedSquashingLayer)
+ return true;
+
+ // If we've modified the collection of squashed layers, we must update
+ // the graphics layer geometry.
+ squashingState.mostRecentMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+
+ layer->clipper().clearClipRectsIncludingDescendants();
+
+ // Issue a repaint, since |layer| may have been added to an already-existing squashing layer.
+ layersNeedingRepaint.append(layer);
+
+ return true;
+ }
+ if (compositedLayerUpdate == RemoveFromSquashingLayer) {
+ if (layer->groupedMapping()) {
+ // Before removing |layer| from an already-existing squashing layer that may have other content, issue a repaint.
+ m_compositor->repaintOnCompositingChange(layer);
+ layer->groupedMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
+ layer->setGroupedMapping(0);
+ }
+
+ // If we need to repaint, do so now that we've removed it from a squashed layer.
+ layersNeedingRepaint.append(layer);
+
+ layer->setLostGroupedMapping(false);
+ return true;
+ }
+
+ return false;
+}
+
+void CompositingLayerAssigner::assignLayersToBackingsForReflectionLayer(RenderLayer* reflectionLayer, bool& layersChanged, Vector<RenderLayer*>& layersNeedingRepaint)
+{
+ CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(reflectionLayer);
+ if (compositedLayerUpdate != NoCompositingStateChange) {
+ layersNeedingRepaint.append(reflectionLayer);
+ layersChanged = true;
+ m_compositor->allocateOrClearCompositedLayerMapping(reflectionLayer, compositedLayerUpdate);
+ }
+ m_compositor->updateDirectCompositingReasons(reflectionLayer);
+ if (reflectionLayer->hasCompositedLayerMapping())
+ reflectionLayer->compositedLayerMapping()->updateGraphicsLayerConfiguration(GraphicsLayerUpdater::ForceUpdate);
+}
+
+void CompositingLayerAssigner::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, bool& layersChanged, Vector<RenderLayer*>& layersNeedingRepaint)
+{
+ if (m_layerSquashingEnabled && requiresSquashing(layer->compositingReasons())) {
+ CompositingReasons reasonsPreventingSquashing = getReasonsPreventingSquashing(layer, squashingState);
+ if (reasonsPreventingSquashing)
+ layer->setCompositingReasons(layer->compositingReasons() | reasonsPreventingSquashing);
+ }
+
+ CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(layer);
+
+ if (m_compositor->allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate)) {
+ layersNeedingRepaint.append(layer);
+ layersChanged = true;
+ }
+
+ // FIXME: special-casing reflection layers here is not right.
+ if (layer->reflectionInfo())
+ assignLayersToBackingsForReflectionLayer(layer->reflectionInfo()->reflectionLayer(), layersChanged, layersNeedingRepaint);
+
+ // Add this layer to a squashing backing if needed.
+ if (m_layerSquashingEnabled) {
+ if (updateSquashingAssignment(layer, squashingState, compositedLayerUpdate, layersNeedingRepaint))
+ layersChanged = true;
+
+ const bool layerIsSquashed = compositedLayerUpdate == PutInSquashingLayer || (compositedLayerUpdate == NoCompositingStateChange && layer->groupedMapping());
+ if (layerIsSquashed) {
+ squashingState.nextSquashedLayerIndex++;
+ IntRect layerBounds = layer->compositingInputs().clippedAbsoluteBoundingBox;
+ squashingState.totalAreaOfSquashedRects += layerBounds.size().area();
+ squashingState.boundingRect.unite(layerBounds);
+ }
+ }
+
+ if (layer->stackingNode()->isStackingContext()) {
+ RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
+ while (RenderLayerStackingNode* curNode = iterator.next())
+ assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged, layersNeedingRepaint);
+ }
+
+ if (m_layerSquashingEnabled) {
+ // At this point, if the layer is to be "separately" composited, then its backing becomes the most recent in paint-order.
+ if (layer->compositingState() == PaintsIntoOwnBacking || layer->compositingState() == HasOwnBackingButPaintsIntoAncestor) {
+ ASSERT(!requiresSquashing(layer->compositingReasons()));
+ squashingState.updateSquashingStateForNewMapping(layer->compositedLayerMapping(), layer->hasCompositedLayerMapping());
+ }
+ }
+
+ RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
+ while (RenderLayerStackingNode* curNode = iterator.next())
+ assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged, layersNeedingRepaint);
+
+ if (squashingState.hasMostRecentMapping && &squashingState.mostRecentMapping->owningLayer() == layer)
+ squashingState.haveAssignedBackingsToEntireSquashingLayerSubtree = true;
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.h
new file mode 100644
index 00000000000..ccc283d3e20
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingLayerAssigner.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 CompositingLayerAssigner_h
+#define CompositingLayerAssigner_h
+
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+#include "platform/geometry/IntRect.h"
+#include "platform/geometry/LayoutPoint.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+class CompositingLayerAssigner {
+public:
+ explicit CompositingLayerAssigner(RenderLayerCompositor*);
+ ~CompositingLayerAssigner();
+
+ void assign(RenderLayer* updateRoot, bool& layersChanged, Vector<RenderLayer*>& layersNeedingRepaint);
+
+ // FIXME: This function should be private. We should remove the one caller
+ // once we've fixed the compositing chicken/egg issues.
+ CompositingStateTransitionType computeCompositedLayerUpdate(RenderLayer*);
+
+private:
+ struct SquashingState {
+ SquashingState()
+ : mostRecentMapping(0)
+ , hasMostRecentMapping(false)
+ , haveAssignedBackingsToEntireSquashingLayerSubtree(false)
+ , nextSquashedLayerIndex(0)
+ , totalAreaOfSquashedRects(0) { }
+
+ void updateSquashingStateForNewMapping(CompositedLayerMappingPtr, bool hasNewCompositedLayerMapping);
+
+ // The most recent composited backing that the layer should squash onto if needed.
+ CompositedLayerMappingPtr mostRecentMapping;
+ bool hasMostRecentMapping;
+
+ // Whether all RenderLayers in the stacking subtree rooted at the most recent mapping's
+ // owning layer have had CompositedLayerMappings assigned. Layers cannot squash into a
+ // CompositedLayerMapping owned by a stacking ancestor, since this changes paint order.
+ bool haveAssignedBackingsToEntireSquashingLayerSubtree;
+
+ // Counter that tracks what index the next RenderLayer would be if it gets squashed to the current squashing layer.
+ size_t nextSquashedLayerIndex;
+
+ // The absolute bounding rect of all the squashed layers.
+ IntRect boundingRect;
+
+ // This is simply the sum of the areas of the squashed rects. This can be very skewed if the rects overlap,
+ // but should be close enough to drive a heuristic.
+ uint64_t totalAreaOfSquashedRects;
+ };
+
+ void assignLayersToBackingsInternal(RenderLayer*, SquashingState&, bool& layersChanged, Vector<RenderLayer*>& layersNeedingRepaint);
+ void assignLayersToBackingsForReflectionLayer(RenderLayer* reflectionLayer, bool& layersChanged, Vector<RenderLayer*>& layersNeedingRepaint);
+ CompositingReasons getReasonsPreventingSquashing(const RenderLayer*, const SquashingState&);
+ bool squashingWouldExceedSparsityTolerance(const RenderLayer* candidate, const SquashingState&);
+ bool updateSquashingAssignment(RenderLayer*, SquashingState&, CompositingStateTransitionType, Vector<RenderLayer*>& layersNeedingRepaint);
+ bool needsOwnBacking(const RenderLayer*) const;
+
+ RenderLayerCompositor* m_compositor;
+ bool m_layerSquashingEnabled;
+};
+
+} // namespace WebCore
+
+#endif // CompositingLayerAssigner_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.cpp
new file mode 100644
index 00000000000..289ba10aed5
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.cpp
@@ -0,0 +1,236 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/rendering/compositing/CompositingReasonFinder.h"
+
+#include "core/frame/FrameView.h"
+#include "core/frame/Settings.h"
+#include "core/page/Page.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+
+namespace WebCore {
+
+CompositingReasonFinder::CompositingReasonFinder(RenderView& renderView)
+ : m_renderView(renderView)
+ , m_compositingTriggers(static_cast<CompositingTriggerFlags>(AllCompositingTriggers))
+{
+ updateTriggers();
+}
+
+void CompositingReasonFinder::updateTriggers()
+{
+ m_compositingTriggers = 0;
+
+ Settings& settings = m_renderView.document().page()->settings();
+ if (settings.acceleratedCompositingForVideoEnabled())
+ m_compositingTriggers |= VideoTrigger;
+ if (settings.acceleratedCompositingForCanvasEnabled())
+ m_compositingTriggers |= CanvasTrigger;
+ if (settings.compositedScrollingForFramesEnabled())
+ m_compositingTriggers |= ScrollableInnerFrameTrigger;
+ if (settings.acceleratedCompositingForFiltersEnabled())
+ m_compositingTriggers |= FilterTrigger;
+
+ // We map both these settings to universal overlow scrolling.
+ // FIXME: Replace these settings with a generic compositing setting for HighDPI.
+ if (settings.acceleratedCompositingForOverflowScrollEnabled() || settings.compositorDrivenAcceleratedScrollingEnabled())
+ m_compositingTriggers |= OverflowScrollTrigger;
+
+ // FIXME: acceleratedCompositingForFixedPositionEnabled should be renamed acceleratedCompositingForViewportConstrainedPositionEnabled().
+ // Or the sticky and fixed position elements should be behind different flags.
+ if (settings.acceleratedCompositingForFixedPositionEnabled())
+ m_compositingTriggers |= ViewportConstrainedPositionedTrigger;
+}
+
+bool CompositingReasonFinder::hasOverflowScrollTrigger() const
+{
+ return m_compositingTriggers & OverflowScrollTrigger;
+}
+
+bool CompositingReasonFinder::isMainFrame() const
+{
+ // FIXME: LocalFrame::isMainFrame() is probably better.
+ return !m_renderView.document().ownerElement();
+}
+
+CompositingReasons CompositingReasonFinder::directReasons(const RenderLayer* layer) const
+{
+ CompositingReasons styleReasons = layer->styleDeterminedCompositingReasons();
+ ASSERT(styleDeterminedReasons(layer->renderer()) == styleReasons);
+ return styleReasons | nonStyleDeterminedDirectReasons(layer);
+}
+
+// This information doesn't appear to be incorporated into CompositingReasons.
+bool CompositingReasonFinder::requiresCompositingForScrollableFrame() const
+{
+ // Need this done first to determine overflow.
+ ASSERT(!m_renderView.needsLayout());
+ if (isMainFrame())
+ return false;
+
+ if (!(m_compositingTriggers & ScrollableInnerFrameTrigger))
+ return false;
+
+ return m_renderView.frameView()->isScrollable();
+}
+
+CompositingReasons CompositingReasonFinder::styleDeterminedReasons(RenderObject* renderer) const
+{
+ CompositingReasons directReasons = CompositingReasonNone;
+
+ RenderStyle* style = renderer->style();
+
+ if (requiresCompositingForTransform(renderer))
+ directReasons |= CompositingReason3DTransform;
+
+ if (requiresCompositingForFilters(renderer))
+ directReasons |= CompositingReasonFilters;
+
+ if (style->backfaceVisibility() == BackfaceVisibilityHidden)
+ directReasons |= CompositingReasonBackfaceVisibilityHidden;
+
+ if (requiresCompositingForAnimation(style))
+ directReasons |= CompositingReasonActiveAnimation;
+
+ if (style->hasWillChangeCompositingHint() && !style->subtreeWillChangeContents())
+ directReasons |= CompositingReasonWillChangeCompositingHint;
+
+ ASSERT(!(directReasons & ~CompositingReasonComboAllStyleDeterminedReasons));
+ return directReasons;
+}
+
+bool CompositingReasonFinder::requiresCompositingForTransform(RenderObject* renderer) const
+{
+ // Note that we ask the renderer if it has a transform, because the style may have transforms,
+ // but the renderer may be an inline that doesn't suppport them.
+ return renderer->hasTransform() && renderer->style()->transform().has3DOperation();
+}
+
+bool CompositingReasonFinder::requiresCompositingForFilters(RenderObject* renderer) const
+{
+ if (!(m_compositingTriggers & FilterTrigger))
+ return false;
+
+ return renderer->hasFilter();
+}
+
+CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(const RenderLayer* layer) const
+{
+ CompositingReasons directReasons = CompositingReasonNone;
+ RenderObject* renderer = layer->renderer();
+
+ if (hasOverflowScrollTrigger()) {
+ // IsUnclippedDescendant is only actually stale during the chicken/egg code path.
+ // FIXME: Use compositingInputs().isUnclippedDescendant to ASSERT that
+ // this value isn't stale.
+ if (layer->compositingInputs().isUnclippedDescendant)
+ directReasons |= CompositingReasonOutOfFlowClipping;
+
+ if (layer->scrollParent())
+ directReasons |= CompositingReasonOverflowScrollingParent;
+
+ if (layer->needsCompositedScrolling())
+ directReasons |= CompositingReasonOverflowScrollingTouch;
+ }
+
+ if (requiresCompositingForPositionFixed(renderer, layer, 0))
+ directReasons |= CompositingReasonPositionFixed;
+
+ directReasons |= renderer->additionalCompositingReasons(m_compositingTriggers);
+
+ ASSERT(!(directReasons & CompositingReasonComboAllStyleDeterminedReasons));
+ return directReasons;
+}
+
+bool CompositingReasonFinder::requiresCompositingForAnimation(RenderStyle* style) const
+{
+ if (style->subtreeWillChangeContents())
+ return style->isRunningAnimationOnCompositor();
+
+ return style->shouldCompositeForCurrentAnimations();
+}
+
+bool CompositingReasonFinder::requiresCompositingForPositionFixed(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
+{
+ if (!(m_compositingTriggers & ViewportConstrainedPositionedTrigger))
+ return false;
+
+ if (renderer->style()->position() != FixedPosition)
+ return false;
+
+ RenderObject* container = renderer->container();
+ // If the renderer is not hooked up yet then we have to wait until it is.
+ if (!container) {
+ ASSERT(m_renderView.document().lifecycle().state() < DocumentLifecycle::InCompositingUpdate);
+ // FIXME: Remove this and ASSERT(container) once we get rid of the incremental
+ // allocateOrClearCompositedLayerMapping compositing update. This happens when
+ // adding the renderer to the tree because we setStyle before addChild in
+ // createRendererForElementIfNeeded.
+ return false;
+ }
+
+ // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
+ // They will stay fixed wrt the container rather than the enclosing frame.
+ if (container != &m_renderView) {
+ if (viewportConstrainedNotCompositedReason)
+ *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer;
+ return false;
+ }
+
+ // If the fixed-position element does not have any scrollable ancestor between it and
+ // its container, then we do not need to spend compositor resources for it. Start by
+ // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below.
+ bool hasScrollableAncestor = false;
+
+ // The FrameView has the scrollbars associated with the top level viewport, so we have to
+ // check the FrameView in addition to the hierarchy of ancestors.
+ FrameView* frameView = m_renderView.frameView();
+ if (frameView && frameView->isScrollable())
+ hasScrollableAncestor = true;
+
+ RenderLayer* ancestor = layer->parent();
+ while (ancestor && !hasScrollableAncestor) {
+ if (ancestor->scrollsOverflow())
+ hasScrollableAncestor = true;
+ if (ancestor->renderer() == &m_renderView)
+ break;
+ ancestor = ancestor->parent();
+ }
+
+ if (!hasScrollableAncestor) {
+ if (viewportConstrainedNotCompositedReason)
+ *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors;
+ return false;
+ }
+
+ // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done.
+ // FIXME: Get rid of this codepath once we get rid of the incremental compositing update in RenderLayer::styleChanged.
+ if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean)
+ return layer->hasCompositedLayerMapping();
+
+ bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant();
+ if (!paintsContent) {
+ if (viewportConstrainedNotCompositedReason)
+ *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent;
+ return false;
+ }
+
+ // Fixed position elements that are invisible in the current view don't get their own layer.
+ if (FrameView* frameView = m_renderView.frameView()) {
+ ASSERT(m_renderView.document().lifecycle().state() == DocumentLifecycle::InCompositingUpdate);
+ LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect();
+ LayoutRect layerBounds = layer->boundingBoxForCompositing(layer->compositor()->rootRenderLayer(), RenderLayer::ApplyBoundsChickenEggHacks);
+ if (!viewBounds.intersects(enclosingIntRect(layerBounds))) {
+ if (viewportConstrainedNotCompositedReason)
+ *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.h
new file mode 100644
index 00000000000..dce877b3fee
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingReasonFinder.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CompositingReasonFinder_h
+#define CompositingReasonFinder_h
+
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/compositing/CompositingTriggers.h"
+#include "platform/graphics/CompositingReasons.h"
+
+namespace WebCore {
+
+class RenderObject;
+class RenderView;
+
+class CompositingReasonFinder {
+ WTF_MAKE_NONCOPYABLE(CompositingReasonFinder);
+public:
+ explicit CompositingReasonFinder(RenderView&);
+
+ CompositingReasons styleDeterminedReasons(RenderObject*) const;
+ CompositingReasons directReasons(const RenderLayer*) const;
+
+ void updateTriggers();
+
+ bool hasOverflowScrollTrigger() const;
+
+ bool requiresCompositingForScrollableFrame() const;
+ bool requiresCompositingForPositionFixed(RenderObject*, const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason*) const;
+
+private:
+ bool isMainFrame() const;
+
+ CompositingReasons nonStyleDeterminedDirectReasons(const RenderLayer*) const;
+
+ bool requiresCompositingForTransform(RenderObject*) const;
+ bool requiresCompositingForFilters(RenderObject*) const;
+ bool requiresCompositingForAnimation(RenderStyle*) const;
+
+ RenderView& m_renderView;
+ CompositingTriggerFlags m_compositingTriggers;
+};
+
+} // namespace WebCore
+
+#endif // CompositingReasonFinder_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.cpp
new file mode 100644
index 00000000000..f44d52d0472
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.cpp
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 "core/rendering/compositing/CompositingRequirementsUpdater.h"
+
+#include "core/rendering/RenderLayerStackingNode.h"
+#include "core/rendering/RenderLayerStackingNodeIterator.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+#include "platform/TraceEvent.h"
+
+namespace WebCore {
+
+class OverlapMapContainer {
+public:
+ void add(const IntRect& bounds)
+ {
+ m_layerRects.append(bounds);
+ m_boundingBox.unite(bounds);
+ }
+
+ bool overlapsLayers(const IntRect& bounds) const
+ {
+ // Checking with the bounding box will quickly reject cases when
+ // layers are created for lists of items going in one direction and
+ // never overlap with each other.
+ if (!bounds.intersects(m_boundingBox))
+ return false;
+ for (unsigned i = 0; i < m_layerRects.size(); i++) {
+ if (m_layerRects[i].intersects(bounds))
+ return true;
+ }
+ return false;
+ }
+
+ void unite(const OverlapMapContainer& otherContainer)
+ {
+ m_layerRects.appendVector(otherContainer.m_layerRects);
+ m_boundingBox.unite(otherContainer.m_boundingBox);
+ }
+private:
+ Vector<IntRect, 64> m_layerRects;
+ IntRect m_boundingBox;
+};
+
+class CompositingRequirementsUpdater::OverlapMap {
+ WTF_MAKE_NONCOPYABLE(OverlapMap);
+public:
+ OverlapMap()
+ {
+ // Begin by assuming the root layer will be composited so that there
+ // is something on the stack. The root layer should also never get a
+ // finishCurrentOverlapTestingContext() call.
+ beginNewOverlapTestingContext();
+ }
+
+ void add(RenderLayer* layer, const IntRect& bounds)
+ {
+ ASSERT(!layer->isRootLayer());
+ if (bounds.isEmpty())
+ return;
+
+ // Layers do not contribute to overlap immediately--instead, they will
+ // contribute to overlap as soon as they have been recursively processed
+ // and popped off the stack.
+ ASSERT(m_overlapStack.size() >= 2);
+ m_overlapStack[m_overlapStack.size() - 2].add(bounds);
+ }
+
+ bool overlapsLayers(const IntRect& bounds) const
+ {
+ return m_overlapStack.last().overlapsLayers(bounds);
+ }
+
+ void beginNewOverlapTestingContext()
+ {
+ // This effectively creates a new "clean slate" for overlap state.
+ // This is used when we know that a subtree or remaining set of
+ // siblings does not need to check overlap with things behind it.
+ m_overlapStack.append(OverlapMapContainer());
+ }
+
+ void finishCurrentOverlapTestingContext()
+ {
+ // The overlap information on the top of the stack is still necessary
+ // for checking overlap of any layers outside this context that may
+ // overlap things from inside this context. Therefore, we must merge
+ // the information from the top of the stack before popping the stack.
+ //
+ // FIXME: we may be able to avoid this deep copy by rearranging how
+ // overlapMap state is managed.
+ m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
+ m_overlapStack.removeLast();
+ }
+
+private:
+ Vector<OverlapMapContainer> m_overlapStack;
+};
+
+class CompositingRequirementsUpdater::RecursionData {
+public:
+ RecursionData(RenderLayer* compAncestor, bool testOverlap)
+ : m_compositingAncestor(compAncestor)
+ , m_subtreeIsCompositing(false)
+ , m_hasUnisolatedCompositedBlendingDescendant(false)
+ , m_testingOverlap(testOverlap)
+#ifndef NDEBUG
+ , m_depth(0)
+#endif
+ {
+ }
+
+ RecursionData(const RecursionData& other)
+ : m_compositingAncestor(other.m_compositingAncestor)
+ , m_subtreeIsCompositing(other.m_subtreeIsCompositing)
+ , m_hasUnisolatedCompositedBlendingDescendant(other.m_hasUnisolatedCompositedBlendingDescendant)
+ , m_testingOverlap(other.m_testingOverlap)
+#ifndef NDEBUG
+ , m_depth(other.m_depth + 1)
+#endif
+ {
+ }
+
+ RenderLayer* m_compositingAncestor;
+ bool m_subtreeIsCompositing;
+ bool m_hasUnisolatedCompositedBlendingDescendant;
+ bool m_testingOverlap;
+#ifndef NDEBUG
+ int m_depth;
+#endif
+};
+
+static bool requiresCompositingOrSquashing(CompositingReasons reasons)
+{
+#ifndef NDEBUG
+ bool fastAnswer = reasons != CompositingReasonNone;
+ bool slowAnswer = requiresCompositing(reasons) || requiresSquashing(reasons);
+ ASSERT(fastAnswer == slowAnswer);
+#endif
+ return reasons != CompositingReasonNone;
+}
+
+static CompositingReasons subtreeReasonsForCompositing(RenderObject* renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants)
+{
+ CompositingReasons subtreeReasons = CompositingReasonNone;
+
+ // FIXME: this seems to be a potentially different layer than the layer for which this was called. May not be an error, but is very confusing.
+ RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
+
+ // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
+ // via compositing so that they also apply to those composited descdendants.
+ if (hasCompositedDescendants) {
+ if (layer->transform())
+ subtreeReasons |= CompositingReasonTransformWithCompositedDescendants;
+
+ if (layer->shouldIsolateCompositedDescendants()) {
+ ASSERT(layer->stackingNode()->isStackingContext());
+ subtreeReasons |= CompositingReasonIsolateCompositedDescendants;
+ }
+
+ // If the implementation of createsGroup changes, we need to be aware of that in this part of code.
+ ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->hasFilter() || renderer->hasBlendMode()) == renderer->createsGroup());
+ if (renderer->isTransparent())
+ subtreeReasons |= CompositingReasonOpacityWithCompositedDescendants;
+ if (renderer->hasMask())
+ subtreeReasons |= CompositingReasonMaskWithCompositedDescendants;
+ if (renderer->hasFilter())
+ subtreeReasons |= CompositingReasonFilterWithCompositedDescendants;
+ if (renderer->hasBlendMode())
+ subtreeReasons |= CompositingReasonBlendingWithCompositedDescendants;
+
+ if (renderer->hasReflection())
+ subtreeReasons |= CompositingReasonReflectionWithCompositedDescendants;
+
+ if (renderer->hasClipOrOverflowClip())
+ subtreeReasons |= CompositingReasonClipsCompositingDescendants;
+ }
+
+ // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that
+ // will be affected by the preserve-3d or perspective.
+ if (has3DTransformedDescendants) {
+ if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D)
+ subtreeReasons |= CompositingReasonPreserve3DWith3DDescendants;
+
+ if (renderer->style()->hasPerspective())
+ subtreeReasons |= CompositingReasonPerspectiveWith3DDescendants;
+ }
+
+ return subtreeReasons;
+}
+
+CompositingRequirementsUpdater::CompositingRequirementsUpdater(RenderView& renderView, CompositingReasonFinder& compositingReasonFinder)
+ : m_renderView(renderView)
+ , m_compositingReasonFinder(compositingReasonFinder)
+{
+}
+
+CompositingRequirementsUpdater::~CompositingRequirementsUpdater()
+{
+}
+
+void CompositingRequirementsUpdater::update(RenderLayer* root)
+{
+ TRACE_EVENT0("blink_rendering", "CompositingRequirementsUpdater::updateRecursive");
+
+ // 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.
+ RecursionData recursionData(root, true);
+ OverlapMap overlapTestRequestMap;
+ bool saw3DTransform = false;
+
+ // FIXME: Passing these unclippedDescendants down and keeping track
+ // of them dynamically, we are requiring a full tree walk. This
+ // should be removed as soon as proper overlap testing based on
+ // scrolling and animation bounds is implemented (crbug.com/252472).
+ Vector<RenderLayer*> unclippedDescendants;
+ IntRect absoluteDecendantBoundingBox;
+ updateRecursive(0, root, overlapTestRequestMap, recursionData, saw3DTransform, unclippedDescendants, absoluteDecendantBoundingBox);
+}
+
+void CompositingRequirementsUpdater::updateRecursive(RenderLayer* ancestorLayer, RenderLayer* layer, OverlapMap& overlapMap, RecursionData& currentRecursionData, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants, IntRect& absoluteDecendantBoundingBox)
+{
+ RenderLayerCompositor* compositor = m_renderView.compositor();
+
+ layer->stackingNode()->updateLayerListsIfNeeded();
+
+ CompositingReasons reasonsToComposite = CompositingReasonNone;
+ CompositingReasons directReasons = m_compositingReasonFinder.directReasons(layer);
+
+ // Video is special. It's the only RenderLayer type that can both have
+ // RenderLayer children and whose children can't use its backing to render
+ // into. These children (the controls) always need to be promoted into their
+ // own layers to draw on top of the accelerated video.
+ if (currentRecursionData.m_compositingAncestor && currentRecursionData.m_compositingAncestor->renderer()->isVideo())
+ directReasons |= CompositingReasonVideoOverlay;
+
+ if (compositor->canBeComposited(layer))
+ reasonsToComposite |= directReasons;
+
+ // Next, accumulate reasons related to overlap.
+ // If overlap testing is used, this reason will be overridden. If overlap testing is not
+ // used, we must assume we overlap if there is anything composited behind us in paint-order.
+ CompositingReasons overlapCompositingReason = currentRecursionData.m_subtreeIsCompositing ? CompositingReasonAssumedOverlap : CompositingReasonNone;
+
+ if (m_renderView.compositor()->acceleratedCompositingForOverflowScrollEnabled()) {
+ Vector<size_t> unclippedDescendantsToRemove;
+ for (size_t i = 0; i < unclippedDescendants.size(); i++) {
+ RenderLayer* unclippedDescendant = unclippedDescendants.at(i);
+ // If we've reached the containing block of one of the unclipped
+ // descendants, that element is no longer relevant to whether or not we
+ // should opt in. Unfortunately we can't easily remove from the list
+ // while we're iterating, so we have to store it for later removal.
+ if (unclippedDescendant->renderer()->containingBlock() == layer->renderer()) {
+ unclippedDescendantsToRemove.append(i);
+ continue;
+ }
+ if (layer->scrollsWithRespectTo(unclippedDescendant))
+ reasonsToComposite |= CompositingReasonAssumedOverlap;
+ }
+
+ // Remove irrelevant unclipped descendants in reverse order so our stored
+ // indices remain valid.
+ for (size_t i = 0; i < unclippedDescendantsToRemove.size(); i++)
+ unclippedDescendants.remove(unclippedDescendantsToRemove.at(unclippedDescendantsToRemove.size() - i - 1));
+
+ if (reasonsToComposite & CompositingReasonOutOfFlowClipping)
+ unclippedDescendants.append(layer);
+ }
+
+ const IntRect& absBounds = layer->compositingInputs().clippedAbsoluteBoundingBox;
+ absoluteDecendantBoundingBox = absBounds;
+
+ if (currentRecursionData.m_testingOverlap && !requiresCompositingOrSquashing(directReasons))
+ overlapCompositingReason = overlapMap.overlapsLayers(absBounds) ? CompositingReasonOverlap : CompositingReasonNone;
+
+ reasonsToComposite |= overlapCompositingReason;
+
+ // 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.
+ RecursionData childRecursionData(currentRecursionData);
+ childRecursionData.m_subtreeIsCompositing = false;
+
+ bool willBeCompositedOrSquashed = compositor->canBeComposited(layer) && requiresCompositingOrSquashing(reasonsToComposite);
+ if (willBeCompositedOrSquashed) {
+ // Tell the parent it has compositing descendants.
+ currentRecursionData.m_subtreeIsCompositing = true;
+ // This layer now acts as the ancestor for kids.
+ childRecursionData.m_compositingAncestor = layer;
+
+ // Here we know that all children and the layer's own contents can blindly paint into
+ // this layer's backing, until a descendant is composited. So, we don't need to check
+ // for overlap with anything behind this layer.
+ overlapMap.beginNewOverlapTestingContext();
+ // This layer is going to be composited, so children can safely ignore the fact that there's an
+ // animation running behind this layer, meaning they can rely on the overlap map testing again.
+ childRecursionData.m_testingOverlap = true;
+ }
+
+#if ASSERT_ENABLED
+ LayerListMutationDetector mutationChecker(layer->stackingNode());
+#endif
+
+ bool anyDescendantHas3DTransform = false;
+ bool willHaveForegroundLayer = false;
+
+ if (layer->stackingNode()->isStackingContext()) {
+ RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
+ while (RenderLayerStackingNode* curNode = iterator.next()) {
+ IntRect absoluteChildDecendantBoundingBox;
+ updateRecursive(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundingBox);
+ absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox);
+
+ // If we have to make a layer for this child, make one now so we can have a contents layer
+ // (since we need to ensure that the -ve z-order child renders underneath our contents).
+ if (childRecursionData.m_subtreeIsCompositing) {
+ reasonsToComposite |= CompositingReasonNegativeZIndexChildren;
+
+ if (!willBeCompositedOrSquashed) {
+ // make layer compositing
+ childRecursionData.m_compositingAncestor = layer;
+ overlapMap.beginNewOverlapTestingContext();
+ willBeCompositedOrSquashed = true;
+ willHaveForegroundLayer = true;
+
+ // FIXME: temporary solution for the first negative z-index composited child:
+ // re-compute the absBounds for the child so that we can add the
+ // negative z-index child's bounds to the new overlap context.
+ overlapMap.beginNewOverlapTestingContext();
+ overlapMap.add(curNode->layer(), curNode->layer()->compositingInputs().clippedAbsoluteBoundingBox);
+ overlapMap.finishCurrentOverlapTestingContext();
+ }
+ }
+ }
+ }
+
+ if (willHaveForegroundLayer) {
+ ASSERT(willBeCompositedOrSquashed);
+ // A foreground layer effectively is a new backing for all subsequent children, so
+ // we don't need to test for overlap with anything behind this. So, we can finish
+ // the previous context that was accumulating rects for the negative z-index
+ // children, and start with a fresh new empty context.
+ overlapMap.finishCurrentOverlapTestingContext();
+ overlapMap.beginNewOverlapTestingContext();
+ // This layer is going to be composited, so children can safely ignore the fact that there's an
+ // animation running behind this layer, meaning they can rely on the overlap map testing again
+ childRecursionData.m_testingOverlap = true;
+ }
+
+ RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
+ while (RenderLayerStackingNode* curNode = iterator.next()) {
+ IntRect absoluteChildDecendantBoundingBox;
+ updateRecursive(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundingBox);
+ absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox);
+ }
+
+ // Now that the subtree has been traversed, we can check for compositing reasons that depended on the state of the subtree.
+
+ if (layer->stackingNode()->isStackingContext()) {
+ layer->setShouldIsolateCompositedDescendants(childRecursionData.m_hasUnisolatedCompositedBlendingDescendant);
+ } else {
+ layer->setShouldIsolateCompositedDescendants(false);
+ currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = childRecursionData.m_hasUnisolatedCompositedBlendingDescendant;
+ }
+
+ // Subsequent layers in the parent's stacking context may also need to composite.
+ if (childRecursionData.m_subtreeIsCompositing)
+ currentRecursionData.m_subtreeIsCompositing = true;
+
+ // Set the flag to say that this SC has compositing children.
+ layer->setHasCompositingDescendant(childRecursionData.m_subtreeIsCompositing);
+
+ if (layer->isRootLayer()) {
+ // The root layer needs to be composited if anything else in the tree is composited.
+ // Otherwise, we can disable compositing entirely.
+ if (childRecursionData.m_subtreeIsCompositing || requiresCompositingOrSquashing(reasonsToComposite) || compositor->rootShouldAlwaysComposite()) {
+ reasonsToComposite |= CompositingReasonRoot;
+ } else {
+ compositor->setCompositingModeEnabled(false);
+ reasonsToComposite = CompositingReasonNone;
+ }
+ } else {
+ // All layers (even ones that aren't being composited) need to get added to
+ // the overlap map. Layers that are not separately composited will paint into their
+ // compositing ancestor's backing, and so are still considered for overlap.
+ if (childRecursionData.m_compositingAncestor && !childRecursionData.m_compositingAncestor->isRootLayer())
+ overlapMap.add(layer, absBounds);
+
+ // Now check for reasons to become composited that depend on the state of descendant layers.
+ CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing(layer->renderer(), childRecursionData.m_subtreeIsCompositing, anyDescendantHas3DTransform);
+ reasonsToComposite |= subtreeCompositingReasons;
+ if (!willBeCompositedOrSquashed && compositor->canBeComposited(layer) && requiresCompositingOrSquashing(subtreeCompositingReasons)) {
+ childRecursionData.m_compositingAncestor = layer;
+ // FIXME: this context push is effectively a no-op but needs to exist for
+ // now, because the code is designed to push overlap information to the
+ // second-from-top context of the stack.
+ overlapMap.beginNewOverlapTestingContext();
+ overlapMap.add(layer, absoluteDecendantBoundingBox);
+ willBeCompositedOrSquashed = true;
+ }
+
+ // If the original layer is composited, the reflection needs to be, too.
+ if (layer->reflectionInfo()) {
+ // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
+ RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer();
+ CompositingReasons reflectionCompositingReason = willBeCompositedOrSquashed ? CompositingReasonReflectionOfCompositedParent : CompositingReasonNone;
+ reflectionLayer->setCompositingReasons(reflectionLayer->compositingReasons() | reflectionCompositingReason);
+ }
+
+ if (willBeCompositedOrSquashed && layer->blendInfo().hasBlendMode())
+ currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = true;
+
+ // Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
+ // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
+ // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
+ bool isCompositedClippingLayer = compositor->canBeComposited(layer) && (reasonsToComposite & CompositingReasonClipsCompositingDescendants);
+ if ((!childRecursionData.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer->renderer()))
+ currentRecursionData.m_testingOverlap = false;
+
+ if (childRecursionData.m_compositingAncestor == layer)
+ overlapMap.finishCurrentOverlapTestingContext();
+
+ descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform();
+ }
+
+ // At this point we have finished collecting all reasons to composite this layer.
+ layer->setCompositingReasons(reasonsToComposite);
+
+}
+
+bool CompositingRequirementsUpdater::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
+{
+ return renderer->style()->hasCurrentTransformAnimation();
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.h
new file mode 100644
index 00000000000..09f219fb002
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingRequirementsUpdater.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 CompositingRequirementsUpdater_h
+#define CompositingRequirementsUpdater_h
+
+#include "platform/geometry/IntRect.h"
+#include "platform/graphics/CompositingReasons.h"
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+class CompositingReasonFinder;
+class RenderLayer;
+class RenderObject;
+class RenderView;
+
+class CompositingRequirementsUpdater {
+public:
+ CompositingRequirementsUpdater(RenderView&, CompositingReasonFinder&);
+ ~CompositingRequirementsUpdater();
+
+ // Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
+ // For the z-order children of a compositing layer:
+ // If a child layers has a compositing layer, then all subsequent layers must
+ // be compositing in order to render above that layer.
+ //
+ // If a child in the negative z-order list is compositing, then the layer itself
+ // must be compositing so that its contents render over that child.
+ // This implies that its positive z-index children must also be compositing.
+ //
+ void update(RenderLayer* root);
+
+private:
+ class OverlapMap;
+ class RecursionData;
+
+ void updateRecursive(RenderLayer* ancestorLayer, RenderLayer* currentLayer, OverlapMap&, RecursionData&, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants, IntRect& absoluteDecendantBoundingBox);
+ bool isRunningAcceleratedTransformAnimation(RenderObject*) const;
+
+ RenderView& m_renderView;
+ CompositingReasonFinder& m_compositingReasonFinder;
+};
+
+} // namespace WebCore
+
+#endif // CompositingRequirementsUpdater_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/CompositingState.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingState.h
index 3873871f304..3873871f304 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/CompositingState.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingState.h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/BidiRun.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingTriggers.h
index 4af7881a87e..499718864be 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/BidiRun.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/CompositingTriggers.h
@@ -1,8 +1,7 @@
-/**
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple, Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2012 Samsung Electronics. 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
@@ -18,34 +17,25 @@
* 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"
-#include "core/rendering/BidiRun.h"
-#include "platform/Partitions.h"
-#include "wtf/RefCountedLeakCounter.h"
-
-using namespace WTF;
+#ifndef CompositingTriggers_h
+#define CompositingTriggers_h
namespace WebCore {
-DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, bidiRunCounter, ("BidiRun"));
+enum CompositingTrigger {
+ VideoTrigger = 1 << 1,
+ CanvasTrigger = 1 << 3,
+ FilterTrigger = 1 << 5,
+ ScrollableInnerFrameTrigger = 1 << 6,
+ OverflowScrollTrigger = 1 << 7,
+ ViewportConstrainedPositionedTrigger = 1 << 8,
+ AllCompositingTriggers = 0xFFFFFFFF,
+};
-void* BidiRun::operator new(size_t sz)
-{
-#ifndef NDEBUG
- bidiRunCounter.increment();
-#endif
- return partitionAlloc(Partitions::getRenderingPartition(), sz);
-}
+typedef unsigned CompositingTriggerFlags;
-void BidiRun::operator delete(void* ptr)
-{
-#ifndef NDEBUG
- bidiRunCounter.decrement();
-#endif
- partitionFree(ptr);
}
-}
+#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.cpp
new file mode 100644
index 00000000000..9826be1185e
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 "core/rendering/compositing/GraphicsLayerTreeBuilder.h"
+
+#include "core/html/HTMLMediaElement.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerReflectionInfo.h"
+#include "core/rendering/RenderPart.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+
+namespace WebCore {
+
+GraphicsLayerTreeBuilder::GraphicsLayerTreeBuilder()
+{
+}
+
+GraphicsLayerTreeBuilder::~GraphicsLayerTreeBuilder()
+{
+}
+
+static bool shouldAppendLayer(const RenderLayer& layer)
+{
+ if (!RuntimeEnabledFeatures::overlayFullscreenVideoEnabled())
+ return true;
+ Node* node = layer.renderer()->node();
+ if (node && isHTMLMediaElement(*node) && toHTMLMediaElement(node)->isFullscreen())
+ return false;
+ return true;
+}
+
+void GraphicsLayerTreeBuilder::rebuild(RenderLayer& layer, GraphicsLayerVector& childLayersOfEnclosingLayer)
+{
+ // 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
+ // have been processed. computeCompositingRequirements() will already have done the repaint if necessary.
+
+ layer.stackingNode()->updateLayerListsIfNeeded();
+
+ const bool hasCompositedLayerMapping = layer.hasCompositedLayerMapping();
+ CompositedLayerMappingPtr currentCompositedLayerMapping = layer.compositedLayerMapping();
+
+ // If this layer has a compositedLayerMapping, then that is where we place subsequent children GraphicsLayers.
+ // Otherwise children continue to append to the child list of the enclosing layer.
+ GraphicsLayerVector layerChildren;
+ GraphicsLayerVector& childList = hasCompositedLayerMapping ? layerChildren : childLayersOfEnclosingLayer;
+
+#if ASSERT_ENABLED
+ LayerListMutationDetector mutationChecker(layer.stackingNode());
+#endif
+
+ if (layer.stackingNode()->isStackingContext()) {
+ RenderLayerStackingNodeIterator iterator(*layer.stackingNode(), NegativeZOrderChildren);
+ while (RenderLayerStackingNode* curNode = iterator.next())
+ rebuild(*curNode->layer(), childList);
+
+ // If a negative z-order child is compositing, we get a foreground layer which needs to get parented.
+ if (hasCompositedLayerMapping && currentCompositedLayerMapping->foregroundLayer())
+ childList.append(currentCompositedLayerMapping->foregroundLayer());
+ }
+
+ RenderLayerStackingNodeIterator iterator(*layer.stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
+ while (RenderLayerStackingNode* curNode = iterator.next())
+ rebuild(*curNode->layer(), childList);
+
+ if (hasCompositedLayerMapping) {
+ bool parented = false;
+ if (layer.renderer()->isRenderPart())
+ parented = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(layer.renderer()));
+
+ if (!parented)
+ currentCompositedLayerMapping->parentForSublayers()->setChildren(layerChildren);
+
+ // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
+ // Otherwise, the overflow control layers are normal children.
+ if (!currentCompositedLayerMapping->hasClippingLayer() && !currentCompositedLayerMapping->hasScrollingLayer()) {
+ if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForHorizontalScrollbar()) {
+ overflowControlLayer->removeFromParent();
+ currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer);
+ }
+
+ if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForVerticalScrollbar()) {
+ overflowControlLayer->removeFromParent();
+ currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer);
+ }
+
+ if (GraphicsLayer* overflowControlLayer = currentCompositedLayerMapping->layerForScrollCorner()) {
+ overflowControlLayer->removeFromParent();
+ currentCompositedLayerMapping->parentForSublayers()->addChild(overflowControlLayer);
+ }
+ }
+
+ if (shouldAppendLayer(layer))
+ childLayersOfEnclosingLayer.append(currentCompositedLayerMapping->childForSuperlayers());
+ }
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderBoxRegionInfo.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.h
index 3bde47e9477..4389ebe7f83 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderBoxRegionInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerTreeBuilder.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,37 +24,24 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef GraphicsLayerTreeBuilder_h
+#define GraphicsLayerTreeBuilder_h
-#ifndef RenderBoxRegionInfo_h
-#define RenderBoxRegionInfo_h
-
-#include "platform/LayoutUnit.h"
-#include "wtf/FastAllocBase.h"
+#include "platform/graphics/GraphicsLayer.h"
+#include "wtf/Vector.h"
namespace WebCore {
-class RenderBoxRegionInfo {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- RenderBoxRegionInfo(LayoutUnit logicalLeft, LayoutUnit logicalWidth, bool isShifted)
- : m_logicalLeft(logicalLeft)
- , m_logicalWidth(logicalWidth)
- , m_isShifted(isShifted)
- { }
-
- LayoutUnit logicalLeft() const { return m_logicalLeft; }
- LayoutUnit logicalWidth() const { return m_logicalWidth; }
+class RenderLayer;
- void shiftLogicalLeft(LayoutUnit delta) { m_logicalLeft += delta; m_isShifted = true; }
-
- bool isShifted() const { return m_isShifted; }
+class GraphicsLayerTreeBuilder {
+public:
+ GraphicsLayerTreeBuilder();
+ ~GraphicsLayerTreeBuilder();
-private:
- LayoutUnit m_logicalLeft;
- LayoutUnit m_logicalWidth;
- bool m_isShifted;
+ void rebuild(RenderLayer&, GraphicsLayerVector& childLayersOfEnclosingLayer);
};
} // namespace WebCore
-#endif // RenderBoxRegionInfo_h
+#endif // GraphicsLayerTreeBuilder_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.cpp
new file mode 100644
index 00000000000..ab9428cef19
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 "core/rendering/compositing/GraphicsLayerUpdater.h"
+
+#include "core/html/HTMLMediaElement.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerReflectionInfo.h"
+#include "core/rendering/RenderPart.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+
+namespace WebCore {
+
+GraphicsLayerUpdater::UpdateContext::UpdateContext(const UpdateContext& other, const RenderLayer& layer)
+ : m_compositingStackingContext(other.m_compositingStackingContext)
+ , m_compositingAncestor(other.compositingContainer(layer))
+{
+ CompositingState compositingState = layer.compositingState();
+ if (compositingState != NotComposited && compositingState != PaintsIntoGroupedBacking) {
+ m_compositingAncestor = &layer;
+ if (layer.stackingNode()->isStackingContext())
+ m_compositingStackingContext = &layer;
+ }
+}
+
+const RenderLayer* GraphicsLayerUpdater::UpdateContext::compositingContainer(const RenderLayer& layer) const
+{
+ return layer.stackingNode()->isNormalFlowOnly() ? m_compositingAncestor : m_compositingStackingContext;
+}
+
+GraphicsLayerUpdater::GraphicsLayerUpdater()
+ : m_needsRebuildTree(false)
+{
+}
+
+GraphicsLayerUpdater::~GraphicsLayerUpdater()
+{
+}
+
+void GraphicsLayerUpdater::update(Vector<RenderLayer*>& layersNeedingPaintInvalidation, RenderLayer& layer, UpdateType updateType, const UpdateContext& context)
+{
+ if (layer.hasCompositedLayerMapping()) {
+ CompositedLayerMappingPtr mapping = layer.compositedLayerMapping();
+
+ const RenderLayer* compositingContainer = context.compositingContainer(layer);
+ ASSERT(compositingContainer == layer.ancestorCompositingLayer());
+ if (mapping->updateRequiresOwnBackingStoreForAncestorReasons(compositingContainer))
+ updateType = ForceUpdate;
+
+ // Note carefully: here we assume that the compositing state of all descendants have been updated already,
+ // so it is legitimate to compute and cache the composited bounds for this layer.
+ mapping->updateCompositedBounds(updateType);
+
+ if (RenderLayerReflectionInfo* reflection = layer.reflectionInfo()) {
+ if (reflection->reflectionLayer()->hasCompositedLayerMapping())
+ reflection->reflectionLayer()->compositedLayerMapping()->updateCompositedBounds(ForceUpdate);
+ }
+
+ if (mapping->updateGraphicsLayerConfiguration(updateType))
+ m_needsRebuildTree = true;
+
+ mapping->updateGraphicsLayerGeometry(updateType, compositingContainer, layersNeedingPaintInvalidation);
+
+ updateType = mapping->updateTypeForChildren(updateType);
+ mapping->clearNeedsGraphicsLayerUpdate();
+
+ if (!layer.parent())
+ layer.compositor()->updateRootLayerPosition();
+
+ if (mapping->hasUnpositionedOverflowControlsLayers())
+ layer.scrollableArea()->positionOverflowControls(IntSize());
+ }
+
+ UpdateContext childContext(context, layer);
+ for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling())
+ update(layersNeedingPaintInvalidation, *child, updateType, childContext);
+}
+
+#if ASSERT_ENABLED
+
+void GraphicsLayerUpdater::assertNeedsToUpdateGraphicsLayerBitsCleared(RenderLayer& layer)
+{
+ if (layer.hasCompositedLayerMapping())
+ layer.compositedLayerMapping()->assertNeedsToUpdateGraphicsLayerBitsCleared();
+
+ for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling())
+ assertNeedsToUpdateGraphicsLayerBitsCleared(*child);
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.h
new file mode 100644
index 00000000000..df992fa91a1
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/GraphicsLayerUpdater.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 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 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 GraphicsLayerUpdater_h
+#define GraphicsLayerUpdater_h
+
+#include "platform/graphics/GraphicsLayer.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+class GraphicsLayerUpdater {
+ class UpdateContext {
+ public:
+ UpdateContext()
+ : m_compositingStackingContext(0)
+ , m_compositingAncestor(0)
+ {
+ }
+
+ UpdateContext(const UpdateContext&, const RenderLayer&);
+
+ const RenderLayer* compositingContainer(const RenderLayer&) const;
+ private:
+ const RenderLayer* m_compositingStackingContext;
+ const RenderLayer* m_compositingAncestor;
+ };
+
+public:
+ GraphicsLayerUpdater();
+ ~GraphicsLayerUpdater();
+
+ enum UpdateType {
+ DoNotForceUpdate,
+ ForceUpdate,
+ };
+
+ void update(Vector<RenderLayer*>& layersNeedingPaintInvalidation, RenderLayer&, UpdateType = DoNotForceUpdate, const UpdateContext& = UpdateContext());
+ void rebuildTree(RenderLayer&, GraphicsLayerVector& childLayersOfEnclosingLayer);
+
+ bool needsRebuildTree() const { return m_needsRebuildTree; }
+
+#if ASSERT_ENABLED
+ static void assertNeedsToUpdateGraphicsLayerBitsCleared(RenderLayer&);
+#endif
+
+private:
+ bool m_needsRebuildTree;
+};
+
+} // namespace WebCore
+
+#endif // GraphicsLayerUpdater_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.cpp b/chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.cpp
new file mode 100644
index 00000000000..5d35300f2a7
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.cpp
@@ -0,0 +1,1259 @@
+/*
+ * Copyright (C) 2009, 2010 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 "core/rendering/compositing/RenderLayerCompositor.h"
+
+#include "core/animation/DocumentAnimations.h"
+#include "core/dom/FullscreenElementStack.h"
+#include "core/dom/ScriptForbiddenScope.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/Settings.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorNodeIds.h"
+#include "core/page/Chrome.h"
+#include "core/page/Page.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/rendering/RenderLayerStackingNode.h"
+#include "core/rendering/RenderLayerStackingNodeIterator.h"
+#include "core/rendering/RenderVideo.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/CompositedLayerMapping.h"
+#include "core/rendering/compositing/CompositingInputsUpdater.h"
+#include "core/rendering/compositing/CompositingLayerAssigner.h"
+#include "core/rendering/compositing/CompositingRequirementsUpdater.h"
+#include "core/rendering/compositing/GraphicsLayerTreeBuilder.h"
+#include "core/rendering/compositing/GraphicsLayerUpdater.h"
+#include "platform/OverscrollTheme.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/TraceEvent.h"
+#include "platform/graphics/GraphicsLayer.h"
+#include "public/platform/Platform.h"
+
+namespace WebCore {
+
+RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView)
+ : m_renderView(renderView)
+ , m_compositingReasonFinder(renderView)
+ , m_pendingUpdateType(CompositingUpdateNone)
+ , m_hasAcceleratedCompositing(true)
+ , m_compositing(false)
+ , m_rootShouldAlwaysCompositeDirty(true)
+ , m_needsUpdateFixedBackground(false)
+ , m_isTrackingRepaints(false)
+ , m_rootLayerAttachment(RootLayerUnattached)
+ , m_inOverlayFullscreenVideo(false)
+{
+ updateAcceleratedCompositingSettings();
+}
+
+RenderLayerCompositor::~RenderLayerCompositor()
+{
+ ASSERT(m_rootLayerAttachment == RootLayerUnattached);
+}
+
+bool RenderLayerCompositor::inCompositingMode() const
+{
+ // FIXME: This should assert that lificycle is >= CompositingClean since
+ // the last step of updateIfNeeded can set this bit to false.
+ ASSERT(!m_rootShouldAlwaysCompositeDirty);
+ return m_compositing;
+}
+
+bool RenderLayerCompositor::staleInCompositingMode() const
+{
+ return m_compositing;
+}
+
+void RenderLayerCompositor::setCompositingModeEnabled(bool enable)
+{
+ if (enable == m_compositing)
+ return;
+
+ m_compositing = enable;
+
+ // RenderPart::requiresAcceleratedCompositing is used to determine self-paintingness
+ // and bases it's return value for frames on the m_compositing bit here.
+ if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) {
+ if (RenderPart* renderer = ownerElement->renderPart())
+ renderer->layer()->updateSelfPaintingLayer();
+ }
+
+ if (m_compositing)
+ ensureRootLayer();
+ else
+ destroyRootLayer();
+
+ // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so
+ // we need to schedule a style recalc in our parent document.
+ if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement())
+ ownerElement->setNeedsCompositingUpdate();
+}
+
+void RenderLayerCompositor::enableCompositingModeIfNeeded()
+{
+ if (!m_rootShouldAlwaysCompositeDirty)
+ return;
+
+ m_rootShouldAlwaysCompositeDirty = false;
+ if (m_compositing)
+ return;
+
+ if (rootShouldAlwaysComposite()) {
+ // FIXME: Is this needed? It was added in https://bugs.webkit.org/show_bug.cgi?id=26651.
+ // No tests fail if it's deleted.
+ setNeedsCompositingUpdate(CompositingUpdateRebuildTree);
+ setCompositingModeEnabled(true);
+ }
+}
+
+bool RenderLayerCompositor::rootShouldAlwaysComposite() const
+{
+ if (!m_hasAcceleratedCompositing)
+ return false;
+ return m_renderView.frame()->isMainFrame() || m_compositingReasonFinder.requiresCompositingForScrollableFrame();
+}
+
+void RenderLayerCompositor::updateAcceleratedCompositingSettings()
+{
+ m_compositingReasonFinder.updateTriggers();
+ m_hasAcceleratedCompositing = m_renderView.document().settings()->acceleratedCompositingEnabled();
+ m_rootShouldAlwaysCompositeDirty = true;
+}
+
+bool RenderLayerCompositor::layerSquashingEnabled() const
+{
+ if (!RuntimeEnabledFeatures::layerSquashingEnabled())
+ return false;
+ if (Settings* settings = m_renderView.document().settings())
+ return settings->layerSquashingEnabled();
+ return true;
+}
+
+bool RenderLayerCompositor::acceleratedCompositingForOverflowScrollEnabled() const
+{
+ return m_compositingReasonFinder.hasOverflowScrollTrigger();
+}
+
+static RenderVideo* findFullscreenVideoRenderer(Document& document)
+{
+ Element* fullscreenElement = FullscreenElementStack::fullscreenElementFrom(document);
+ while (fullscreenElement && fullscreenElement->isFrameOwnerElement()) {
+ Document* contentDocument = toHTMLFrameOwnerElement(fullscreenElement)->contentDocument();
+ if (!contentDocument)
+ return 0;
+ fullscreenElement = FullscreenElementStack::fullscreenElementFrom(*contentDocument);
+ }
+ if (!isHTMLVideoElement(fullscreenElement))
+ return 0;
+ RenderObject* renderer = fullscreenElement->renderer();
+ if (!renderer)
+ return 0;
+ return toRenderVideo(renderer);
+}
+
+void RenderLayerCompositor::updateIfNeededRecursive()
+{
+ for (Frame* child = m_renderView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (child->isLocalFrame())
+ toLocalFrame(child)->contentRenderer()->compositor()->updateIfNeededRecursive();
+ }
+
+ TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateIfNeededRecursive");
+
+ ASSERT(!m_renderView.needsLayout());
+
+ ScriptForbiddenScope forbidScript;
+
+ // FIXME: enableCompositingModeIfNeeded can trigger a CompositingUpdateRebuildTree,
+ // which asserts that it's not InCompositingUpdate.
+ enableCompositingModeIfNeeded();
+
+ lifecycle().advanceTo(DocumentLifecycle::InCompositingUpdate);
+ updateIfNeeded();
+ lifecycle().advanceTo(DocumentLifecycle::CompositingClean);
+
+ DocumentAnimations::startPendingAnimations(m_renderView.document());
+ // TODO: Figure out why this fails on Chrome OS login page. crbug.com/365507
+ // ASSERT(lifecycle().state() == DocumentLifecycle::CompositingClean);
+
+#if ASSERT_ENABLED
+ assertNoUnresolvedDirtyBits();
+ for (Frame* child = m_renderView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (child->isLocalFrame())
+ toLocalFrame(child)->contentRenderer()->compositor()->assertNoUnresolvedDirtyBits();
+ }
+#endif
+}
+
+void RenderLayerCompositor::setNeedsCompositingUpdate(CompositingUpdateType updateType)
+{
+ ASSERT(updateType != CompositingUpdateNone);
+
+ // FIXME: This function should only set dirty bits. We shouldn't
+ // enable compositing mode here.
+ // We check needsLayout here because we don't know if we need to enable
+ // compositing mode until layout is up-to-date because we need to know
+ // if this frame scrolls.
+ //
+ // NOTE: CastStreamingApiTestWithPixelOutput.RtpStreamError triggers
+ // an ASSERT when this code is removed.
+ if (!m_renderView.needsLayout())
+ enableCompositingModeIfNeeded();
+
+ m_pendingUpdateType = std::max(m_pendingUpdateType, updateType);
+ page()->animator().scheduleVisualUpdate();
+ lifecycle().ensureStateAtMost(DocumentLifecycle::LayoutClean);
+}
+
+void RenderLayerCompositor::didLayout()
+{
+ // FIXME: Technically we only need to do this when the FrameView's
+ // isScrollable method would return a different value.
+ m_rootShouldAlwaysCompositeDirty = true;
+ enableCompositingModeIfNeeded();
+
+ // FIXME: Rather than marking the entire RenderView as dirty, we should
+ // track which RenderLayers moved during layout and only dirty those
+ // specific RenderLayers.
+ rootRenderLayer()->setNeedsCompositingInputsUpdate();
+ setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
+}
+
+#if ASSERT_ENABLED
+
+void RenderLayerCompositor::assertNoUnresolvedDirtyBits()
+{
+ ASSERT(m_pendingUpdateType == CompositingUpdateNone);
+ ASSERT(!m_rootShouldAlwaysCompositeDirty);
+}
+
+#endif
+
+void RenderLayerCompositor::applyOverlayFullscreenVideoAdjustment()
+{
+ m_inOverlayFullscreenVideo = false;
+ if (!m_rootContentLayer)
+ return;
+
+ bool isMainFrame = m_renderView.frame()->isMainFrame();
+ RenderVideo* video = findFullscreenVideoRenderer(m_renderView.document());
+ if (!video || !video->hasCompositedLayerMapping()) {
+ if (isMainFrame) {
+ GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer();
+ if (backgroundLayer && !backgroundLayer->parent())
+ rootFixedBackgroundsChanged();
+ }
+ return;
+ }
+
+ GraphicsLayer* videoLayer = video->compositedLayerMapping()->mainGraphicsLayer();
+
+ // The fullscreen video has layer position equal to its enclosing frame's scroll position because fullscreen container is fixed-positioned.
+ // We should reset layer position here since we are going to reattach the layer at the very top level.
+ videoLayer->setPosition(IntPoint());
+
+ // Only steal fullscreen video layer and clear all other layers if we are the main frame.
+ if (!isMainFrame)
+ return;
+
+ m_rootContentLayer->removeAllChildren();
+ m_overflowControlsHostLayer->addChild(videoLayer);
+ if (GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer())
+ backgroundLayer->removeFromParent();
+ m_inOverlayFullscreenVideo = true;
+}
+
+void RenderLayerCompositor::updateIfNeeded()
+{
+ CompositingUpdateType updateType = m_pendingUpdateType;
+ m_pendingUpdateType = CompositingUpdateNone;
+
+ if (!hasAcceleratedCompositing() || updateType == CompositingUpdateNone)
+ return;
+
+ RenderLayer* updateRoot = rootRenderLayer();
+
+ Vector<RenderLayer*> layersNeedingRepaint;
+
+ if (updateType >= CompositingUpdateAfterCompositingInputChange) {
+ bool layersChanged = false;
+ {
+ TRACE_EVENT0("blink_rendering", "CompositingInputsUpdater::update");
+ CompositingInputsUpdater(updateRoot).update(updateRoot);
+#if ASSERT_ENABLED
+ CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(updateRoot);
+#endif
+ }
+
+ CompositingRequirementsUpdater(m_renderView, m_compositingReasonFinder).update(updateRoot);
+
+ {
+ TRACE_EVENT0("blink_rendering", "CompositingLayerAssigner::assign");
+ CompositingLayerAssigner(this).assign(updateRoot, layersChanged, layersNeedingRepaint);
+ }
+
+ {
+ TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateAfterCompositingChange");
+ if (const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView.frameView()->scrollableAreas()) {
+ for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it)
+ (*it)->updateAfterCompositingChange();
+ }
+ }
+
+ if (layersChanged)
+ updateType = std::max(updateType, CompositingUpdateRebuildTree);
+ }
+
+ if (updateType != CompositingUpdateNone) {
+ TRACE_EVENT0("blink_rendering", "GraphicsLayerUpdater::updateRecursive");
+ GraphicsLayerUpdater updater;
+ updater.update(layersNeedingRepaint, *updateRoot);
+
+ if (updater.needsRebuildTree())
+ updateType = std::max(updateType, CompositingUpdateRebuildTree);
+
+#if ASSERT_ENABLED
+ // FIXME: Move this check to the end of the compositing update.
+ GraphicsLayerUpdater::assertNeedsToUpdateGraphicsLayerBitsCleared(*updateRoot);
+#endif
+ }
+
+ if (updateType >= CompositingUpdateRebuildTree) {
+ GraphicsLayerVector childList;
+ {
+ TRACE_EVENT0("blink_rendering", "GraphicsLayerTreeBuilder::rebuild");
+ GraphicsLayerTreeBuilder().rebuild(*updateRoot, childList);
+ }
+
+ if (childList.isEmpty())
+ destroyRootLayer();
+ else
+ m_rootContentLayer->setChildren(childList);
+
+ if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled())
+ applyOverlayFullscreenVideoAdjustment();
+ }
+
+ if (m_needsUpdateFixedBackground) {
+ rootFixedBackgroundsChanged();
+ m_needsUpdateFixedBackground = false;
+ }
+
+ for (unsigned i = 0; i < layersNeedingRepaint.size(); i++) {
+ RenderLayer* layer = layersNeedingRepaint[i];
+ layer->repainter().computeRepaintRectsIncludingNonCompositingDescendants();
+
+ repaintOnCompositingChange(layer);
+ }
+
+ // Inform the inspector that the layer tree has changed.
+ if (m_renderView.frame()->isMainFrame())
+ InspectorInstrumentation::layerTreeDidChange(m_renderView.frame());
+}
+
+bool RenderLayerCompositor::allocateOrClearCompositedLayerMapping(RenderLayer* layer, const CompositingStateTransitionType compositedLayerUpdate)
+{
+ bool compositedLayerMappingChanged = false;
+ bool nonCompositedReasonChanged = updateLayerIfViewportConstrained(layer);
+
+ // FIXME: It would be nice to directly use the layer's compositing reason,
+ // but allocateOrClearCompositedLayerMapping also gets called without having updated compositing
+ // requirements fully.
+ switch (compositedLayerUpdate) {
+ case AllocateOwnCompositedLayerMapping:
+ ASSERT(!layer->hasCompositedLayerMapping());
+ setCompositingModeEnabled(true);
+
+ // If this layer was previously squashed, we need to remove its reference to a groupedMapping right away, so
+ // that computing repaint rects will know the layer's correct compositingState.
+ // FIXME: do we need to also remove the layer from it's location in the squashing list of its groupedMapping?
+ // Need to create a test where a squashed layer pops into compositing. And also to cover all other
+ // sorts of compositingState transitions.
+ layer->setLostGroupedMapping(false);
+ layer->setGroupedMapping(0);
+
+ // If we need to repaint, do so before allocating the compositedLayerMapping
+ repaintOnCompositingChange(layer);
+ layer->ensureCompositedLayerMapping();
+ compositedLayerMappingChanged = true;
+
+ // At this time, the ScrollingCooridnator only supports the top-level frame.
+ if (layer->isRootLayer() && m_renderView.frame()->isMainFrame()) {
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
+ }
+ break;
+ case RemoveOwnCompositedLayerMapping:
+ // PutInSquashingLayer means you might have to remove the composited layer mapping first.
+ case PutInSquashingLayer:
+ if (layer->hasCompositedLayerMapping()) {
+ // If we're removing the compositedLayerMapping from a reflection, clear the source GraphicsLayer's pointer to
+ // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection
+ // are both either composited, or not composited.
+ if (layer->isReflection()) {
+ RenderLayer* sourceLayer = toRenderLayerModelObject(layer->renderer()->parent())->layer();
+ if (sourceLayer->hasCompositedLayerMapping()) {
+ ASSERT(sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->replicaLayer() == layer->compositedLayerMapping()->mainGraphicsLayer());
+ sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->setReplicatedByLayer(0);
+ }
+ }
+
+ layer->clearCompositedLayerMapping();
+ compositedLayerMappingChanged = true;
+ }
+
+ break;
+ case RemoveFromSquashingLayer:
+ case NoCompositingStateChange:
+ // Do nothing.
+ break;
+ }
+
+ if (layer->hasCompositedLayerMapping() && layer->compositedLayerMapping()->updateRequiresOwnBackingStoreForIntrinsicReasons())
+ compositedLayerMappingChanged = true;
+
+ if (compositedLayerMappingChanged && layer->renderer()->isRenderPart()) {
+ RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer()));
+ if (innerCompositor && innerCompositor->staleInCompositingMode())
+ innerCompositor->updateRootLayerAttachment();
+ }
+
+ if (compositedLayerMappingChanged)
+ layer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
+
+ // If a fixed position layer gained/lost a compositedLayerMapping or the reason not compositing it changed,
+ // the scrolling coordinator needs to recalculate whether it can do fast scrolling.
+ if (compositedLayerMappingChanged || nonCompositedReasonChanged) {
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView.frameView());
+ }
+
+ return compositedLayerMappingChanged || nonCompositedReasonChanged;
+}
+
+bool RenderLayerCompositor::updateLayerIfViewportConstrained(RenderLayer* layer)
+{
+ RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason;
+ m_compositingReasonFinder.requiresCompositingForPositionFixed(layer->renderer(), layer, &viewportConstrainedNotCompositedReason);
+
+ if (layer->viewportConstrainedNotCompositedReason() != viewportConstrainedNotCompositedReason) {
+ ASSERT(viewportConstrainedNotCompositedReason == RenderLayer::NoNotCompositedReason || layer->renderer()->style()->position() == FixedPosition);
+ layer->setViewportConstrainedNotCompositedReason(viewportConstrainedNotCompositedReason);
+ return true;
+ }
+ return false;
+}
+
+// These are temporary hacks to work around chicken-egg issues while we continue to refactor the compositing code.
+// See crbug.com/383191 for a list of tests that fail if this method is removed.
+void RenderLayerCompositor::applyUpdateLayerCompositingStateChickenEggHacks(RenderLayer* layer, CompositingStateTransitionType compositedLayerUpdate)
+{
+ if (compositedLayerUpdate != NoCompositingStateChange) {
+ bool compositedLayerMappingChanged = allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate);
+ if (compositedLayerMappingChanged) {
+ // Repaint rects can only be computed for layers that have already been attached to the
+ // render tree, but a chicken-egg compositing update can happen before |layer| gets
+ // attached. Since newly-created renderers don't get parented until they are attached
+ // (see RenderTreeBuilder::createRendererForElementIfNeeded), we can check for attachment
+ // by checking for a parent.
+ if (layer->parent())
+ layer->repainter().computeRepaintRectsIncludingNonCompositingDescendants();
+ repaintOnCompositingChange(layer);
+ }
+ }
+}
+
+void RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, UpdateLayerCompositingStateOptions options)
+{
+ layer->setCompositingReasons(layer->styleDeterminedCompositingReasons(), CompositingReasonComboAllStyleDeterminedReasons);
+ CompositingStateTransitionType compositedLayerUpdate = CompositingLayerAssigner(this).computeCompositedLayerUpdate(layer);
+
+ if (compositedLayerUpdate != NoCompositingStateChange)
+ setNeedsCompositingUpdate(CompositingUpdateRebuildTree);
+
+ if (options == UseChickenEggHacks)
+ applyUpdateLayerCompositingStateChickenEggHacks(layer, compositedLayerUpdate);
+}
+
+void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
+{
+ // If the renderer is not attached yet, no need to repaint.
+ if (layer->renderer() != &m_renderView && !layer->renderer()->parent())
+ return;
+
+ layer->repainter().repaintIncludingNonCompositingDescendants();
+}
+
+// This method assumes that layout is up-to-date, unlike repaintOnCompositingChange().
+void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer* layer, const LayoutRect& rect)
+{
+ RenderLayer* compositedAncestor = layer->enclosingCompositingLayerForRepaint(ExcludeSelf);
+ if (!compositedAncestor)
+ return;
+ ASSERT(compositedAncestor->compositingState() == PaintsIntoOwnBacking || compositedAncestor->compositingState() == PaintsIntoGroupedBacking);
+
+ LayoutPoint offset;
+ layer->convertToLayerCoords(compositedAncestor, offset);
+ LayoutRect repaintRect = rect;
+ repaintRect.moveBy(offset);
+ compositedAncestor->repainter().setBackingNeedsRepaintInRect(repaintRect);
+}
+
+void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
+{
+ if (m_overflowControlsHostLayer)
+ m_overflowControlsHostLayer->setPosition(contentsOffset);
+}
+
+void RenderLayerCompositor::frameViewDidChangeSize()
+{
+ if (m_containerLayer) {
+ FrameView* frameView = m_renderView.frameView();
+ m_containerLayer->setSize(frameView->unscaledVisibleContentSize());
+
+ frameViewDidScroll();
+ updateOverflowControlsLayers();
+ }
+}
+
+enum AcceleratedFixedRootBackgroundHistogramBuckets {
+ ScrolledMainFrameBucket = 0,
+ ScrolledMainFrameWithAcceleratedFixedRootBackground = 1,
+ ScrolledMainFrameWithUnacceleratedFixedRootBackground = 2,
+ AcceleratedFixedRootBackgroundHistogramMax = 3
+};
+
+void RenderLayerCompositor::frameViewDidScroll()
+{
+ FrameView* frameView = m_renderView.frameView();
+ IntPoint scrollPosition = frameView->scrollPosition();
+
+ if (!m_scrollLayer)
+ return;
+
+ bool scrollingCoordinatorHandlesOffset = false;
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+ if (Settings* settings = m_renderView.document().settings()) {
+ if (m_renderView.frame()->isMainFrame() || settings->compositedScrollingForFramesEnabled())
+ scrollingCoordinatorHandlesOffset = scrollingCoordinator->scrollableAreaScrollLayerDidChange(frameView);
+ }
+ }
+
+ // Scroll position = scroll minimum + scroll offset. Adjust the layer's
+ // position to handle whatever the scroll coordinator isn't handling.
+ // The minimum scroll position is non-zero for RTL pages with overflow.
+ if (scrollingCoordinatorHandlesOffset)
+ m_scrollLayer->setPosition(-frameView->minimumScrollPosition());
+ else
+ m_scrollLayer->setPosition(-scrollPosition);
+
+
+ blink::Platform::current()->histogramEnumeration("Renderer.AcceleratedFixedRootBackground",
+ ScrolledMainFrameBucket,
+ AcceleratedFixedRootBackgroundHistogramMax);
+}
+
+void RenderLayerCompositor::frameViewScrollbarsExistenceDidChange()
+{
+ if (m_containerLayer)
+ updateOverflowControlsLayers();
+}
+
+void RenderLayerCompositor::rootFixedBackgroundsChanged()
+{
+ if (!supportsFixedRootBackgroundCompositing())
+ return;
+
+ // To avoid having to make the fixed root background layer fixed positioned to
+ // stay put, we position it in the layer tree as follows:
+ //
+ // + Overflow controls host
+ // + LocalFrame clip
+ // + (Fixed root background) <-- Here.
+ // + LocalFrame scroll
+ // + Root content layer
+ // + Scrollbars
+ //
+ // That is, it needs to be the first child of the frame clip, the sibling of
+ // the frame scroll layer. The compositor does not own the background layer, it
+ // just positions it (like the foreground layer).
+ if (GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer())
+ m_containerLayer->addChildBelow(backgroundLayer, m_scrollLayer.get());
+}
+
+bool RenderLayerCompositor::scrollingLayerDidChange(RenderLayer* layer)
+{
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ return scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer->scrollableArea());
+ return false;
+}
+
+String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
+{
+ ASSERT(lifecycle().state() >= DocumentLifecycle::CompositingClean);
+
+ if (!m_rootContentLayer)
+ return String();
+
+ // We skip dumping the scroll and clip layers to keep layerTreeAsText output
+ // similar between platforms (unless we explicitly request dumping from the
+ // root.
+ GraphicsLayer* rootLayer = m_rootContentLayer.get();
+ if (flags & LayerTreeIncludesRootLayer)
+ rootLayer = rootGraphicsLayer();
+
+ String layerTreeText = rootLayer->layerTreeAsText(flags);
+
+ // The true root layer is not included in the dump, so if we want to report
+ // its repaint rects, they must be included here.
+ if (flags & LayerTreeIncludesRepaintRects)
+ return m_renderView.frameView()->trackedPaintInvalidationRectsAsText() + layerTreeText;
+
+ return layerTreeText;
+}
+
+RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer)
+{
+ if (!renderer->node()->isFrameOwnerElement())
+ return 0;
+
+ HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(renderer->node());
+ if (Document* contentDocument = element->contentDocument()) {
+ if (RenderView* view = contentDocument->renderView())
+ return view->compositor();
+ }
+ return 0;
+}
+
+// FIXME: What does this function do? It needs a clearer name.
+bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
+{
+ RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer);
+ if (!innerCompositor || !innerCompositor->staleInCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
+ return false;
+
+ RenderLayer* layer = renderer->layer();
+ if (!layer->hasCompositedLayerMapping())
+ return false;
+
+ CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping();
+ GraphicsLayer* hostingLayer = compositedLayerMapping->parentForSublayers();
+ GraphicsLayer* rootLayer = innerCompositor->rootGraphicsLayer();
+ if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) {
+ hostingLayer->removeAllChildren();
+ hostingLayer->addChild(rootLayer);
+ }
+ return true;
+}
+
+void RenderLayerCompositor::repaintCompositedLayers()
+{
+ recursiveRepaintLayer(rootRenderLayer());
+}
+
+void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer* layer)
+{
+ // FIXME: This method does not work correctly with transforms.
+ if (layer->compositingState() == PaintsIntoOwnBacking) {
+ layer->compositedLayerMapping()->setContentsNeedDisplay();
+ // This function is called only when it is desired to repaint the entire compositing graphics layer tree.
+ // This includes squashing.
+ layer->compositedLayerMapping()->setSquashingContentsNeedDisplay();
+ }
+
+ layer->stackingNode()->updateLayerListsIfNeeded();
+
+#if ASSERT_ENABLED
+ LayerListMutationDetector mutationChecker(layer->stackingNode());
+#endif
+
+ unsigned childrenToVisit = NormalFlowChildren;
+ if (layer->hasCompositingDescendant())
+ childrenToVisit |= PositiveZOrderChildren | NegativeZOrderChildren;
+ RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), childrenToVisit);
+ while (RenderLayerStackingNode* curNode = iterator.next())
+ recursiveRepaintLayer(curNode->layer());
+}
+
+RenderLayer* RenderLayerCompositor::rootRenderLayer() const
+{
+ return m_renderView.layer();
+}
+
+GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const
+{
+ if (m_overflowControlsHostLayer)
+ return m_overflowControlsHostLayer.get();
+ return m_rootContentLayer.get();
+}
+
+GraphicsLayer* RenderLayerCompositor::scrollLayer() const
+{
+ return m_scrollLayer.get();
+}
+
+GraphicsLayer* RenderLayerCompositor::containerLayer() const
+{
+ return m_containerLayer.get();
+}
+
+GraphicsLayer* RenderLayerCompositor::ensureRootTransformLayer()
+{
+ ASSERT(rootGraphicsLayer());
+
+ if (!m_rootTransformLayer.get()) {
+ m_rootTransformLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_overflowControlsHostLayer->addChild(m_rootTransformLayer.get());
+ m_rootTransformLayer->addChild(m_containerLayer.get());
+ updateOverflowControlsLayers();
+ }
+
+ return m_rootTransformLayer.get();
+}
+
+void RenderLayerCompositor::setIsInWindow(bool isInWindow)
+{
+ if (!staleInCompositingMode())
+ return;
+
+ if (isInWindow) {
+ if (m_rootLayerAttachment != RootLayerUnattached)
+ return;
+
+ RootLayerAttachment attachment = m_renderView.frame()->isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
+ attachRootLayer(attachment);
+ } else {
+ if (m_rootLayerAttachment == RootLayerUnattached)
+ return;
+
+ detachRootLayer();
+ }
+}
+
+void RenderLayerCompositor::updateRootLayerPosition()
+{
+ if (m_rootContentLayer) {
+ const IntRect& documentRect = m_renderView.documentRect();
+ m_rootContentLayer->setSize(documentRect.size());
+ m_rootContentLayer->setPosition(documentRect.location());
+#if USE(RUBBER_BANDING)
+ if (m_layerForOverhangShadow)
+ OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get());
+#endif
+ }
+ if (m_containerLayer) {
+ FrameView* frameView = m_renderView.frameView();
+ m_containerLayer->setSize(frameView->unscaledVisibleContentSize());
+ }
+}
+
+void RenderLayerCompositor::updateStyleDeterminedCompositingReasons(RenderLayer* layer)
+{
+ CompositingReasons reasons = m_compositingReasonFinder.styleDeterminedReasons(layer->renderer());
+ layer->setStyleDeterminedCompositingReasons(reasons);
+}
+
+void RenderLayerCompositor::updateDirectCompositingReasons(RenderLayer* layer)
+{
+ CompositingReasons reasons = m_compositingReasonFinder.directReasons(layer);
+ layer->setCompositingReasons(reasons, CompositingReasonComboAllDirectReasons);
+}
+
+void RenderLayerCompositor::setOverlayLayer(GraphicsLayer* layer)
+{
+ ASSERT(rootGraphicsLayer());
+
+ if (layer->parent() != m_overflowControlsHostLayer.get())
+ m_overflowControlsHostLayer->addChild(layer);
+}
+
+bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
+{
+ // 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->subtreeIsInvisible() && layer->renderer()->flowThreadState() == RenderObject::NotInsideFlowThread;
+}
+
+// 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.
+// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
+// but a sibling in the z-order hierarchy.
+bool RenderLayerCompositor::clippedByNonAncestorInStackingTree(const RenderLayer* layer) const
+{
+ if (!layer->hasCompositedLayerMapping() || !layer->parent())
+ return false;
+
+ const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
+ if (!compositingAncestor)
+ return false;
+
+ RenderObject* clippingContainer = layer->renderer()->clippingContainer();
+ if (!clippingContainer)
+ return false;
+
+ if (compositingAncestor->renderer()->isDescendantOf(clippingContainer))
+ return false;
+
+ return true;
+}
+
+// Return true if the given layer is a stacking context and has compositing child
+// layers that it needs to clip. In this case we insert a clipping GraphicsLayer
+// into the hierarchy between this layer and its children in the z-order hierarchy.
+bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
+{
+ return layer->hasCompositingDescendant() && layer->renderer()->hasClipOrOverflowClip();
+}
+
+// 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.
+bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
+{
+ return layer->stackingNode()->hasNegativeZOrderList();
+}
+
+static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
+{
+ if (!scrollbar)
+ return;
+
+ context.save();
+ const IntRect& scrollbarRect = scrollbar->frameRect();
+ context.translate(-scrollbarRect.x(), -scrollbarRect.y());
+ IntRect transformedClip = clip;
+ transformedClip.moveBy(scrollbarRect.location());
+ scrollbar->paint(&context, transformedClip);
+ context.restore();
+}
+
+void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
+{
+ if (graphicsLayer == layerForHorizontalScrollbar())
+ paintScrollbar(m_renderView.frameView()->horizontalScrollbar(), context, clip);
+ else if (graphicsLayer == layerForVerticalScrollbar())
+ paintScrollbar(m_renderView.frameView()->verticalScrollbar(), context, clip);
+ else if (graphicsLayer == layerForScrollCorner()) {
+ const IntRect& scrollCorner = m_renderView.frameView()->scrollCornerRect();
+ context.save();
+ context.translate(-scrollCorner.x(), -scrollCorner.y());
+ IntRect transformedClip = clip;
+ transformedClip.moveBy(scrollCorner.location());
+ m_renderView.frameView()->paintScrollCorner(&context, transformedClip);
+ context.restore();
+ }
+}
+
+bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
+{
+ if (Settings* settings = m_renderView.document().settings()) {
+ if (settings->acceleratedCompositingForFixedRootBackgroundEnabled())
+ return true;
+ }
+ return false;
+}
+
+bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer* layer) const
+{
+ if (layer != m_renderView.layer())
+ return false;
+
+ return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
+}
+
+GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
+{
+ // Get the fixed root background from the RenderView layer's compositedLayerMapping.
+ RenderLayer* viewLayer = m_renderView.layer();
+ if (!viewLayer)
+ return 0;
+
+ if (viewLayer->compositingState() == PaintsIntoOwnBacking && viewLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBackground())
+ return viewLayer->compositedLayerMapping()->backgroundLayer();
+
+ return 0;
+}
+
+static void resetTrackedRepaintRectsRecursive(GraphicsLayer* graphicsLayer)
+{
+ if (!graphicsLayer)
+ return;
+
+ graphicsLayer->resetTrackedRepaints();
+
+ for (size_t i = 0; i < graphicsLayer->children().size(); ++i)
+ resetTrackedRepaintRectsRecursive(graphicsLayer->children()[i]);
+
+ if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer())
+ resetTrackedRepaintRectsRecursive(replicaLayer);
+
+ if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer())
+ resetTrackedRepaintRectsRecursive(maskLayer);
+
+ if (GraphicsLayer* clippingMaskLayer = graphicsLayer->contentsClippingMaskLayer())
+ resetTrackedRepaintRectsRecursive(clippingMaskLayer);
+}
+
+void RenderLayerCompositor::resetTrackedRepaintRects()
+{
+ if (GraphicsLayer* rootLayer = rootGraphicsLayer())
+ resetTrackedRepaintRectsRecursive(rootLayer);
+}
+
+void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints)
+{
+ ASSERT(lifecycle().state() == DocumentLifecycle::CompositingClean);
+ m_isTrackingRepaints = tracksRepaints;
+}
+
+bool RenderLayerCompositor::isTrackingRepaints() const
+{
+ return m_isTrackingRepaints;
+}
+
+static bool shouldCompositeOverflowControls(FrameView* view)
+{
+ if (Page* page = view->frame().page()) {
+ if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+ if (scrollingCoordinator->coordinatesScrollingForFrameView(view))
+ return true;
+ }
+
+ return true;
+}
+
+bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
+{
+ FrameView* view = m_renderView.frameView();
+ return shouldCompositeOverflowControls(view) && view->horizontalScrollbar();
+}
+
+bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
+{
+ FrameView* view = m_renderView.frameView();
+ return shouldCompositeOverflowControls(view) && view->verticalScrollbar();
+}
+
+bool RenderLayerCompositor::requiresScrollCornerLayer() const
+{
+ FrameView* view = m_renderView.frameView();
+ return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible();
+}
+
+void RenderLayerCompositor::updateOverflowControlsLayers()
+{
+#if USE(RUBBER_BANDING)
+ if (m_renderView.frame()->isMainFrame()) {
+ if (!m_layerForOverhangShadow) {
+ m_layerForOverhangShadow = GraphicsLayer::create(graphicsLayerFactory(), this);
+ OverscrollTheme::theme()->setUpOverhangShadowLayer(m_layerForOverhangShadow.get());
+ OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get());
+ m_scrollLayer->addChild(m_layerForOverhangShadow.get());
+ }
+ } else {
+ ASSERT(!m_layerForOverhangShadow);
+ }
+#endif
+ GraphicsLayer* controlsParent = m_rootTransformLayer.get() ? m_rootTransformLayer.get() : m_overflowControlsHostLayer.get();
+
+ if (requiresHorizontalScrollbarLayer()) {
+ if (!m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+ }
+
+ if (m_layerForHorizontalScrollbar->parent() != controlsParent) {
+ controlsParent->addChild(m_layerForHorizontalScrollbar.get());
+
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
+ }
+ } else if (m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar->removeFromParent();
+ m_layerForHorizontalScrollbar = nullptr;
+
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
+ }
+
+ if (requiresVerticalScrollbarLayer()) {
+ if (!m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+ }
+
+ if (m_layerForVerticalScrollbar->parent() != controlsParent) {
+ controlsParent->addChild(m_layerForVerticalScrollbar.get());
+
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
+ }
+ } else if (m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar->removeFromParent();
+ m_layerForVerticalScrollbar = nullptr;
+
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
+ }
+
+ if (requiresScrollCornerLayer()) {
+ if (!m_layerForScrollCorner) {
+ m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this);
+ controlsParent->addChild(m_layerForScrollCorner.get());
+ }
+ } else if (m_layerForScrollCorner) {
+ m_layerForScrollCorner->removeFromParent();
+ m_layerForScrollCorner = nullptr;
+ }
+
+ m_renderView.frameView()->positionScrollbarLayers();
+}
+
+void RenderLayerCompositor::ensureRootLayer()
+{
+ RootLayerAttachment expectedAttachment = m_renderView.frame()->isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
+ if (expectedAttachment == m_rootLayerAttachment)
+ return;
+
+ if (!m_rootContentLayer) {
+ m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+ IntRect overflowRect = m_renderView.pixelSnappedLayoutOverflowRect();
+ m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
+ m_rootContentLayer->setPosition(FloatPoint());
+ m_rootContentLayer->setOwnerNodeId(InspectorNodeIds::idForNode(m_renderView.generatingNode()));
+
+ // Need to clip to prevent transformed content showing outside this frame
+ m_rootContentLayer->setMasksToBounds(true);
+ }
+
+ if (!m_overflowControlsHostLayer) {
+ ASSERT(!m_scrollLayer);
+ ASSERT(!m_containerLayer);
+
+ // Create a layer to host the clipping layer and the overflow controls layers.
+ m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+
+ // Create a clipping layer if this is an iframe or settings require to clip.
+ m_containerLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+ bool containerMasksToBounds = !m_renderView.frame()->isMainFrame();
+ if (Settings* settings = m_renderView.document().settings()) {
+ if (settings->mainFrameClipsContent())
+ containerMasksToBounds = true;
+ }
+ m_containerLayer->setMasksToBounds(containerMasksToBounds);
+
+ m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true);
+
+ // Hook them up
+ m_overflowControlsHostLayer->addChild(m_containerLayer.get());
+ m_containerLayer->addChild(m_scrollLayer.get());
+ m_scrollLayer->addChild(m_rootContentLayer.get());
+
+ frameViewDidChangeSize();
+ }
+
+ // Check to see if we have to change the attachment
+ if (m_rootLayerAttachment != RootLayerUnattached)
+ detachRootLayer();
+
+ attachRootLayer(expectedAttachment);
+}
+
+void RenderLayerCompositor::destroyRootLayer()
+{
+ if (!m_rootContentLayer)
+ return;
+
+ detachRootLayer();
+
+#if USE(RUBBER_BANDING)
+ if (m_layerForOverhangShadow) {
+ m_layerForOverhangShadow->removeFromParent();
+ m_layerForOverhangShadow = nullptr;
+ }
+#endif
+
+ if (m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar->removeFromParent();
+ m_layerForHorizontalScrollbar = nullptr;
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
+ if (Scrollbar* horizontalScrollbar = m_renderView.frameView()->verticalScrollbar())
+ m_renderView.frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
+ }
+
+ if (m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar->removeFromParent();
+ m_layerForVerticalScrollbar = nullptr;
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
+ if (Scrollbar* verticalScrollbar = m_renderView.frameView()->verticalScrollbar())
+ m_renderView.frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
+ }
+
+ if (m_layerForScrollCorner) {
+ m_layerForScrollCorner = nullptr;
+ m_renderView.frameView()->invalidateScrollCorner(m_renderView.frameView()->scrollCornerRect());
+ }
+
+ if (m_overflowControlsHostLayer) {
+ m_overflowControlsHostLayer = nullptr;
+ m_containerLayer = nullptr;
+ m_scrollLayer = nullptr;
+ }
+ ASSERT(!m_scrollLayer);
+ m_rootContentLayer = nullptr;
+ m_rootTransformLayer = nullptr;
+}
+
+void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment)
+{
+ if (!m_rootContentLayer)
+ return;
+
+ switch (attachment) {
+ case RootLayerUnattached:
+ ASSERT_NOT_REACHED();
+ break;
+ case RootLayerAttachedViaChromeClient: {
+ LocalFrame& frame = m_renderView.frameView()->frame();
+ Page* page = frame.page();
+ if (!page)
+ return;
+ page->chrome().client().attachRootGraphicsLayer(rootGraphicsLayer());
+ break;
+ }
+ case RootLayerAttachedViaEnclosingFrame: {
+ HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement();
+ ASSERT(ownerElement);
+ // The layer will get hooked up via CompositedLayerMapping::updateGraphicsLayerConfiguration()
+ // for the frame's renderer in the parent document.
+ ownerElement->setNeedsCompositingUpdate();
+ break;
+ }
+ }
+
+ m_rootLayerAttachment = attachment;
+}
+
+void RenderLayerCompositor::detachRootLayer()
+{
+ if (!m_rootContentLayer || m_rootLayerAttachment == RootLayerUnattached)
+ return;
+
+ switch (m_rootLayerAttachment) {
+ case RootLayerAttachedViaEnclosingFrame: {
+ // The layer will get unhooked up via CompositedLayerMapping::updateGraphicsLayerConfiguration()
+ // for the frame's renderer in the parent document.
+ if (m_overflowControlsHostLayer)
+ m_overflowControlsHostLayer->removeFromParent();
+ else
+ m_rootContentLayer->removeFromParent();
+
+ if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement())
+ ownerElement->setNeedsCompositingUpdate();
+ break;
+ }
+ case RootLayerAttachedViaChromeClient: {
+ LocalFrame& frame = m_renderView.frameView()->frame();
+ Page* page = frame.page();
+ if (!page)
+ return;
+ page->chrome().client().attachRootGraphicsLayer(0);
+ }
+ break;
+ case RootLayerUnattached:
+ break;
+ }
+
+ m_rootLayerAttachment = RootLayerUnattached;
+}
+
+void RenderLayerCompositor::updateRootLayerAttachment()
+{
+ ensureRootLayer();
+}
+
+ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const
+{
+ if (Page* page = this->page())
+ return page->scrollingCoordinator();
+
+ return 0;
+}
+
+GraphicsLayerFactory* RenderLayerCompositor::graphicsLayerFactory() const
+{
+ if (Page* page = this->page())
+ return page->chrome().client().graphicsLayerFactory();
+ return 0;
+}
+
+Page* RenderLayerCompositor::page() const
+{
+ return m_renderView.frameView()->frame().page();
+}
+
+DocumentLifecycle& RenderLayerCompositor::lifecycle() const
+{
+ return m_renderView.document().lifecycle();
+}
+
+String RenderLayerCompositor::debugName(const GraphicsLayer* graphicsLayer)
+{
+ String name;
+ if (graphicsLayer == m_rootContentLayer.get()) {
+ name = "Content Root Layer";
+ } else if (graphicsLayer == m_rootTransformLayer.get()) {
+ name = "Root Transform Layer";
+#if USE(RUBBER_BANDING)
+ } else if (graphicsLayer == m_layerForOverhangShadow.get()) {
+ name = "Overhang Areas Shadow";
+#endif
+ } else if (graphicsLayer == m_overflowControlsHostLayer.get()) {
+ name = "Overflow Controls Host Layer";
+ } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
+ name = "Horizontal Scrollbar Layer";
+ } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
+ name = "Vertical Scrollbar Layer";
+ } else if (graphicsLayer == m_layerForScrollCorner.get()) {
+ name = "Scroll Corner Layer";
+ } else if (graphicsLayer == m_containerLayer.get()) {
+ name = "LocalFrame Clipping Layer";
+ } else if (graphicsLayer == m_scrollLayer.get()) {
+ name = "LocalFrame Scrolling Layer";
+ } else {
+ ASSERT_NOT_REACHED();
+ }
+
+ return name;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.h b/chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.h
new file mode 100644
index 00000000000..4fc1a0456f9
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/compositing/RenderLayerCompositor.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2009 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 RenderLayerCompositor_h
+#define RenderLayerCompositor_h
+
+#include "core/page/ChromeClient.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/compositing/CompositingReasonFinder.h"
+#include "platform/graphics/GraphicsLayerClient.h"
+#include "wtf/HashMap.h"
+
+namespace WebCore {
+
+class GraphicsLayer;
+class RenderPart;
+class ScrollingCoordinator;
+
+enum CompositingUpdateType {
+ CompositingUpdateNone,
+ CompositingUpdateAfterGeometryChange,
+ CompositingUpdateAfterCompositingInputChange,
+ CompositingUpdateRebuildTree,
+};
+
+enum CompositingStateTransitionType {
+ NoCompositingStateChange,
+ AllocateOwnCompositedLayerMapping,
+ RemoveOwnCompositedLayerMapping,
+ PutInSquashingLayer,
+ RemoveFromSquashingLayer
+};
+
+// RenderLayerCompositor manages the hierarchy of
+// composited RenderLayers. It determines which RenderLayers
+// become compositing, and creates and maintains a hierarchy of
+// GraphicsLayers based on the RenderLayer painting order.
+//
+// There is one RenderLayerCompositor per RenderView.
+
+class RenderLayerCompositor FINAL : public GraphicsLayerClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit RenderLayerCompositor(RenderView&);
+ virtual ~RenderLayerCompositor();
+
+ void updateIfNeededRecursive();
+
+ // Return true if this RenderView is in "compositing mode" (i.e. has one or more
+ // composited RenderLayers)
+ bool inCompositingMode() const;
+ // FIXME: Replace all callers with inCompositingMdoe and remove this function.
+ bool staleInCompositingMode() const;
+ // This will make a compositing layer at the root automatically, and hook up to
+ // the native view/window system.
+ void setCompositingModeEnabled(bool);
+
+ // Returns true if the accelerated compositing is enabled
+ bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
+ bool layerSquashingEnabled() const;
+
+ bool acceleratedCompositingForOverflowScrollEnabled() const;
+
+ bool rootShouldAlwaysComposite() const;
+
+ // Copy the accelerated compositing related flags from Settings
+ void updateAcceleratedCompositingSettings();
+
+ // Used to indicate that a compositing update will be needed for the next frame that gets drawn.
+ void setNeedsCompositingUpdate(CompositingUpdateType);
+
+ void didLayout();
+
+ enum UpdateLayerCompositingStateOptions {
+ Normal,
+ UseChickenEggHacks, // Use this to trigger temporary chicken-egg hacks. See crbug.com/339892.
+ };
+
+ // Update the compositing dirty bits, based on the compositing-impacting properties of the layer.
+ void updateLayerCompositingState(RenderLayer*, UpdateLayerCompositingStateOptions = Normal);
+
+ // Returns whether this layer is clipped by another layer that is not an ancestor of the given layer in the stacking context hierarchy.
+ bool clippedByNonAncestorInStackingTree(const RenderLayer*) const;
+ // Whether layer's compositedLayerMapping needs a GraphicsLayer to clip z-order children of the given RenderLayer.
+ bool clipsCompositingDescendants(const RenderLayer*) const;
+
+ // Whether the given layer needs an extra 'contents' layer.
+ bool needsContentsCompositingLayer(const RenderLayer*) const;
+
+ bool supportsFixedRootBackgroundCompositing() const;
+ bool needsFixedRootBackgroundLayer(const RenderLayer*) const;
+ GraphicsLayer* fixedRootBackgroundLayer() const;
+ void setNeedsUpdateFixedBackground() { m_needsUpdateFixedBackground = true; }
+
+ // Repaint the appropriate layers when the given RenderLayer starts or stops being composited.
+ void repaintOnCompositingChange(RenderLayer*);
+
+ void repaintInCompositedAncestor(RenderLayer*, const LayoutRect&);
+ void repaintCompositedLayers();
+
+ RenderLayer* rootRenderLayer() const;
+ GraphicsLayer* rootGraphicsLayer() const;
+ GraphicsLayer* scrollLayer() const;
+ GraphicsLayer* containerLayer() const;
+
+ // We don't always have a root transform layer. This function lazily allocates one
+ // and returns it as required.
+ GraphicsLayer* ensureRootTransformLayer();
+
+ enum RootLayerAttachment {
+ RootLayerUnattached,
+ RootLayerAttachedViaChromeClient,
+ RootLayerAttachedViaEnclosingFrame
+ };
+
+ RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
+ void updateRootLayerAttachment();
+ void updateRootLayerPosition();
+
+ void setIsInWindow(bool);
+
+ static RenderLayerCompositor* frameContentsCompositor(RenderPart*);
+ // Return true if the layers changed.
+ static bool parentFrameContentLayers(RenderPart*);
+
+ // Update the geometry of the layers used for clipping and scrolling in frames.
+ void frameViewDidChangeLocation(const IntPoint& contentsOffset);
+ void frameViewDidChangeSize();
+ void frameViewDidScroll();
+ void frameViewScrollbarsExistenceDidChange();
+ void rootFixedBackgroundsChanged();
+
+ bool scrollingLayerDidChange(RenderLayer*);
+
+ String layerTreeAsText(LayerTreeFlags);
+
+ GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
+ GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
+ GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
+
+ void resetTrackedRepaintRects();
+ void setTracksRepaints(bool);
+
+ virtual String debugName(const GraphicsLayer*) OVERRIDE;
+
+ void updateStyleDeterminedCompositingReasons(RenderLayer*);
+
+ // Whether the layer could ever be composited.
+ bool canBeComposited(const RenderLayer*) const;
+
+ // FIXME: Move allocateOrClearCompositedLayerMapping to CompositingLayerAssigner once we've fixed
+ // the compositing chicken/egg issues.
+ bool allocateOrClearCompositedLayerMapping(RenderLayer*, CompositingStateTransitionType compositedLayerUpdate);
+
+ void updateDirectCompositingReasons(RenderLayer*);
+
+ void setOverlayLayer(GraphicsLayer*);
+
+ bool inOverlayFullscreenVideo() const { return m_inOverlayFullscreenVideo; }
+
+private:
+ class OverlapMap;
+
+#if ASSERT_ENABLED
+ void assertNoUnresolvedDirtyBits();
+#endif
+
+ // Make updates to the layer based on viewport-constrained properties such as position:fixed. This can in turn affect
+ // compositing.
+ bool updateLayerIfViewportConstrained(RenderLayer*);
+
+ // GraphicsLayerClient implementation
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double) OVERRIDE { }
+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&) OVERRIDE;
+
+ virtual bool isTrackingRepaints() const OVERRIDE;
+
+ // Whether the given RL needs to paint into its own separate backing (and hence would need its own CompositedLayerMapping).
+ bool needsOwnBacking(const RenderLayer*) const;
+
+ void updateIfNeeded();
+
+ void recursiveRepaintLayer(RenderLayer*);
+
+ void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer*, OverlapMap&, struct CompositingRecursionData&, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants, IntRect& absoluteDecendantBoundingBox);
+
+ bool hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const;
+
+ void ensureRootLayer();
+ void destroyRootLayer();
+
+ void attachRootLayer(RootLayerAttachment);
+ void detachRootLayer();
+
+ void updateOverflowControlsLayers();
+
+ Page* page() const;
+
+ GraphicsLayerFactory* graphicsLayerFactory() const;
+ ScrollingCoordinator* scrollingCoordinator() const;
+
+ void enableCompositingModeIfNeeded();
+
+ bool requiresHorizontalScrollbarLayer() const;
+ bool requiresVerticalScrollbarLayer() const;
+ bool requiresScrollCornerLayer() const;
+
+ void applyUpdateLayerCompositingStateChickenEggHacks(RenderLayer*, CompositingStateTransitionType compositedLayerUpdate);
+
+ DocumentLifecycle& lifecycle() const;
+
+ void applyOverlayFullscreenVideoAdjustment();
+
+ RenderView& m_renderView;
+ OwnPtr<GraphicsLayer> m_rootContentLayer;
+ OwnPtr<GraphicsLayer> m_rootTransformLayer;
+
+ CompositingReasonFinder m_compositingReasonFinder;
+
+ CompositingUpdateType m_pendingUpdateType;
+
+ bool m_hasAcceleratedCompositing;
+ bool m_compositing;
+
+ // The root layer doesn't composite if it's a non-scrollable frame.
+ // So, after a layout we set this dirty bit to know that we need
+ // to recompute whether the root layer should composite even if
+ // none of its descendants composite.
+ // FIXME: Get rid of all the callers of setCompositingModeEnabled
+ // except the one in updateIfNeeded, then rename this to
+ // m_compositingDirty.
+ bool m_rootShouldAlwaysCompositeDirty;
+ bool m_needsUpdateFixedBackground;
+ bool m_isTrackingRepaints; // Used for testing.
+
+ RootLayerAttachment m_rootLayerAttachment;
+
+ // Enclosing container layer, which clips for iframe content
+ OwnPtr<GraphicsLayer> m_containerLayer;
+ OwnPtr<GraphicsLayer> m_scrollLayer;
+
+ // Enclosing layer for overflow controls and the clipping layer
+ OwnPtr<GraphicsLayer> m_overflowControlsHostLayer;
+
+ // Layers for overflow controls
+ OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
+ OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
+ OwnPtr<GraphicsLayer> m_layerForScrollCorner;
+#if USE(RUBBER_BANDING)
+ OwnPtr<GraphicsLayer> m_layerForOverhangShadow;
+#endif
+
+ bool m_inOverlayFullscreenVideo;
+};
+
+} // namespace WebCore
+
+#endif // RenderLayerCompositor_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContext.cpp b/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContext.cpp
new file mode 100644
index 00000000000..513b2c3beaa
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContext.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Adobe Systems Incorporated.
+ *
+ * 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"
+#include "core/rendering/line/BreakingContextInlineHeaders.h"
+
+namespace WebCore {
+
+InlineIterator BreakingContext::handleEndOfLine()
+{
+ if (m_lineBreak == m_resolver.position() && (!m_lineBreak.object() || !m_lineBreak.object()->isBR())) {
+ // we just add as much as possible
+ if (m_blockStyle->whiteSpace() == PRE && !m_current.offset()) {
+ m_lineBreak.moveTo(m_lastObject, m_lastObject->isText() ? m_lastObject->length() : 0);
+ } else if (m_lineBreak.object()) {
+ // Don't ever break in the middle of a word if we can help it.
+ // There's no room at all. We just have to be on this line,
+ // even though we'll spill out.
+ m_lineBreak.moveTo(m_current.object(), m_current.offset());
+ }
+ }
+
+ // FIXME Bug 100049: We do not need to consume input in a multi-segment line
+ // unless no segment will.
+ if (m_lineBreak == m_resolver.position())
+ m_lineBreak.increment();
+
+ // Sanity check our midpoints.
+ m_lineMidpointState.checkMidpoints(m_lineBreak);
+
+ m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpointState, m_lineBreak, TrailingObjects::CollapseFirstSpace);
+
+ // We might have made lineBreak an iterator that points past the end
+ // of the object. Do this adjustment to make it point to the start
+ // of the next object instead to avoid confusing the rest of the
+ // code.
+ if (m_lineBreak.offset()) {
+ // This loop enforces the invariant that line breaks should never point
+ // at an empty inline. See http://crbug.com/305904.
+ do {
+ m_lineBreak.setOffset(m_lineBreak.offset() - 1);
+ m_lineBreak.increment();
+ } while (!m_lineBreak.atEnd() && isEmptyInline(m_lineBreak.object()));
+ }
+
+ return m_lineBreak;
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContextInlineHeaders.h b/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContextInlineHeaders.h
index 989d7e3cfd0..fba56c6fa7c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContextInlineHeaders.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/BreakingContextInlineHeaders.h
@@ -26,183 +26,25 @@
#include "core/rendering/InlineIterator.h"
#include "core/rendering/InlineTextBox.h"
-#include "core/rendering/LineWidth.h"
#include "core/rendering/RenderCombineText.h"
#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderRubyRun.h"
#include "core/rendering/break_lines.h"
+#include "core/rendering/line/LineBreaker.h"
#include "core/rendering/line/LineInfo.h"
-#include "core/rendering/shapes/ShapeInsideInfo.h"
+#include "core/rendering/line/LineWidth.h"
+#include "core/rendering/line/RenderTextInfo.h"
+#include "core/rendering/line/TrailingObjects.h"
+#include "core/rendering/line/WordMeasurement.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
namespace WebCore {
-using namespace std;
-using namespace WTF;
-using namespace Unicode;
-
// We don't let our line box tree for a single line get any deeper than this.
const unsigned cMaxLineDepth = 200;
-struct RenderTextInfo {
- // Destruction of m_layout requires TextLayout to be a complete type, so the constructor and destructor are made non-inline to avoid compilation errors.
- RenderTextInfo();
- ~RenderTextInfo();
-
- RenderText* m_text;
- OwnPtr<TextLayout> m_layout;
- LazyLineBreakIterator m_lineBreakIterator;
- const Font* m_font;
-
- void createLayout(RenderText* renderText, float xPos, bool collapseWhiteSpace)
- {
-#if OS(MACOSX)
- m_layout = m_font->createLayoutForMacComplexText(RenderBlockFlow::constructTextRun(renderText, *m_font, renderText, renderText->style()), renderText->textLength(), xPos, collapseWhiteSpace);
-#else
- m_layout = nullptr;
-#endif
- }
-};
-
-class WordMeasurement {
-public:
- WordMeasurement()
- : renderer(0)
- , width(0)
- , startOffset(0)
- , endOffset(0)
- {
- }
-
- RenderText* renderer;
- float width;
- int startOffset;
- int endOffset;
- HashSet<const SimpleFontData*> fallbackFonts;
-};
-
-// Don't call this directly. Use one of the descriptive helper functions below.
-inline void deprecatedAddMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
-{
- if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
- lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
-
- InlineIterator* midpoints = lineMidpointState.midpoints.data();
- midpoints[lineMidpointState.numMidpoints++] = midpoint;
-}
-
-inline void startIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
-{
- ASSERT(!(lineMidpointState.numMidpoints % 2));
- deprecatedAddMidpoint(lineMidpointState, midpoint);
-}
-
-inline void stopIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
-{
- ASSERT(lineMidpointState.numMidpoints % 2);
- deprecatedAddMidpoint(lineMidpointState, midpoint);
-}
-
-// When ignoring spaces, this needs to be called for objects that need line boxes such as RenderInlines or
-// hard line breaks to ensure that they're not ignored.
-inline void ensureLineBoxInsideIgnoredSpaces(LineMidpointState& lineMidpointState, RenderObject* renderer)
-{
- InlineIterator midpoint(0, renderer, 0);
- stopIgnoringSpaces(lineMidpointState, midpoint);
- startIgnoringSpaces(lineMidpointState, midpoint);
-}
-
-// Adding a pair of midpoints before a character will split it out into a new line box.
-inline void ensureCharacterGetsLineBox(LineMidpointState& lineMidpointState, InlineIterator& textParagraphSeparator)
-{
- InlineIterator midpoint(0, textParagraphSeparator.object(), textParagraphSeparator.m_pos);
- startIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.object(), textParagraphSeparator.m_pos - 1));
- stopIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.object(), textParagraphSeparator.m_pos));
-}
-
-class TrailingObjects {
-public:
- TrailingObjects();
- void setTrailingWhitespace(RenderText*);
- void clear();
- void appendBoxIfNeeded(RenderBox*);
-
- enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace };
-
- void updateMidpointsForTrailingBoxes(LineMidpointState&, const InlineIterator& lBreak, CollapseFirstSpaceOrNot);
-
-private:
- RenderText* m_whitespace;
- Vector<RenderBox*, 4> m_boxes;
-};
-
-TrailingObjects::TrailingObjects()
- : m_whitespace(0)
-{
-}
-
-inline void TrailingObjects::setTrailingWhitespace(RenderText* whitespace)
-{
- ASSERT(whitespace);
- m_whitespace = whitespace;
-}
-
-inline void TrailingObjects::clear()
-{
- m_whitespace = 0;
- // Using resize(0) rather than clear() here saves 2% on
- // PerformanceTests/Layout/line-layout.html because we avoid freeing and
- // re-allocating the underlying buffer repeatedly.
- m_boxes.resize(0);
-}
-
-inline void TrailingObjects::appendBoxIfNeeded(RenderBox* box)
-{
- if (m_whitespace)
- m_boxes.append(box);
-}
-
-void TrailingObjects::updateMidpointsForTrailingBoxes(LineMidpointState& lineMidpointState, const InlineIterator& lBreak, CollapseFirstSpaceOrNot collapseFirstSpace)
-{
- if (!m_whitespace)
- return;
-
- // This object is either going to be part of the last midpoint, or it is going to be the actual endpoint.
- // In both cases we just decrease our pos by 1 level to exclude the space, allowing it to - in effect - collapse into the newline.
- if (lineMidpointState.numMidpoints % 2) {
- // Find the trailing space object's midpoint.
- int trailingSpaceMidpoint = lineMidpointState.numMidpoints - 1;
- for ( ; trailingSpaceMidpoint > 0 && lineMidpointState.midpoints[trailingSpaceMidpoint].object() != m_whitespace; --trailingSpaceMidpoint) { }
- ASSERT(trailingSpaceMidpoint >= 0);
- if (collapseFirstSpace == CollapseFirstSpace)
- lineMidpointState.midpoints[trailingSpaceMidpoint].m_pos--;
-
- // Now make sure every single trailingPositionedBox following the trailingSpaceMidpoint properly stops and starts
- // ignoring spaces.
- size_t currentMidpoint = trailingSpaceMidpoint + 1;
- for (size_t i = 0; i < m_boxes.size(); ++i) {
- if (currentMidpoint >= lineMidpointState.numMidpoints) {
- // We don't have a midpoint for this box yet.
- ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
- } else {
- ASSERT(lineMidpointState.midpoints[currentMidpoint].object() == m_boxes[i]);
- ASSERT(lineMidpointState.midpoints[currentMidpoint + 1].object() == m_boxes[i]);
- }
- currentMidpoint += 2;
- }
- } else if (!lBreak.object()) {
- ASSERT(m_whitespace->isText());
- ASSERT(collapseFirstSpace == CollapseFirstSpace);
- // Add a new end midpoint that stops right at the very end.
- unsigned length = m_whitespace->textLength();
- unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
- InlineIterator endMid(0, m_whitespace, pos);
- startIgnoringSpaces(lineMidpointState, endMid);
- for (size_t i = 0; i < m_boxes.size(); ++i) {
- ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
- }
- }
-}
-
class BreakingContext {
public:
BreakingContext(InlineBidiResolver& resolver, LineInfo& inLineInfo, LineWidth& lineWidth, RenderTextInfo& inRenderTextInfo, FloatingObject* inLastFloatFromPreviousLine, bool appliedStartWidth, RenderBlockFlow* block)
@@ -309,8 +151,6 @@ private:
TrailingObjects m_trailingObjects;
};
-enum WhitespacePosition { LeadingWhitespace, TrailingWhitespace };
-
inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const LineInfo& lineInfo, WhitespacePosition whitespacePosition)
{
// CSS2 16.6.1
@@ -441,7 +281,7 @@ inline void BreakingContext::handleBR(EClear& clear)
// need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a
// run for this object.
if (m_ignoringSpaces && m_currentStyle->clear() != CNONE)
- ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, br);
+ m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(br);
if (!m_lineInfo.isEmpty())
clear = m_currentStyle->clear();
@@ -495,7 +335,7 @@ inline void BreakingContext::handleOutOfFlowPositioned(Vector<RenderBox*>& posit
RenderBox* box = toRenderBox(m_current.object());
bool isInlineType = box->style()->isOriginalDisplayInlineType();
if (!isInlineType) {
- m_block->setStaticInlinePositionForChild(box, m_block->logicalHeight(), m_block->startOffsetForContent(m_block->logicalHeight()));
+ m_block->setStaticInlinePositionForChild(box, m_block->logicalHeight(), m_block->startOffsetForContent());
} else {
// If our original display was an INLINE type, then we can go ahead
// and determine our static y position now.
@@ -506,12 +346,12 @@ inline void BreakingContext::handleOutOfFlowPositioned(Vector<RenderBox*>& posit
// then start ignoring spaces again.
if (isInlineType || box->container()->isRenderInline()) {
if (m_ignoringSpaces)
- ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, box);
- m_trailingObjects.appendBoxIfNeeded(box);
+ m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(box);
+ m_trailingObjects.appendObjectIfNeeded(box);
} else {
positionedObjects.append(box);
}
- m_width.addUncommittedWidth(inlineLogicalWidth(box));
+ m_width.addUncommittedWidth(inlineLogicalWidth(box).toFloat());
// Reset prior line break context characters.
m_renderTextInfo.m_lineBreakIterator.resetPriorContext();
}
@@ -524,10 +364,10 @@ inline void BreakingContext::handleFloat()
// If it does, position it now, otherwise, position
// it after moving to next line (in newLine() func)
// FIXME: Bug 110372: Properly position multiple stacked floats with non-rectangular shape outside.
- if (m_floatsFitOnLine && m_width.fitsOnLine(m_block->logicalWidthForFloat(floatingObject))) {
+ if (m_floatsFitOnLine && m_width.fitsOnLine(m_block->logicalWidthForFloat(floatingObject).toFloat(), ExcludeWhitespace)) {
m_block->positionNewFloatOnLine(floatingObject, m_lastFloatFromPreviousLine, m_lineInfo, m_width);
if (m_lineBreak.object() == m_current.object()) {
- ASSERT(!m_lineBreak.m_pos);
+ ASSERT(!m_lineBreak.offset());
m_lineBreak.increment();
}
} else {
@@ -549,7 +389,7 @@ inline bool shouldSkipWhitespaceAfterStartObject(RenderBlockFlow* block, RenderO
RenderText* nextText = toRenderText(next);
UChar nextChar = nextText->characterAt(0);
if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
- startIgnoringSpaces(lineMidpointState, InlineIterator(0, o, 0));
+ lineMidpointState.startIgnoringSpaces(InlineIterator(0, o, 0));
return true;
}
}
@@ -564,29 +404,31 @@ inline void BreakingContext::handleEmptyInline()
RenderInline* flowBox = toRenderInline(m_current.object());
- // Now that some inline flows have line boxes, if we are already ignoring spaces, we need
- // to make sure that we stop to include this object and then start ignoring spaces again.
- // If this object is at the start of the line, we need to behave like list markers and
- // start ignoring spaces.
bool requiresLineBox = alwaysRequiresLineBox(m_current.object());
if (requiresLineBox || requiresLineBoxForContent(flowBox, m_lineInfo)) {
- // An empty inline that only has line-height, vertical-align or font-metrics will only get a
- // line box to affect the height of the line if the rest of the line is not empty.
+ // An empty inline that only has line-height, vertical-align or font-metrics will
+ // not force linebox creation (and thus affect the height of the line) if the rest of the line is empty.
if (requiresLineBox)
m_lineInfo.setEmpty(false, m_block, &m_width);
if (m_ignoringSpaces) {
+ // If we are in a run of ignored spaces then ensure we get a linebox if lineboxes are eventually
+ // created for the line...
m_trailingObjects.clear();
- ensureLineBoxInsideIgnoredSpaces(m_lineMidpointState, m_current.object());
+ m_lineMidpointState.ensureLineBoxInsideIgnoredSpaces(m_current.object());
} else if (m_blockStyle->collapseWhiteSpace() && m_resolver.position().object() == m_current.object()
&& shouldSkipWhitespaceAfterStartObject(m_block, m_current.object(), m_lineMidpointState)) {
- // Like with list markers, we start ignoring spaces to make sure that any
- // additional spaces we see will be discarded.
+ // If this object is at the start of the line, we need to behave like list markers and
+ // start ignoring spaces.
m_currentCharacterShouldCollapseIfPreWap = m_currentCharacterIsSpace = true;
m_ignoringSpaces = true;
+ } else {
+ // If we are after a trailing space but aren't ignoring spaces yet then ensure we get a linebox
+ // if we encounter collapsible whitepace.
+ m_trailingObjects.appendObjectIfNeeded(m_current.object());
}
}
- m_width.addUncommittedWidth(inlineLogicalWidth(m_current.object()) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
+ m_width.addUncommittedWidth((inlineLogicalWidth(m_current.object()) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox)).toFloat());
}
inline void BreakingContext::handleReplaced()
@@ -603,7 +445,7 @@ inline void BreakingContext::handleReplaced()
}
if (m_ignoringSpaces)
- stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.object(), 0));
+ m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), 0));
m_lineInfo.setEmpty(false, m_block, &m_width);
m_ignoringSpaces = false;
@@ -621,9 +463,9 @@ inline void BreakingContext::handleReplaced()
m_ignoringSpaces = true;
}
if (toRenderListMarker(m_current.object())->isInside())
- m_width.addUncommittedWidth(replacedLogicalWidth);
+ m_width.addUncommittedWidth(replacedLogicalWidth.toFloat());
} else {
- m_width.addUncommittedWidth(replacedLogicalWidth);
+ m_width.addUncommittedWidth(replacedLogicalWidth.toFloat());
}
if (m_current.object()->isRubyRun())
m_width.applyOverhang(toRenderRubyRun(m_current.object()), m_lastObject, m_nextObject);
@@ -633,7 +475,7 @@ inline void BreakingContext::handleReplaced()
inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText* renderer)
{
- return iter.object() == renderer && iter.m_pos >= renderer->textLength();
+ return iter.object() == renderer && iter.offset() >= renderer->textLength();
}
inline void nextCharacter(UChar& currentCharacter, UChar& lastCharacter, UChar& secondToLastCharacter)
@@ -651,66 +493,26 @@ inline float firstPositiveWidth(const WordMeasurements& wordMeasurements)
return 0;
}
-inline void updateSegmentsForShapes(RenderBlockFlow* block, const FloatingObject* lastFloatFromPreviousLine, const WordMeasurements& wordMeasurements, LineWidth& width, bool isFirstLine)
+inline float measureHyphenWidth(RenderText* renderer, const Font& font, TextDirection textDirection)
{
- ASSERT(lastFloatFromPreviousLine);
-
- ShapeInsideInfo* shapeInsideInfo = block->layoutShapeInsideInfo();
- if (!lastFloatFromPreviousLine->isPlaced() || !shapeInsideInfo)
- return;
-
- bool isHorizontalWritingMode = block->isHorizontalWritingMode();
- LayoutUnit logicalOffsetFromShapeContainer = block->logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner()).height();
-
- LayoutUnit lineLogicalTop = block->logicalHeight() + logicalOffsetFromShapeContainer;
- LayoutUnit lineLogicalHeight = block->lineHeight(isFirstLine, isHorizontalWritingMode ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
- LayoutUnit lineLogicalBottom = lineLogicalTop + lineLogicalHeight;
-
- LayoutUnit floatLogicalTop = block->logicalTopForFloat(lastFloatFromPreviousLine);
- LayoutUnit floatLogicalBottom = block->logicalBottomForFloat(lastFloatFromPreviousLine);
-
- bool lineOverlapsWithFloat = (floatLogicalTop < lineLogicalBottom) && (lineLogicalTop < floatLogicalBottom);
- if (!lineOverlapsWithFloat)
- return;
-
- float minSegmentWidth = firstPositiveWidth(wordMeasurements);
-
- LayoutUnit floatLogicalWidth = block->logicalWidthForFloat(lastFloatFromPreviousLine);
- LayoutUnit availableLogicalWidth = block->logicalWidth() - block->logicalRightForFloat(lastFloatFromPreviousLine);
- if (availableLogicalWidth < minSegmentWidth)
- block->setLogicalHeight(floatLogicalBottom);
-
- if (block->logicalHeight() < floatLogicalTop) {
- shapeInsideInfo->adjustLogicalLineTop(minSegmentWidth + floatLogicalWidth);
- block->setLogicalHeight(shapeInsideInfo->logicalLineTop() - logicalOffsetFromShapeContainer);
- }
-
- lineLogicalTop = block->logicalHeight() + logicalOffsetFromShapeContainer;
-
- shapeInsideInfo->updateSegmentsForLine(lineLogicalTop, lineLogicalHeight);
- width.updateCurrentShapeSegment();
- width.updateAvailableWidth();
+ RenderStyle* style = renderer->style();
+ return font.width(RenderBlockFlow::constructTextRun(renderer, font,
+ style->hyphenString().string(), style, style->direction()));
}
-inline float measureHyphenWidth(RenderText* renderer, const Font& font)
+ALWAYS_INLINE TextDirection textDirectionFromUnicode(WTF::Unicode::Direction direction)
{
- RenderStyle* style = renderer->style();
- return font.width(RenderBlockFlow::constructTextRun(renderer, font, style->hyphenString().string(), style));
+ return direction == WTF::Unicode::RightToLeft
+ || direction == WTF::Unicode::RightToLeftArabic ? RTL : LTR;
}
-ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*>* fallbackFonts = 0, TextLayout* layout = 0)
+ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*>* fallbackFonts = 0)
{
GlyphOverflow glyphOverflow;
if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
- return text->width(from, len, font, xPos, fallbackFonts, &glyphOverflow);
-
- if (layout)
- return Font::width(*layout, from, len, fallbackFonts);
+ return text->width(from, len, font, xPos, text->style()->direction(), fallbackFonts, &glyphOverflow);
TextRun run = RenderBlockFlow::constructTextRun(text, font, text, from, len, text->style());
- run.setCharactersLength(text->textLength() - from);
- ASSERT(run.charactersLength() >= run.length());
-
run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
run.setTabSize(!collapseWhiteSpace, text->style()->tabSize());
run.setXPos(xPos);
@@ -719,13 +521,20 @@ ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, con
inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool& hyphenated)
{
- if (!m_current.m_pos)
+ if (!m_current.offset())
m_appliedStartWidth = false;
RenderText* renderText = toRenderText(m_current.object());
bool isSVGText = renderText->isSVGInlineText();
+ // If we have left a no-wrap inline and entered an autowrap inline while ignoring spaces
+ // then we need to mark the start of the autowrap inline as a potential linebreak now.
+ if (m_autoWrap && !RenderStyle::autoWrap(m_lastWS) && m_ignoringSpaces) {
+ m_width.commit();
+ m_lineBreak.moveToStartOf(m_current.object());
+ }
+
if (renderText->style()->hasTextCombine() && m_current.object()->isCombineText() && !toRenderCombineText(m_current.object())->isCombined()) {
RenderCombineText* combineRenderer = toRenderCombineText(m_current.object());
combineRenderer->combineText();
@@ -741,7 +550,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
const Font& font = style->font();
bool isFixedPitch = font.isFixedPitch();
- unsigned lastSpace = m_current.m_pos;
+ unsigned lastSpace = m_current.offset();
float wordSpacing = m_currentStyle->wordSpacing();
float lastSpaceWordSpacing = 0;
float wordSpacingForWordMeasurement = 0;
@@ -763,28 +572,28 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
if (renderText->isWordBreak()) {
m_width.commit();
m_lineBreak.moveToStartOf(m_current.object());
- ASSERT(m_current.m_pos == renderText->textLength());
+ ASSERT(m_current.offset() == renderText->textLength());
}
if (m_renderTextInfo.m_text != renderText) {
m_renderTextInfo.m_text = renderText;
m_renderTextInfo.m_font = &font;
- m_renderTextInfo.createLayout(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText->text(), style->locale());
- } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) {
+ } else if (m_renderTextInfo.m_font != &font) {
m_renderTextInfo.m_font = &font;
- m_renderTextInfo.createLayout(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
}
- TextLayout* textLayout = m_renderTextInfo.m_layout.get();
-
- // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
+ // Non-zero only when kerning is enabled, in which case we measure
// words with their trailing space, then subtract its width.
- float wordTrailingSpaceWidth = (font.typesettingFeatures() & Kerning) && !textLayout ? font.width(RenderBlockFlow::constructTextRun(renderText, font, &space, 1, style)) + wordSpacing : 0;
+ float wordTrailingSpaceWidth = (font.fontDescription().typesettingFeatures() & Kerning) ?
+ font.width(RenderBlockFlow::constructTextRun(
+ renderText, font, &space, 1, style,
+ style->direction())) + wordSpacing
+ : 0;
UChar lastCharacter = m_renderTextInfo.m_lineBreakIterator.lastCharacter();
UChar secondToLastCharacter = m_renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
- for (; m_current.m_pos < renderText->textLength(); m_current.fastIncrementInTextNode()) {
+ for (; m_current.offset() < renderText->textLength(); m_current.fastIncrementInTextNode()) {
bool previousCharacterIsSpace = m_currentCharacterIsSpace;
bool previousCharacterShouldCollapseIfPreWap = m_currentCharacterShouldCollapseIfPreWap;
UChar c = m_current.current();
@@ -794,7 +603,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
m_lineInfo.setEmpty(false, m_block, &m_width);
if (c == softHyphen && m_autoWrap && !hyphenWidth) {
- hyphenWidth = measureHyphenWidth(renderText, font);
+ hyphenWidth = measureHyphenWidth(renderText, font, textDirectionFromUnicode(m_resolver.position().direction()));
m_width.addUncommittedWidth(hyphenWidth);
}
@@ -802,12 +611,14 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
if ((breakAll || breakWords) && !midWordBreak) {
wrapW += charWidth;
- bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.m_pos + 1 < renderText->textLength() && U16_IS_TRAIL((*renderText)[m_current.m_pos + 1]);
- charWidth = textWidth(renderText, m_current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch, m_collapseWhiteSpace, 0, textLayout);
+ bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && m_current.offset() + 1 < renderText->textLength() && U16_IS_TRAIL((*renderText)[m_current.offset() + 1]);
+ charWidth = textWidth(renderText, m_current.offset(), midWordBreakIsBeforeSurrogatePair ? 2 : 1, font, m_width.committedWidth() + wrapW, isFixedPitch, m_collapseWhiteSpace, 0);
midWordBreak = m_width.committedWidth() + wrapW + charWidth > m_width.availableWidth();
}
- bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.m_pos, m_current.m_nextBreakablePosition));
+ int nextBreakablePosition = m_current.nextBreakablePosition();
+ bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition));
+ m_current.setNextBreakablePosition(nextBreakablePosition);
if (betweenWords || midWordBreak) {
bool stoppedIgnoringSpaces = false;
@@ -818,8 +629,8 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
// new point.
m_ignoringSpaces = false;
wordSpacingForWordMeasurement = 0;
- lastSpace = m_current.m_pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.object(), m_current.m_pos));
+ lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces.
+ m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset()));
stoppedIgnoringSpaces = true;
} else {
// Just keep ignoring these spaces.
@@ -832,37 +643,38 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
WordMeasurement& wordMeasurement = wordMeasurements.last();
wordMeasurement.renderer = renderText;
- wordMeasurement.endOffset = m_current.m_pos;
+ wordMeasurement.endOffset = m_current.offset();
wordMeasurement.startOffset = lastSpace;
- float additionalTmpW;
+ float additionalTempWidth;
if (wordTrailingSpaceWidth && c == ' ')
- additionalTmpW = textWidth(renderText, lastSpace, m_current.m_pos + 1 - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;
+ additionalTempWidth = textWidth(renderText, lastSpace, m_current.offset() + 1 - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts) - wordTrailingSpaceWidth;
else
- additionalTmpW = textWidth(renderText, lastSpace, m_current.m_pos - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);
+ additionalTempWidth = textWidth(renderText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts);
+
+ wordMeasurement.width = additionalTempWidth + wordSpacingForWordMeasurement;
+ additionalTempWidth += lastSpaceWordSpacing;
+ m_width.addUncommittedWidth(additionalTempWidth);
+
+ if (m_collapseWhiteSpace && previousCharacterIsSpace && m_currentCharacterIsSpace && additionalTempWidth)
+ m_width.setTrailingWhitespaceWidth(additionalTempWidth);
- wordMeasurement.width = additionalTmpW + wordSpacingForWordMeasurement;
- additionalTmpW += lastSpaceWordSpacing;
- m_width.addUncommittedWidth(additionalTmpW);
if (!m_appliedStartWidth) {
- m_width.addUncommittedWidth(inlineLogicalWidth(m_current.object(), true, false));
+ m_width.addUncommittedWidth(inlineLogicalWidth(m_current.object(), true, false).toFloat());
m_appliedStartWidth = true;
}
- if (m_lastFloatFromPreviousLine)
- updateSegmentsForShapes(m_block, m_lastFloatFromPreviousLine, wordMeasurements, m_width, m_lineInfo.isFirstLine());
-
applyWordSpacing = wordSpacing && m_currentCharacterIsSpace;
if (!m_width.committedWidth() && m_autoWrap && !m_width.fitsOnLine())
- m_width.fitBelowFloats();
+ m_width.fitBelowFloats(m_lineInfo.isFirstLine());
if (m_autoWrap || breakWords) {
// If we break only after white-space, consider the current character
// as candidate width for this line.
bool lineWasTooWide = false;
if (m_width.fitsOnLine() && m_currentCharacterIsSpace && m_currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
- float charWidth = textWidth(renderText, m_current.m_pos, 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);
+ float charWidth = textWidth(renderText, m_current.offset(), 1, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts) + (applyWordSpacing ? wordSpacing : 0);
// Check if line is too big even without the extra space
// at the end of the line. If it is not, do nothing.
// If the line needs the extra whitespace to be too long,
@@ -870,23 +682,23 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
// additional whitespace.
if (!m_width.fitsOnLine(charWidth)) {
lineWasTooWide = true;
- m_lineBreak.moveTo(m_current.object(), m_current.m_pos, m_current.m_nextBreakablePosition);
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
skipTrailingWhitespace(m_lineBreak, m_lineInfo);
}
}
if (lineWasTooWide || !m_width.fitsOnLine()) {
if (m_lineBreak.atTextParagraphSeparator()) {
- if (!stoppedIgnoringSpaces && m_current.m_pos > 0)
- ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
+ if (!stoppedIgnoringSpaces && m_current.offset() > 0)
+ m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
m_lineBreak.increment();
m_lineInfo.setPreviousLineBrokeCleanly(true);
- wordMeasurement.endOffset = m_lineBreak.m_pos;
+ wordMeasurement.endOffset = m_lineBreak.offset();
}
- if (m_lineBreak.object() && m_lineBreak.m_pos && m_lineBreak.object()->isText() && toRenderText(m_lineBreak.object())->textLength() && toRenderText(m_lineBreak.object())->characterAt(m_lineBreak.m_pos - 1) == softHyphen)
+ if (m_lineBreak.object() && m_lineBreak.offset() && m_lineBreak.object()->isText() && toRenderText(m_lineBreak.object())->textLength() && toRenderText(m_lineBreak.object())->characterAt(m_lineBreak.offset() - 1) == softHyphen)
hyphenated = true;
- if (m_lineBreak.m_pos && m_lineBreak.m_pos != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
+ if (m_lineBreak.offset() && m_lineBreak.offset() != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
if (charWidth) {
- wordMeasurement.endOffset = m_lineBreak.m_pos;
+ wordMeasurement.endOffset = m_lineBreak.offset();
wordMeasurement.width = charWidth;
}
}
@@ -897,7 +709,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
}
} else {
if (!betweenWords || (midWordBreak && !m_autoWrap))
- m_width.addUncommittedWidth(-additionalTmpW);
+ m_width.addUncommittedWidth(-additionalTempWidth);
if (hyphenWidth) {
// Subtract the width of the soft hyphen out since we fit on a line.
m_width.addUncommittedWidth(-hyphenWidth);
@@ -907,9 +719,9 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
}
if (c == '\n' && m_preservesNewline) {
- if (!stoppedIgnoringSpaces && m_current.m_pos > 0)
- ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
- m_lineBreak.moveTo(m_current.object(), m_current.m_pos, m_current.m_nextBreakablePosition);
+ if (!stoppedIgnoringSpaces && m_current.offset())
+ m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
m_lineBreak.increment();
m_lineInfo.setPreviousLineBrokeCleanly(true);
return true;
@@ -918,23 +730,23 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
if (m_autoWrap && betweenWords) {
m_width.commit();
wrapW = 0;
- m_lineBreak.moveTo(m_current.object(), m_current.m_pos, m_current.m_nextBreakablePosition);
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
// Auto-wrapping text should not wrap in the middle of a word once it has had an
// opportunity to break after a word.
breakWords = false;
}
- if (midWordBreak && !U16_IS_TRAIL(c) && !(category(c) & (Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining))) {
+ if (midWordBreak && !U16_IS_TRAIL(c) && !(WTF::Unicode::category(c) & (WTF::Unicode::Mark_NonSpacing | WTF::Unicode::Mark_Enclosing | WTF::Unicode::Mark_SpacingCombining))) {
// Remember this as a breakable position in case
// adding the end width forces a break.
- m_lineBreak.moveTo(m_current.object(), m_current.m_pos, m_current.m_nextBreakablePosition);
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
midWordBreak &= (breakWords || breakAll);
}
if (betweenWords) {
lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
- lastSpace = m_current.m_pos;
+ lastSpace = m_current.offset();
}
if (!m_ignoringSpaces && m_currentStyle->collapseWhiteSpace()) {
@@ -947,8 +759,8 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
// We just entered a mode where we are ignoring
// spaces. Create a midpoint to terminate the run
// before the second space.
- startIgnoringSpaces(m_lineMidpointState, m_startOfIgnoredSpaces);
- m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
+ m_lineMidpointState.startIgnoringSpaces(m_startOfIgnoredSpaces);
+ m_trailingObjects.updateMidpointsForTrailingObjects(m_lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
}
}
} else if (m_ignoringSpaces) {
@@ -957,24 +769,24 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
m_ignoringSpaces = false;
lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
- lastSpace = m_current.m_pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- stopIgnoringSpaces(m_lineMidpointState, InlineIterator(0, m_current.object(), m_current.m_pos));
+ lastSpace = m_current.offset(); // e.g., "Foo goo", don't add in any of the ignored spaces.
+ m_lineMidpointState.stopIgnoringSpaces(InlineIterator(0, m_current.object(), m_current.offset()));
}
- if (isSVGText && m_current.m_pos > 0) {
+ if (isSVGText && m_current.offset()) {
// Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
- if (toRenderSVGInlineText(renderText)->characterStartsNewTextChunk(m_current.m_pos))
- ensureCharacterGetsLineBox(m_lineMidpointState, m_current);
+ if (toRenderSVGInlineText(renderText)->characterStartsNewTextChunk(m_current.offset()))
+ m_lineMidpointState.ensureCharacterGetsLineBox(m_current);
}
if (m_currentCharacterIsSpace && !previousCharacterIsSpace) {
m_startOfIgnoredSpaces.setObject(m_current.object());
- m_startOfIgnoredSpaces.m_pos = m_current.m_pos;
+ m_startOfIgnoredSpaces.setOffset(m_current.offset());
}
if (!m_currentCharacterIsSpace && previousCharacterShouldCollapseIfPreWap) {
if (m_autoWrap && m_currentStyle->breakOnlyAfterWhiteSpace())
- m_lineBreak.moveTo(m_current.object(), m_current.m_pos, m_current.m_nextBreakablePosition);
+ m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
}
if (m_collapseWhiteSpace && m_currentCharacterIsSpace && !m_ignoringSpaces)
@@ -993,12 +805,18 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
wordMeasurement.renderer = renderText;
// IMPORTANT: current.m_pos is > length here!
- float additionalTmpW = m_ignoringSpaces ? 0 : textWidth(renderText, lastSpace, m_current.m_pos - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);
+ float additionalTempWidth = m_ignoringSpaces ? 0 : textWidth(renderText, lastSpace, m_current.offset() - lastSpace, font, m_width.currentWidth(), isFixedPitch, m_collapseWhiteSpace, &wordMeasurement.fallbackFonts);
wordMeasurement.startOffset = lastSpace;
- wordMeasurement.endOffset = m_current.m_pos;
- wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTmpW + wordSpacingForWordMeasurement;
- additionalTmpW += lastSpaceWordSpacing;
- m_width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(m_current.object(), !m_appliedStartWidth, m_includeEndWidth));
+ wordMeasurement.endOffset = m_current.offset();
+ wordMeasurement.width = m_ignoringSpaces ? 0 : additionalTempWidth + wordSpacingForWordMeasurement;
+ additionalTempWidth += lastSpaceWordSpacing;
+
+ LayoutUnit inlineLogicalTempWidth = inlineLogicalWidth(m_current.object(), !m_appliedStartWidth, m_includeEndWidth);
+ m_width.addUncommittedWidth(additionalTempWidth + inlineLogicalTempWidth);
+
+ if (m_collapseWhiteSpace && m_currentCharacterIsSpace && additionalTempWidth)
+ m_width.setTrailingWhitespaceWidth(additionalTempWidth + inlineLogicalTempWidth);
+
m_includeEndWidth = false;
if (!m_width.fitsOnLine()) {
@@ -1031,7 +849,7 @@ inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
}
if (!m_width.fitsOnLine() && !m_width.committedWidth())
- m_width.fitBelowFloats();
+ m_width.fitBelowFloats(m_lineInfo.isFirstLine());
bool canPlaceOnLine = m_width.fitsOnLine() || !m_autoWrapWasEverTrueOnLine;
if (canPlaceOnLine && checkForBreak) {
@@ -1041,6 +859,7 @@ inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
}
}
+ ASSERT_WITH_SECURITY_IMPLICATION(m_currentStyle->refCount() > 0);
if (checkForBreak && !m_width.fitsOnLine()) {
// if we have floats, try to get below them.
if (m_currentCharacterIsSpace && !m_ignoringSpaces && m_currentStyle->collapseWhiteSpace())
@@ -1051,7 +870,7 @@ inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
return;
}
- m_width.fitBelowFloats();
+ m_width.fitBelowFloats(m_lineInfo.isFirstLine());
// |width| may have been adjusted because we got shoved down past a float (thus
// giving us more room), so we need to retest, and only jump to
@@ -1063,7 +882,7 @@ inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
} else if (m_blockStyle->autoWrap() && !m_width.fitsOnLine() && !m_width.committedWidth()) {
// If the container autowraps but the current child does not then we still need to ensure that it
// wraps and moves below any floats.
- m_width.fitBelowFloats();
+ m_width.fitBelowFloats(m_lineInfo.isFirstLine());
}
if (!m_current.object()->isFloatingOrOutOfFlowPositioned()) {
@@ -1075,69 +894,16 @@ inline void BreakingContext::commitAndUpdateLineBreakIfNeeded()
}
}
-inline void checkMidpoints(LineMidpointState& lineMidpointState, InlineIterator& lBreak)
-{
- // Check to see if our last midpoint is a start point beyond the line break. If so,
- // shave it off the list, and shave off a trailing space if the previous end point doesn't
- // preserve whitespace.
- if (lBreak.object() && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
- InlineIterator* midpoints = lineMidpointState.midpoints.data();
- InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
- const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 1];
- InlineIterator currpoint = endpoint;
- while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
- currpoint.increment();
- if (currpoint == lBreak) {
- // We hit the line break before the start point. Shave off the start point.
- lineMidpointState.numMidpoints--;
- if (endpoint.object()->style()->collapseWhiteSpace() && endpoint.object()->isText())
- endpoint.m_pos--;
- }
- }
-}
-
-InlineIterator BreakingContext::handleEndOfLine()
+inline IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBreak, RenderStyle* style)
{
- ShapeInsideInfo* shapeInfo = m_block->layoutShapeInsideInfo();
- bool segmentAllowsOverflow = !shapeInfo || !shapeInfo->hasSegments();
-
- if (m_lineBreak == m_resolver.position() && (!m_lineBreak.object() || !m_lineBreak.object()->isBR()) && segmentAllowsOverflow) {
- // we just add as much as possible
- if (m_blockStyle->whiteSpace() == PRE && !m_current.m_pos) {
- m_lineBreak.moveTo(m_lastObject, m_lastObject->isText() ? m_lastObject->length() : 0);
- } else if (m_lineBreak.object()) {
- // Don't ever break in the middle of a word if we can help it.
- // There's no room at all. We just have to be on this line,
- // even though we'll spill out.
- m_lineBreak.moveTo(m_current.object(), m_current.m_pos);
- }
- }
+ IndentTextOrNot shouldIndentText = DoNotIndentText;
+ if (isFirstLine || (isAfterHardLineBreak && style->textIndentLine()) == TextIndentEachLine)
+ shouldIndentText = IndentText;
- // FIXME Bug 100049: We do not need to consume input in a multi-segment line
- // unless no segment will.
- // make sure we consume at least one char/object.
- if (m_lineBreak == m_resolver.position() && segmentAllowsOverflow)
- m_lineBreak.increment();
-
- // Sanity check our midpoints.
- checkMidpoints(m_lineMidpointState, m_lineBreak);
-
- m_trailingObjects.updateMidpointsForTrailingBoxes(m_lineMidpointState, m_lineBreak, TrailingObjects::CollapseFirstSpace);
-
- // We might have made lineBreak an iterator that points past the end
- // of the object. Do this adjustment to make it point to the start
- // of the next object instead to avoid confusing the rest of the
- // code.
- if (m_lineBreak.m_pos > 0) {
- // This loop enforces the invariant that line breaks should never point
- // at an empty inline. See http://crbug.com/305904.
- do {
- m_lineBreak.m_pos--;
- m_lineBreak.increment();
- } while (!m_lineBreak.atEnd() && isEmptyInline(m_lineBreak.object()));
- }
+ if (style->textIndentType() == TextIndentHanging)
+ shouldIndentText = shouldIndentText == IndentText ? DoNotIndentText : IndentText;
- return m_lineBreak;
+ return shouldIndentText;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.cpp b/chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.cpp
new file mode 100644
index 00000000000..074aafe5a4b
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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"
+#include "core/rendering/line/LineBreaker.h"
+
+#include "core/rendering/line/BreakingContextInlineHeaders.h"
+
+namespace WebCore {
+
+void LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo,
+ FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
+{
+ while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) {
+ RenderObject* object = resolver.position().object();
+ if (object->isOutOfFlowPositioned()) {
+ setStaticPositions(m_block, toRenderBox(object));
+ if (object->style()->isOriginalDisplayInlineType()) {
+ resolver.runs().addRun(createRun(0, 1, object, resolver));
+ lineInfo.incrementRunsFromLeadingWhitespace();
+ }
+ } else if (object->isFloating()) {
+ m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width);
+ } else if (object->isText() && object->style()->hasTextCombine() && object->isCombineText() && !toRenderCombineText(object)->isCombined()) {
+ toRenderCombineText(object)->combineText();
+ if (toRenderCombineText(object)->isCombined())
+ continue;
+ }
+ resolver.position().increment(&resolver);
+ }
+ resolver.commitExplicitEmbedding();
+}
+
+void LineBreaker::reset()
+{
+ m_positionedObjects.clear();
+ m_hyphenated = false;
+ m_clear = CNONE;
+}
+
+InlineIterator LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
+{
+ reset();
+
+ ASSERT(resolver.position().root() == m_block);
+
+ bool appliedStartWidth = resolver.position().offset() > 0;
+
+ LineWidth width(*m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style()));
+
+ skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width);
+
+ if (resolver.position().atEnd())
+ return resolver.position();
+
+ BreakingContext context(resolver, lineInfo, width, renderTextInfo, lastFloatFromPreviousLine, appliedStartWidth, m_block);
+
+ while (context.currentObject()) {
+ context.initializeForCurrentObject();
+ if (context.currentObject()->isBR()) {
+ context.handleBR(m_clear);
+ } else if (context.currentObject()->isOutOfFlowPositioned()) {
+ context.handleOutOfFlowPositioned(m_positionedObjects);
+ } else if (context.currentObject()->isFloating()) {
+ context.handleFloat();
+ } else if (context.currentObject()->isRenderInline()) {
+ context.handleEmptyInline();
+ } else if (context.currentObject()->isReplaced()) {
+ context.handleReplaced();
+ } else if (context.currentObject()->isText()) {
+ if (context.handleText(wordMeasurements, m_hyphenated)) {
+ // We've hit a hard text line break. Our line break iterator is updated, so go ahead and early return.
+ return context.lineBreak();
+ }
+ } else {
+ ASSERT_NOT_REACHED();
+ }
+
+ if (context.atEnd())
+ return context.handleEndOfLine();
+
+ context.commitAndUpdateLineBreakIfNeeded();
+
+ if (context.atEnd())
+ return context.handleEndOfLine();
+
+ context.increment();
+ }
+
+ context.clearLineBreakIfFitsOnLine();
+
+ return context.handleEndOfLine();
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.h b/chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.h
new file mode 100644
index 00000000000..2cb519205df
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/LineBreaker.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * 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 LineBreaker_h
+#define LineBreaker_h
+
+#include "core/rendering/InlineIterator.h"
+#include "core/rendering/line/LineInfo.h"
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+enum WhitespacePosition { LeadingWhitespace, TrailingWhitespace };
+
+struct RenderTextInfo;
+
+class LineBreaker {
+public:
+ friend class BreakingContext;
+ LineBreaker(RenderBlockFlow* block)
+ : m_block(block)
+ {
+ reset();
+ }
+
+ InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
+
+ bool lineWasHyphenated() { return m_hyphenated; }
+ const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
+ EClear clear() { return m_clear; }
+private:
+ void reset();
+
+ void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
+
+ RenderBlockFlow* m_block;
+ bool m_hyphenated;
+ EClear m_clear;
+ Vector<RenderBox*> m_positionedObjects;
+};
+
+}
+
+#endif // LineBreaker_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/LineInfo.h b/chromium/third_party/WebKit/Source/core/rendering/line/LineInfo.h
index 337da116e8b..bd5ad169678 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/line/LineInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/LineInfo.h
@@ -24,6 +24,8 @@
#ifndef LineInfo_h
#define LineInfo_h
+#include "core/rendering/line/LineWidth.h"
+
namespace WebCore {
class LineInfo {
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/LineLayoutState.h b/chromium/third_party/WebKit/Source/core/rendering/line/LineLayoutState.h
new file mode 100644
index 00000000000..b62adcd9bd6
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/LineLayoutState.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2014 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
+ * 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 LineLayoutState_h
+#define LineLayoutState_h
+
+#include "core/rendering/RenderBlockFlow.h"
+#include "platform/geometry/LayoutRect.h"
+
+namespace WebCore {
+
+// Like LayoutState for layout(), LineLayoutState keeps track of global information
+// during an entire linebox tree layout pass (aka layoutInlineChildren).
+class LineLayoutState {
+public:
+ LineLayoutState(bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFlowThread* flowThread)
+ : m_lastFloat(0)
+ , m_endLine(0)
+ , m_floatIndex(0)
+ , m_endLineLogicalTop(0)
+ , m_endLineMatched(false)
+ , m_checkForFloatsFromLastLine(false)
+ , m_hasInlineChild(false)
+ , m_isFullLayout(fullLayout)
+ , m_repaintLogicalTop(repaintLogicalTop)
+ , m_repaintLogicalBottom(repaintLogicalBottom)
+ , m_adjustedLogicalLineTop(0)
+ , m_usesRepaintBounds(false)
+ , m_flowThread(flowThread)
+ { }
+
+ void markForFullLayout() { m_isFullLayout = true; }
+ bool isFullLayout() const { return m_isFullLayout; }
+
+ bool usesRepaintBounds() const { return m_usesRepaintBounds; }
+
+ void setRepaintRange(LayoutUnit logicalHeight)
+ {
+ m_usesRepaintBounds = true;
+ m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight;
+ }
+
+ void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0)
+ {
+ m_usesRepaintBounds = true;
+ m_repaintLogicalTop = std::min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + std::min<LayoutUnit>(paginationDelta, 0));
+ m_repaintLogicalBottom = std::max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + std::max<LayoutUnit>(paginationDelta, 0));
+ }
+
+ bool endLineMatched() const { return m_endLineMatched; }
+ void setEndLineMatched(bool endLineMatched) { m_endLineMatched = endLineMatched; }
+
+ bool checkForFloatsFromLastLine() const { return m_checkForFloatsFromLastLine; }
+ void setCheckForFloatsFromLastLine(bool check) { m_checkForFloatsFromLastLine = check; }
+
+ bool hasInlineChild() const { return m_hasInlineChild; }
+ void setHasInlineChild(bool hasInlineChild) { m_hasInlineChild = hasInlineChild; }
+
+ LineInfo& lineInfo() { return m_lineInfo; }
+ const LineInfo& lineInfo() const { return m_lineInfo; }
+
+ 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; }
+
+ FloatingObject* lastFloat() const { return m_lastFloat; }
+ void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
+
+ Vector<RenderBlockFlow::FloatWithRect>& floats() { return m_floats; }
+
+ unsigned floatIndex() const { return m_floatIndex; }
+ void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }
+
+ LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; }
+ void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; }
+
+ RenderFlowThread* flowThread() const { return m_flowThread; }
+ void setFlowThread(RenderFlowThread* thread) { m_flowThread = thread; }
+
+private:
+ Vector<RenderBlockFlow::FloatWithRect> m_floats;
+ FloatingObject* m_lastFloat;
+ RootInlineBox* m_endLine;
+ LineInfo m_lineInfo;
+ unsigned m_floatIndex;
+ LayoutUnit m_endLineLogicalTop;
+ bool m_endLineMatched;
+ bool m_checkForFloatsFromLastLine;
+ // Used as a performance optimization to avoid doing a full repaint when our floats
+ // change but we don't have any inline children.
+ bool m_hasInlineChild;
+
+ bool m_isFullLayout;
+
+ // FIXME: Should this be a range object instead of two ints?
+ LayoutUnit& m_repaintLogicalTop;
+ LayoutUnit& m_repaintLogicalBottom;
+
+ LayoutUnit m_adjustedLogicalLineTop;
+
+ bool m_usesRepaintBounds;
+
+ RenderFlowThread* m_flowThread;
+};
+
+}
+
+#endif // LineLayoutState_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LineWidth.cpp b/chromium/third_party/WebKit/Source/core/rendering/line/LineWidth.cpp
index ea720e2024e..1b46843d9f4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LineWidth.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/LineWidth.cpp
@@ -28,7 +28,7 @@
*/
#include "config.h"
-#include "core/rendering/LineWidth.h"
+#include "core/rendering/line/LineWidth.h"
#include "core/rendering/RenderBlock.h"
#include "core/rendering/RenderRubyRun.h"
@@ -40,14 +40,13 @@ LineWidth::LineWidth(RenderBlockFlow& block, bool isFirstLine, IndentTextOrNot s
, m_uncommittedWidth(0)
, m_committedWidth(0)
, m_overhangWidth(0)
+ , m_trailingWhitespaceWidth(0)
, m_left(0)
, m_right(0)
, m_availableWidth(0)
- , m_segment(0)
, m_isFirstLine(isFirstLine)
, m_shouldIndentText(shouldIndentText)
{
- updateCurrentShapeSegment();
updateAvailableWidth();
}
@@ -55,13 +54,8 @@ void LineWidth::updateAvailableWidth(LayoutUnit replacedHeight)
{
LayoutUnit height = m_block.logicalHeight();
LayoutUnit logicalHeight = m_block.minLineHeightForReplacedRenderer(m_isFirstLine, replacedHeight);
- m_left = m_block.logicalLeftOffsetForLine(height, shouldIndentText(), logicalHeight);
- m_right = m_block.logicalRightOffsetForLine(height, shouldIndentText(), logicalHeight);
-
- if (m_segment) {
- m_left = std::max<float>(m_segment->logicalLeft, m_left);
- m_right = std::min<float>(m_segment->logicalRight, m_right);
- }
+ m_left = m_block.logicalLeftOffsetForLine(height, shouldIndentText(), logicalHeight).toFloat();
+ m_right = m_block.logicalRightOffsetForLine(height, shouldIndentText(), logicalHeight).toFloat();
computeAvailableWidthFromLeftAndRight();
}
@@ -72,47 +66,31 @@ void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat
if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat))
return;
- // When floats with shape outside are stacked, the floats are positioned based on the margin box of the float,
- // not the shape's contour. Since we computed the width based on the shape contour when we added the float,
- // when we add a subsequent float on the same line, we need to undo the shape delta in order to position
- // based on the margin box. In order to do this, we need to walk back through the floating object list to find
- // the first previous float that is on the same side as our newFloat.
- ShapeOutsideInfo* previousShapeOutsideInfo = 0;
- const FloatingObjectSet& floatingObjectSet = m_block.m_floatingObjects->set();
- FloatingObjectSetIterator it = floatingObjectSet.end();
- FloatingObjectSetIterator begin = floatingObjectSet.begin();
- LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
- for (--it; it != begin; --it) {
- FloatingObject* previousFloat = *it;
- if (previousFloat != newFloat && previousFloat->type() == newFloat->type()) {
- previousShapeOutsideInfo = previousFloat->renderer()->shapeOutsideInfo();
- if (previousShapeOutsideInfo)
- previousShapeOutsideInfo->updateDeltasForContainingBlockLine(&m_block, previousFloat, m_block.logicalHeight(), lineHeight);
- break;
- }
- }
-
ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo();
- if (shapeOutsideInfo)
- shapeOutsideInfo->updateDeltasForContainingBlockLine(&m_block, newFloat, m_block.logicalHeight(), lineHeight);
+ if (shapeOutsideInfo) {
+ LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+ shapeOutsideInfo->updateDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight);
+ }
if (newFloat->type() == FloatingObject::FloatLeft) {
- float newLeft = m_block.logicalRightForFloat(newFloat);
- if (previousShapeOutsideInfo)
- newLeft -= previousShapeOutsideInfo->rightMarginBoxDelta();
- if (shapeOutsideInfo)
- newLeft += shapeOutsideInfo->rightMarginBoxDelta();
-
+ float newLeft = m_block.logicalRightForFloat(newFloat).toFloat();
+ if (shapeOutsideInfo) {
+ if (shapeOutsideInfo->lineOverlapsShape())
+ newLeft += shapeOutsideInfo->rightMarginBoxDelta();
+ else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line.
+ newLeft = m_left;
+ }
if (shouldIndentText() && m_block.style()->isLeftToRightDirection())
newLeft += floorToInt(m_block.textIndentOffset());
m_left = std::max<float>(m_left, newLeft);
} else {
- float newRight = m_block.logicalLeftForFloat(newFloat);
- if (previousShapeOutsideInfo)
- newRight -= previousShapeOutsideInfo->leftMarginBoxDelta();
- if (shapeOutsideInfo)
- newRight += shapeOutsideInfo->leftMarginBoxDelta();
-
+ float newRight = m_block.logicalLeftForFloat(newFloat).toFloat();
+ if (shapeOutsideInfo) {
+ if (shapeOutsideInfo->lineOverlapsShape())
+ newRight += shapeOutsideInfo->leftMarginBoxDelta();
+ else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line.
+ newRight = m_right;
+ }
if (shouldIndentText() && !m_block.style()->isLeftToRightDirection())
newRight -= floorToInt(m_block.textIndentOffset());
m_right = std::min<float>(m_right, newRight);
@@ -141,7 +119,65 @@ void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRendere
m_overhangWidth += startOverhang + endOverhang;
}
-void LineWidth::fitBelowFloats()
+inline static float availableWidthAtOffset(const RenderBlockFlow& block, const LayoutUnit& offset, bool shouldIndentText, float& newLineLeft, float& newLineRight)
+{
+ newLineLeft = block.logicalLeftOffsetForLine(offset, shouldIndentText).toFloat();
+ newLineRight = block.logicalRightOffsetForLine(offset, shouldIndentText).toFloat();
+ return std::max(0.0f, newLineRight - newLineLeft);
+}
+
+inline static float availableWidthAtOffset(const RenderBlockFlow& block, const LayoutUnit& offset, bool shouldIndentText)
+{
+ float newLineLeft = block.logicalLeftOffsetForLine(offset, shouldIndentText).toFloat();
+ float newLineRight = block.logicalRightOffsetForLine(offset, shouldIndentText).toFloat();
+ return std::max(0.0f, newLineRight - newLineLeft);
+}
+
+void LineWidth::updateLineDimension(LayoutUnit newLineTop, LayoutUnit newLineWidth, const float& newLineLeft, const float& newLineRight)
+{
+ if (newLineWidth <= m_availableWidth)
+ return;
+
+ m_block.setLogicalHeight(newLineTop);
+ m_availableWidth = newLineWidth + m_overhangWidth;
+ m_left = newLineLeft;
+ m_right = newLineRight;
+}
+
+inline static bool isWholeLineFit(const RenderBlockFlow& block, const LayoutUnit& lineTop, LayoutUnit lineHeight, float uncommittedWidth, bool shouldIndentText)
+{
+ for (LayoutUnit lineBottom = lineTop; lineBottom <= lineTop + lineHeight; lineBottom++) {
+ LayoutUnit availableWidthAtBottom = availableWidthAtOffset(block, lineBottom, shouldIndentText);
+ if (availableWidthAtBottom < uncommittedWidth)
+ return false;
+ }
+ return true;
+}
+
+void LineWidth::wrapNextToShapeOutside(bool isFirstLine)
+{
+ LayoutUnit lineHeight = m_block.lineHeight(isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+ LayoutUnit lineLogicalTop = m_block.logicalHeight();
+ LayoutUnit newLineTop = lineLogicalTop;
+ LayoutUnit floatLogicalBottom = m_block.nextFloatLogicalBottomBelow(lineLogicalTop);
+
+ float newLineWidth;
+ float newLineLeft = m_left;
+ float newLineRight = m_right;
+ while (true) {
+ newLineWidth = availableWidthAtOffset(m_block, newLineTop, shouldIndentText(), newLineLeft, newLineRight);
+ if (newLineWidth >= m_uncommittedWidth && isWholeLineFit(m_block, newLineTop, lineHeight, m_uncommittedWidth, shouldIndentText()))
+ break;
+
+ if (newLineTop >= floatLogicalBottom)
+ break;
+
+ newLineTop++;
+ }
+ updateLineDimension(newLineTop, newLineWidth, newLineLeft, newLineRight);
+}
+
+void LineWidth::fitBelowFloats(bool isFirstLine)
{
ASSERT(!m_committedWidth);
ASSERT(!fitsOnLine());
@@ -151,42 +187,23 @@ void LineWidth::fitBelowFloats()
float newLineWidth = m_availableWidth;
float newLineLeft = m_left;
float newLineRight = m_right;
+
+ FloatingObject* lastFloatFromPreviousLine = (m_block.containsFloats() ? m_block.m_floatingObjects->set().last().get() : 0);
+ if (lastFloatFromPreviousLine && lastFloatFromPreviousLine->renderer()->shapeOutsideInfo())
+ return wrapNextToShapeOutside(isFirstLine);
+
while (true) {
floatLogicalBottom = m_block.nextFloatLogicalBottomBelow(lastFloatLogicalBottom, ShapeOutsideFloatShapeOffset);
if (floatLogicalBottom <= lastFloatLogicalBottom)
break;
- newLineLeft = m_block.logicalLeftOffsetForLine(floatLogicalBottom, shouldIndentText());
- newLineRight = m_block.logicalRightOffsetForLine(floatLogicalBottom, shouldIndentText());
- newLineWidth = max(0.0f, newLineRight - newLineLeft);
+ newLineWidth = availableWidthAtOffset(m_block, floatLogicalBottom, shouldIndentText(), newLineLeft, newLineRight);
lastFloatLogicalBottom = floatLogicalBottom;
- // FIXME: This code should be refactored to incorporate with the code above.
- ShapeInsideInfo* shapeInsideInfo = m_block.layoutShapeInsideInfo();
- if (shapeInsideInfo) {
- LayoutUnit logicalOffsetFromShapeContainer = m_block.logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner()).height();
- LayoutUnit lineHeight = m_block.lineHeight(false, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
- shapeInsideInfo->updateSegmentsForLine(lastFloatLogicalBottom + logicalOffsetFromShapeContainer, lineHeight);
- updateCurrentShapeSegment();
- updateAvailableWidth();
- }
-
if (newLineWidth >= m_uncommittedWidth)
break;
}
-
- if (newLineWidth > m_availableWidth) {
- m_block.setLogicalHeight(lastFloatLogicalBottom);
- m_availableWidth = newLineWidth + m_overhangWidth;
- m_left = newLineLeft;
- m_right = newLineRight;
- }
-}
-
-void LineWidth::updateCurrentShapeSegment()
-{
- if (ShapeInsideInfo* shapeInsideInfo = m_block.layoutShapeInsideInfo())
- m_segment = shapeInsideInfo->currentSegment();
+ updateLineDimension(lastFloatLogicalBottom, newLineWidth, newLineLeft, newLineRight);
}
void LineWidth::computeAvailableWidthFromLeftAndRight()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/LineWidth.h b/chromium/third_party/WebKit/Source/core/rendering/line/LineWidth.h
index 59e1442445e..c9346b770b7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/LineWidth.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/LineWidth.h
@@ -35,14 +35,12 @@
namespace WebCore {
class FloatingObject;
-class RenderBlock;
class RenderObject;
class RenderRubyRun;
class RenderBlockFlow;
-struct LineSegment;
-
enum IndentTextOrNot { DoNotIndentText, IndentText };
+enum WhitespaceTreatment { ExcludeWhitespace, IncludeWhitespace };
class LineWidth {
public:
@@ -50,35 +48,41 @@ public:
bool fitsOnLine() const { return currentWidth() <= (m_availableWidth + LayoutUnit::epsilon()); }
bool fitsOnLine(float extra) const { return currentWidth() + extra <= (m_availableWidth + LayoutUnit::epsilon()); }
+ bool fitsOnLine(float extra, WhitespaceTreatment whitespaceTreatment) const
+ {
+ return currentWidth() - (whitespaceTreatment == ExcludeWhitespace ? trailingWhitespaceWidth() : 0) + extra <= (m_availableWidth + LayoutUnit::epsilon());
+ }
float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }
// FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.
float uncommittedWidth() const { return m_uncommittedWidth; }
float committedWidth() const { return m_committedWidth; }
float availableWidth() const { return m_availableWidth; }
+ float trailingWhitespaceWidth() const { return m_trailingWhitespaceWidth; }
void updateAvailableWidth(LayoutUnit minimumHeight = 0);
void shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject*);
void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; }
void commit();
void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
- void fitBelowFloats();
-
- void updateCurrentShapeSegment();
+ void fitBelowFloats(bool isFirstLine = false);
+ void setTrailingWhitespaceWidth(float width) { m_trailingWhitespaceWidth = width; }
bool shouldIndentText() const { return m_shouldIndentText == IndentText; }
private:
void computeAvailableWidthFromLeftAndRight();
+ void updateLineDimension(LayoutUnit newLineTop, LayoutUnit newLineWidth, const float& newLineLeft, const float& newLineRight);
+ void wrapNextToShapeOutside(bool isFirstLine);
RenderBlockFlow& m_block;
float m_uncommittedWidth;
float m_committedWidth;
float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
+ float m_trailingWhitespaceWidth;
float m_left;
float m_right;
float m_availableWidth;
- const LineSegment* m_segment;
bool m_isFirstLine;
IndentTextOrNot m_shouldIndentText;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RegionOversetState.h b/chromium/third_party/WebKit/Source/core/rendering/line/RenderTextInfo.h
index e29e370a20a..0ad1c598a25 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RegionOversetState.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/RenderTextInfo.h
@@ -1,4 +1,8 @@
/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
@@ -16,18 +20,28 @@
*
*/
-#ifndef RegionOversetState_h
-#define RegionOversetState_h
+#ifndef RenderTextInfo_h
+#define RenderTextInfo_h
+
+#include "platform/text/TextBreakIterator.h"
namespace WebCore {
-enum RegionOversetState {
- RegionUndefined,
- RegionEmpty,
- RegionFit,
- RegionOverset
+class Font;
+class RenderText;
+
+struct RenderTextInfo {
+ RenderTextInfo()
+ : m_text(0)
+ , m_font(0)
+ {
+ }
+
+ RenderText* m_text;
+ LazyLineBreakIterator m_lineBreakIterator;
+ const Font* m_font;
};
} // namespace WebCore
-#endif // RegionOversetState_h
+#endif // RenderTextInfo_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.cpp b/chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.cpp
new file mode 100644
index 00000000000..62c489b84b5
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2014 Adobe Systems Inc.
+ *
+ * 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"
+#include "core/rendering/line/TrailingObjects.h"
+
+#include "core/rendering/InlineIterator.h"
+
+namespace WebCore {
+
+void TrailingObjects::updateMidpointsForTrailingObjects(LineMidpointState& lineMidpointState, const InlineIterator& lBreak, CollapseFirstSpaceOrNot collapseFirstSpace)
+{
+ if (!m_whitespace)
+ return;
+
+ // This object is either going to be part of the last midpoint, or it is going to be the actual endpoint.
+ // In both cases we just decrease our pos by 1 level to exclude the space, allowing it to - in effect - collapse into the newline.
+ if (lineMidpointState.numMidpoints() % 2) {
+ // Find the trailing space object's midpoint.
+ int trailingSpaceMidpoint = lineMidpointState.numMidpoints() - 1;
+ for ( ; trailingSpaceMidpoint > 0 && lineMidpointState.midpoints()[trailingSpaceMidpoint].object() != m_whitespace; --trailingSpaceMidpoint) { }
+ ASSERT(trailingSpaceMidpoint >= 0);
+ if (collapseFirstSpace == CollapseFirstSpace)
+ lineMidpointState.midpoints()[trailingSpaceMidpoint].setOffset(lineMidpointState.midpoints()[trailingSpaceMidpoint].offset() -1);
+
+ // Now make sure every single trailingPositionedBox following the trailingSpaceMidpoint properly stops and starts
+ // ignoring spaces.
+ size_t currentMidpoint = trailingSpaceMidpoint + 1;
+ for (size_t i = 0; i < m_objects.size(); ++i) {
+ if (currentMidpoint >= lineMidpointState.numMidpoints()) {
+ // We don't have a midpoint for this box yet.
+ lineMidpointState.ensureLineBoxInsideIgnoredSpaces(m_objects[i]);
+ } else {
+ ASSERT(lineMidpointState.midpoints()[currentMidpoint].object() == m_objects[i]);
+ ASSERT(lineMidpointState.midpoints()[currentMidpoint + 1].object() == m_objects[i]);
+ }
+ currentMidpoint += 2;
+ }
+ } else if (!lBreak.object()) {
+ ASSERT(m_whitespace->isText());
+ ASSERT(collapseFirstSpace == CollapseFirstSpace);
+ // Add a new end midpoint that stops right at the very end.
+ unsigned length = m_whitespace->textLength();
+ unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
+ InlineIterator endMid(0, m_whitespace, pos);
+ lineMidpointState.startIgnoringSpaces(endMid);
+ for (size_t i = 0; i < m_objects.size(); ++i) {
+ lineMidpointState.ensureLineBoxInsideIgnoredSpaces(m_objects[i]);
+ }
+ }
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.h b/chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.h
new file mode 100644
index 00000000000..72b1369ab20
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/TrailingObjects.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2014 Adobe Systems Inc.
+ *
+ * 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 TrailingObjects_h
+#define TrailingObjects_h
+
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+class InlineIterator;
+class RenderObject;
+class RenderText;
+
+struct BidiRun;
+
+template <class Iterator, class Run> class BidiResolver;
+template <class Iterator> class MidpointState;
+typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
+typedef MidpointState<InlineIterator> LineMidpointState;
+
+// This class allows us to ensure lineboxes are created in the right place on the line when
+// an out-of-flow positioned object or an empty inline is encountered between a trailing space
+// and subsequent spaces and we want to ignore (i.e. collapse) surplus whitespace. So for example:
+// <div>X <span></span> Y</div>
+// or
+// <div>X <div style="position: absolute"></div> Y</div>
+// In both of the above snippets the inline and the positioned object occur after a trailing space
+// and before a space that will cause our line breaking algorithm to start ignoring spaces. When it
+// does that we want to ensure that the inline/positioned object gets a linebox and that it is part
+// of the collapsed whitespace. So to achieve this we use appendObjectIfNeeded() to keep track of
+// objects encountered after a trailing whitespace and updateMidpointsForTrailingObjects() to put
+// them in the right place when we start ignoring surplus whitespace.
+
+class TrailingObjects {
+public:
+ TrailingObjects()
+ : m_whitespace(0)
+ {
+ }
+
+ void setTrailingWhitespace(RenderText* whitespace)
+ {
+ ASSERT(whitespace);
+ m_whitespace = whitespace;
+ }
+
+ void clear()
+ {
+ m_whitespace = 0;
+ // Using resize(0) rather than clear() here saves 2% on
+ // PerformanceTests/Layout/line-layout.html because we avoid freeing and
+ // re-allocating the underlying buffer repeatedly.
+ m_objects.resize(0);
+ }
+
+ void appendObjectIfNeeded(RenderObject* object)
+ {
+ if (m_whitespace)
+ m_objects.append(object);
+ }
+
+ enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace };
+
+ void updateMidpointsForTrailingObjects(LineMidpointState&, const InlineIterator& lBreak, CollapseFirstSpaceOrNot);
+
+private:
+ RenderText* m_whitespace;
+ Vector<RenderObject*, 4> m_objects;
+};
+
+}
+
+#endif // TrailingObjects_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/line/WordMeasurement.h b/chromium/third_party/WebKit/Source/core/rendering/line/WordMeasurement.h
new file mode 100644
index 00000000000..46803dd0c56
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/line/WordMeasurement.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Adobe Systems Incorporated.
+ *
+ * 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 WordMeasurement_h
+#define WordMeasurement_h
+
+#include "platform/fonts/SimpleFontData.h"
+#include "wtf/HashSet.h"
+
+namespace WebCore {
+
+class RenderText;
+
+class WordMeasurement {
+public:
+ WordMeasurement()
+ : renderer(0)
+ , width(0)
+ , startOffset(0)
+ , endOffset(0)
+ {
+ }
+
+ RenderText* renderer;
+ float width;
+ int startOffset;
+ int endOffset;
+ HashSet<const SimpleFontData*> fallbackFonts;
+};
+
+} // namespace WebCore
+
+#endif // WordMeasurement_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp
index 86c9136ac90..bba80270c55 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp
@@ -42,14 +42,6 @@ LayoutRect BoxShape::shapeMarginLogicalBoundingBox() const
return static_cast<LayoutRect>(marginBounds);
}
-LayoutRect BoxShape::shapePaddingLogicalBoundingBox() const
-{
- FloatRect paddingBounds(m_bounds.rect());
- if (shapePadding() > 0)
- paddingBounds.inflate(-shapePadding());
- return static_cast<LayoutRect>(paddingBounds);
-}
-
FloatRoundedRect BoxShape::shapeMarginBounds() const
{
FloatRoundedRect marginBounds(m_bounds);
@@ -60,24 +52,14 @@ FloatRoundedRect BoxShape::shapeMarginBounds() const
return marginBounds;
}
-FloatRoundedRect BoxShape::shapePaddingBounds() const
-{
- FloatRoundedRect paddingBounds(m_bounds);
- if (shapePadding() > 0) {
- paddingBounds.inflate(-shapePadding());
- paddingBounds.expandRadii(-shapePadding());
- }
- return paddingBounds;
-}
-
void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
const FloatRoundedRect& marginBounds = shapeMarginBounds();
if (marginBounds.isEmpty() || !lineOverlapsShapeMarginBounds(logicalTop, logicalHeight))
return;
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
+ float y1 = logicalTop.toFloat();
+ float y2 = (logicalTop + logicalHeight).toFloat();
const FloatRect& rect = marginBounds.rect();
if (!marginBounds.isRounded()) {
@@ -85,11 +67,25 @@ void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHei
return;
}
+ float topCornerMaxY = std::max<float>(marginBounds.topLeftCorner().maxY(), marginBounds.topRightCorner().maxY());
+ float bottomCornerMinY = std::min<float>(marginBounds.bottomLeftCorner().y(), marginBounds.bottomRightCorner().y());
+
+ if (topCornerMaxY <= bottomCornerMinY && y1 <= topCornerMaxY && y2 >= bottomCornerMinY) {
+ result.append(LineSegment(rect.x(), rect.maxX()));
+ return;
+ }
+
float x1 = rect.maxX();
float x2 = rect.x();
float minXIntercept;
float maxXIntercept;
+ if (y1 <= marginBounds.topLeftCorner().maxY() && y2 >= marginBounds.bottomLeftCorner().y())
+ x1 = rect.x();
+
+ if (y1 <= marginBounds.topRightCorner().maxY() && y2 >= marginBounds.bottomRightCorner().y())
+ x2 = rect.maxX();
+
if (marginBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) {
x1 = std::min<float>(x1, minXIntercept);
x2 = std::max<float>(x2, maxXIntercept);
@@ -104,27 +100,11 @@ void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHei
result.append(LineSegment(x1, x2));
}
-void BoxShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+void BoxShape::buildDisplayPaths(DisplayPaths& paths) const
{
- const FloatRoundedRect& paddingBounds = shapePaddingBounds();
- if (paddingBounds.isEmpty())
- return;
-
- const FloatRect& rect = paddingBounds.rect();
- if (logicalTop < rect.y() || logicalTop + logicalHeight > rect.maxY())
- return;
-
- // FIXME: this method is only a stub, https://bugs.webkit.org/show_bug.cgi?id=124605.
-
- result.append(LineSegment(rect.x(), rect.maxX()));
-}
-
-bool BoxShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize&, LayoutUnit& result) const
-{
- // FIXME: this method is only a stub, https://bugs.webkit.org/show_bug.cgi?id=124606.
-
- result = minLogicalIntervalTop;
- return true;
+ paths.shape.addRoundedRect(m_bounds.rect(), m_bounds.radii().topLeft(), m_bounds.radii().topRight(), m_bounds.radii().bottomLeft(), m_bounds.radii().bottomRight());
+ if (shapeMargin())
+ paths.marginShape.addRoundedRect(shapeMarginBounds().rect(), shapeMarginBounds().radii().topLeft(), shapeMarginBounds().radii().topRight(), shapeMarginBounds().radii().bottomLeft(), shapeMarginBounds().radii().bottomRight());
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h
index 823187a7ca9..06a51489615 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h
@@ -35,7 +35,7 @@
namespace WebCore {
-class BoxShape : public Shape {
+class BoxShape FINAL : public Shape {
public:
BoxShape(const FloatRoundedRect& bounds)
: Shape()
@@ -44,15 +44,12 @@ public:
}
virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE;
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE;
virtual bool isEmpty() const OVERRIDE { return m_bounds.isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths&) const OVERRIDE;
private:
FloatRoundedRect shapeMarginBounds() const;
- FloatRoundedRect shapePaddingBounds() const;
FloatRoundedRect m_bounds;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp
index 9b1f50193f1..74538f391fd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp
@@ -31,6 +31,8 @@
#include "core/rendering/shapes/BoxShape.h"
+#include "platform/geometry/RoundedRect.h"
+
#include <gtest/gtest.h>
namespace WebCore {
@@ -39,9 +41,9 @@ class BoxShapeTest : public ::testing::Test {
protected:
BoxShapeTest() { }
- PassOwnPtr<Shape> createBoxShape(const LayoutSize& size, float shapeMargin, float shapePadding)
+ PassOwnPtr<Shape> createBoxShape(const RoundedRect& bounds, float shapeMargin)
{
- return Shape::createLayoutBoxShape(size, TopToBottomWritingMode, Length(shapeMargin, Fixed), Length(shapePadding, Fixed));
+ return Shape::createLayoutBoxShape(bounds, TopToBottomWritingMode, shapeMargin);
}
};
@@ -56,8 +58,10 @@ using namespace WebCore;
SegmentList result; \
shapePtr->getExcludedIntervals(lineTop, lineHeight, result); \
EXPECT_EQ(1u, result.size()); \
- EXPECT_EQ(expectedLeft, result[0].logicalLeft); \
- EXPECT_EQ(expectedRight, result[0].logicalRight); \
+ if (result.size() == 1u) { \
+ EXPECT_FLOAT_EQ(expectedLeft, result[0].logicalLeft); \
+ EXPECT_FLOAT_EQ(expectedRight, result[0].logicalRight); \
+ } \
}
#define TEST_NO_EXCLUDED_INTERVAL(shapePtr, lineTop, lineHeight) \
@@ -67,13 +71,21 @@ using namespace WebCore;
EXPECT_EQ(0u, result.size()); \
}
+/* The BoxShape is based on a 100x50 rectangle at 0,0. The shape-margin value is 10,
+ * so the shapeMarginBoundingBox rectangle is 120x70 at -10,-10:
+ *
+ * -10,-10 110,-10
+ * +--------+
+ * | |
+ * +--------+
+ * -10,60 60,60
+ */
TEST_F(BoxShapeTest, zeroRadii)
{
- OwnPtr<Shape> shape = createBoxShape(LayoutSize(100, 50), 10, 20);
+ OwnPtr<Shape> shape = createBoxShape(RoundedRect(0, 0, 100, 50), 10);
EXPECT_FALSE(shape->isEmpty());
EXPECT_EQ(LayoutRect(-10, -10, 120, 70), shape->shapeMarginLogicalBoundingBox());
- EXPECT_EQ(LayoutRect(20, 20, 60, 10), shape->shapePaddingLogicalBoundingBox());
// A BoxShape's bounds include the top edge but not the bottom edge.
// Similarly a "line", specified as top,height to the overlap methods,
@@ -98,16 +110,34 @@ TEST_F(BoxShapeTest, zeroRadii)
TEST_NO_EXCLUDED_INTERVAL(shape, -12, 2);
TEST_NO_EXCLUDED_INTERVAL(shape, 60, 1);
TEST_NO_EXCLUDED_INTERVAL(shape, 100, 200);
+}
+
+/* BoxShape geometry for this test. Corner radii are in parens, x and y intercepts
+ * for the elliptical corners are noted. The rectangle itself is at 0,0 with width and height 100.
+ *
+ * (10, 15) x=10 x=90 (10, 20)
+ * (--+---------+--)
+ * y=15 +--| |-+ y=20
+ * | |
+ * | |
+ * y=85 + -| |- + y=70
+ * (--+---------+--)
+ * (25, 15) x=25 x=80 (20, 30)
+ */
+TEST_F(BoxShapeTest, getIntervals)
+{
+ const RoundedRect::Radii cornerRadii(IntSize(10, 15), IntSize(10, 20), IntSize(25, 15), IntSize(20, 30));
+ OwnPtr<Shape> shape = createBoxShape(RoundedRect(IntRect(0, 0, 100, 100), cornerRadii), 0);
+ EXPECT_FALSE(shape->isEmpty());
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(21, 1));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(20, 0));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(-10, 200));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(25, 35));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(29, 1));
+ EXPECT_EQ(LayoutRect(0, 0, 100, 100), shape->shapeMarginLogicalBoundingBox());
- EXPECT_FALSE(shape->lineOverlapsShapePaddingBounds(18, 2));
- EXPECT_FALSE(shape->lineOverlapsShapePaddingBounds(30, 1));
- EXPECT_FALSE(shape->lineOverlapsShapePaddingBounds(100, 200));
+ TEST_EXCLUDED_INTERVAL(shape, 10, 95, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 5, 25, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 15, 6, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 20, 50, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 69, 5, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 85, 10, 0, 97.320511f);
}
} // namespace
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp
index 26ddcf3606b..98cd8367e1e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp
@@ -30,70 +30,11 @@
#include "config.h"
#include "core/rendering/shapes/PolygonShape.h"
-#include "core/rendering/shapes/ShapeInterval.h"
#include "platform/geometry/LayoutPoint.h"
#include "wtf/MathExtras.h"
namespace WebCore {
-enum EdgeIntersectionType {
- Normal,
- VertexMinY,
- VertexMaxY,
- VertexYBoth
-};
-
-struct EdgeIntersection {
- const FloatPolygonEdge* edge;
- FloatPoint point;
- EdgeIntersectionType type;
-};
-
-static inline float leftSide(const FloatPoint& vertex1, const FloatPoint& vertex2, const FloatPoint& point)
-{
- return ((point.x() - vertex1.x()) * (vertex2.y() - vertex1.y())) - ((vertex2.x() - vertex1.x()) * (point.y() - vertex1.y()));
-}
-
-static inline bool isReflexVertex(const FloatPoint& prevVertex, const FloatPoint& vertex, const FloatPoint& nextVertex)
-{
- return leftSide(prevVertex, nextVertex, vertex) < 0;
-}
-
-static bool computeXIntersection(const FloatPolygonEdge* edgePointer, float y, EdgeIntersection& result)
-{
- const FloatPolygonEdge& edge = *edgePointer;
-
- if (edge.minY() > y || edge.maxY() < y)
- return false;
-
- const FloatPoint& vertex1 = edge.vertex1();
- const FloatPoint& vertex2 = edge.vertex2();
- float dy = vertex2.y() - vertex1.y();
-
- float intersectionX;
- EdgeIntersectionType intersectionType;
-
- if (!dy) {
- intersectionType = VertexYBoth;
- intersectionX = edge.minX();
- } else if (y == edge.minY()) {
- intersectionType = VertexMinY;
- intersectionX = (vertex1.y() < vertex2.y()) ? vertex1.x() : vertex2.x();
- } else if (y == edge.maxY()) {
- intersectionType = VertexMaxY;
- intersectionX = (vertex1.y() > vertex2.y()) ? vertex1.x() : vertex2.x();
- } else {
- intersectionType = Normal;
- intersectionX = ((y - vertex1.y()) * (vertex2.x() - vertex1.x()) / dy) + vertex1.x();
- }
-
- result.edge = edgePointer;
- result.type = intersectionType;
- result.point.set(intersectionX, y);
-
- return true;
-}
-
static inline FloatSize inwardEdgeNormal(const FloatPolygonEdge& edge)
{
FloatSize edgeDelta = edge.vertex2() - edge.vertex1();
@@ -110,422 +51,113 @@ static inline FloatSize outwardEdgeNormal(const FloatPolygonEdge& edge)
return -inwardEdgeNormal(edge);
}
-static inline void appendArc(Vector<FloatPoint>& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex, bool padding)
-{
- float startAngle = atan2(startArcVertex.y() - arcCenter.y(), startArcVertex.x() - arcCenter.x());
- float endAngle = atan2(endArcVertex.y() - arcCenter.y(), endArcVertex.x() - arcCenter.x());
- const float twoPI = piFloat * 2;
- if (startAngle < 0)
- startAngle += twoPI;
- if (endAngle < 0)
- endAngle += twoPI;
- float angle = (startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + twoPI - endAngle);
- const float arcSegmentCount = 6; // An even number so that one arc vertex will be eactly arcRadius from arcCenter.
- float arcSegmentAngle = ((padding) ? -angle : twoPI - angle) / arcSegmentCount;
-
- vertices.append(startArcVertex);
- for (unsigned i = 1; i < arcSegmentCount; ++i) {
- float angle = startAngle + arcSegmentAngle * i;
- vertices.append(arcCenter + FloatPoint(cos(angle) * arcRadius, sin(angle) * arcRadius));
- }
- vertices.append(endArcVertex);
-}
-
-static inline void snapVerticesToLayoutUnitGrid(Vector<FloatPoint>& vertices)
-{
- for (unsigned i = 0; i < vertices.size(); ++i)
- vertices[i] = flooredLayoutPoint(vertices[i]);
-}
-
-static inline PassOwnPtr<FloatPolygon> computeShapePaddingBounds(const FloatPolygon& polygon, float padding, WindRule fillRule)
-{
- OwnPtr<Vector<FloatPoint> > paddedVertices = adoptPtr(new Vector<FloatPoint>());
- FloatPoint intersection;
-
- for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) {
- const FloatPolygonEdge& thisEdge = polygon.edgeAt(i);
- const FloatPolygonEdge& prevEdge = thisEdge.previousEdge();
- OffsetPolygonEdge thisOffsetEdge(thisEdge, inwardEdgeNormal(thisEdge) * padding);
- OffsetPolygonEdge prevOffsetEdge(prevEdge, inwardEdgeNormal(prevEdge) * padding);
-
- if (prevOffsetEdge.intersection(thisOffsetEdge, intersection))
- paddedVertices->append(intersection);
- else if (isReflexVertex(prevEdge.vertex1(), thisEdge.vertex1(), thisEdge.vertex2()))
- appendArc(*paddedVertices, thisEdge.vertex1(), padding, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), true);
- }
-
- snapVerticesToLayoutUnitGrid(*paddedVertices);
- return adoptPtr(new FloatPolygon(paddedVertices.release(), fillRule));
-}
-
-static inline PassOwnPtr<FloatPolygon> computeShapeMarginBounds(const FloatPolygon& polygon, float margin, WindRule fillRule)
-{
- OwnPtr<Vector<FloatPoint> > marginVertices = adoptPtr(new Vector<FloatPoint>());
- FloatPoint intersection;
-
- for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) {
- const FloatPolygonEdge& thisEdge = polygon.edgeAt(i);
- const FloatPolygonEdge& prevEdge = thisEdge.previousEdge();
- OffsetPolygonEdge thisOffsetEdge(thisEdge, outwardEdgeNormal(thisEdge) * margin);
- OffsetPolygonEdge prevOffsetEdge(prevEdge, outwardEdgeNormal(prevEdge) * margin);
-
- if (prevOffsetEdge.intersection(thisOffsetEdge, intersection))
- marginVertices->append(intersection);
- else
- appendArc(*marginVertices, thisEdge.vertex1(), margin, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), false);
- }
-
- snapVerticesToLayoutUnitGrid(*marginVertices);
- return adoptPtr(new FloatPolygon(marginVertices.release(), fillRule));
-}
+static inline bool overlapsYRange(const FloatRect& rect, float y1, float y2) { return !rect.isEmpty() && y2 >= y1 && y2 >= rect.y() && y1 <= rect.maxY(); }
-const FloatPolygon& PolygonShape::shapePaddingBounds() const
+float OffsetPolygonEdge::xIntercept(float y) const
{
- ASSERT(shapePadding() >= 0);
- if (!shapePadding() || m_polygon.isEmpty())
- return m_polygon;
+ ASSERT(y >= minY() && y <= maxY());
- if (!m_paddingBounds)
- m_paddingBounds = computeShapePaddingBounds(m_polygon, shapePadding(), m_polygon.fillRule());
+ if (vertex1().y() == vertex2().y() || vertex1().x() == vertex2().x())
+ return minX();
+ if (y == minY())
+ return vertex1().y() < vertex2().y() ? vertex1().x() : vertex2().x();
+ if (y == maxY())
+ return vertex1().y() > vertex2().y() ? vertex1().x() : vertex2().x();
- return *m_paddingBounds;
+ return vertex1().x() + ((y - vertex1().y()) * (vertex2().x() - vertex1().x()) / (vertex2().y() - vertex1().y()));
}
-const FloatPolygon& PolygonShape::shapeMarginBounds() const
+FloatShapeInterval OffsetPolygonEdge::clippedEdgeXRange(float y1, float y2) const
{
- ASSERT(shapeMargin() >= 0);
- if (!shapeMargin() || m_polygon.isEmpty())
- return m_polygon;
+ if (!overlapsYRange(y1, y2) || (y1 == maxY() && minY() <= y1) || (y2 == minY() && maxY() >= y2))
+ return FloatShapeInterval();
- if (!m_marginBounds)
- m_marginBounds = computeShapeMarginBounds(m_polygon, shapeMargin(), m_polygon.fillRule());
+ if (isWithinYRange(y1, y2))
+ return FloatShapeInterval(minX(), maxX());
- return *m_marginBounds;
-}
-
-static inline bool getVertexIntersectionVertices(const EdgeIntersection& intersection, FloatPoint& prevVertex, FloatPoint& thisVertex, FloatPoint& nextVertex)
-{
- if (intersection.type != VertexMinY && intersection.type != VertexMaxY)
- return false;
-
- ASSERT(intersection.edge && intersection.edge->polygon());
- const FloatPolygon& polygon = *(intersection.edge->polygon());
- const FloatPolygonEdge& thisEdge = *(intersection.edge);
+ // Clip the edge line segment to the vertical range y1,y2 and then return
+ // the clipped line segment's horizontal range.
- if ((intersection.type == VertexMinY && (thisEdge.vertex1().y() < thisEdge.vertex2().y()))
- || (intersection.type == VertexMaxY && (thisEdge.vertex1().y() > thisEdge.vertex2().y()))) {
- prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex1());
- thisVertex = polygon.vertexAt(thisEdge.vertexIndex1());
- nextVertex = polygon.vertexAt(thisEdge.vertexIndex2());
+ FloatPoint minYVertex;
+ FloatPoint maxYVertex;
+ if (vertex1().y() < vertex2().y()) {
+ minYVertex = vertex1();
+ maxYVertex = vertex2();
} else {
- prevVertex = polygon.vertexAt(thisEdge.vertexIndex1());
- thisVertex = polygon.vertexAt(thisEdge.vertexIndex2());
- nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex2());
+ minYVertex = vertex2();
+ maxYVertex = vertex1();
}
-
- return true;
-}
-
-static inline bool appendIntervalX(float x, bool inside, FloatShapeIntervals& result)
-{
- if (!inside)
- result.append(FloatShapeInterval(x, x));
- else
- result.last().setX2(x);
-
- return !inside;
+ float xForY1 = (minYVertex.y() < y1) ? xIntercept(y1) : minYVertex.x();
+ float xForY2 = (maxYVertex.y() > y2) ? xIntercept(y2) : maxYVertex.x();
+ return FloatShapeInterval(std::min(xForY1, xForY2), std::max(xForY1, xForY2));
}
-static bool compareEdgeIntersectionX(const EdgeIntersection& intersection1, const EdgeIntersection& intersection2)
+static float circleXIntercept(float y, float radius)
{
- float x1 = intersection1.point.x();
- float x2 = intersection2.point.x();
- return (x1 == x2) ? intersection1.type < intersection2.type : x1 < x2;
+ ASSERT(radius > 0);
+ return radius * sqrt(1 - (y * y) / (radius * radius));
}
-static void computeXIntersections(const FloatPolygon& polygon, float y, bool isMinY, FloatShapeIntervals& result)
+static FloatShapeInterval clippedCircleXRange(const FloatPoint& center, float radius, float y1, float y2)
{
- Vector<const FloatPolygonEdge*> edges;
- if (!polygon.overlappingEdges(y, y, edges))
- return;
-
- Vector<EdgeIntersection> intersections;
- EdgeIntersection intersection;
- for (unsigned i = 0; i < edges.size(); ++i) {
- if (computeXIntersection(edges[i], y, intersection) && intersection.type != VertexYBoth)
- intersections.append(intersection);
- }
-
- if (intersections.size() < 2)
- return;
-
- std::sort(intersections.begin(), intersections.end(), WebCore::compareEdgeIntersectionX);
-
- unsigned index = 0;
- int windCount = 0;
- bool inside = false;
+ if (y1 > center.y() + radius || y2 < center.y() - radius)
+ return FloatShapeInterval();
- while (index < intersections.size()) {
- const EdgeIntersection& thisIntersection = intersections[index];
- if (index + 1 < intersections.size()) {
- const EdgeIntersection& nextIntersection = intersections[index + 1];
- if ((thisIntersection.point.x() == nextIntersection.point.x()) && (thisIntersection.type == VertexMinY || thisIntersection.type == VertexMaxY)) {
- if (thisIntersection.type == nextIntersection.type) {
- // Skip pairs of intersections whose types are VertexMaxY,VertexMaxY and VertexMinY,VertexMinY.
- index += 2;
- } else {
- // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one intersection.
- ++index;
- }
- continue;
- }
- }
-
- bool edgeCrossing = thisIntersection.type == Normal;
- if (!edgeCrossing) {
- FloatPoint prevVertex;
- FloatPoint thisVertex;
- FloatPoint nextVertex;
-
- if (getVertexIntersectionVertices(thisIntersection, prevVertex, thisVertex, nextVertex)) {
- if (nextVertex.y() == y)
- edgeCrossing = (isMinY) ? prevVertex.y() > y : prevVertex.y() < y;
- else if (prevVertex.y() == y)
- edgeCrossing = (isMinY) ? nextVertex.y() > y : nextVertex.y() < y;
- else
- edgeCrossing = true;
- }
- }
+ if (center.y() >= y1 && center.y() <= y2)
+ return FloatShapeInterval(center.x() - radius, center.x() + radius);
- if (edgeCrossing && polygon.fillRule() == RULE_NONZERO) {
- const FloatPolygonEdge& thisEdge = *thisIntersection.edge;
- windCount += (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? 1 : -1;
- }
-
- if (edgeCrossing && (!inside || !windCount))
- inside = appendIntervalX(thisIntersection.point.x(), inside, result);
+ // Clip the circle to the vertical range y1,y2 and return the extent of the clipped circle's
+ // projection on the X axis
- ++index;
- }
+ float xi = circleXIntercept((y2 < center.y() ? y2 : y1) - center.y(), radius);
+ return FloatShapeInterval(center.x() - xi, center.x() + xi);
}
-static bool compareX1(const FloatShapeInterval a, const FloatShapeInterval& b) { return a.x1() < b.x1(); }
-
-static void sortAndMergeShapeIntervals(FloatShapeIntervals& intervals)
+LayoutRect PolygonShape::shapeMarginLogicalBoundingBox() const
{
- std::sort(intervals.begin(), intervals.end(), compareX1);
-
- for (unsigned i = 1; i < intervals.size(); ) {
- const FloatShapeInterval& thisInterval = intervals[i];
- FloatShapeInterval& previousInterval = intervals[i - 1];
- if (thisInterval.overlaps(previousInterval)) {
- previousInterval.setX2(std::max<float>(previousInterval.x2(), thisInterval.x2()));
- intervals.remove(i);
- } else {
- ++i;
- }
- }
+ FloatRect box = m_polygon.boundingBox();
+ box.inflate(shapeMargin());
+ return LayoutRect(box);
}
-static void computeOverlappingEdgeXProjections(const FloatPolygon& polygon, float y1, float y2, FloatShapeIntervals& result)
+void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
- Vector<const FloatPolygonEdge*> edges;
- if (!polygon.overlappingEdges(y1, y2, edges))
- return;
+ float y1 = logicalTop.toFloat();
+ float y2 = logicalTop.toFloat() + logicalHeight.toFloat();
- EdgeIntersection intersection;
- for (unsigned i = 0; i < edges.size(); ++i) {
- const FloatPolygonEdge *edge = edges[i];
- float x1;
- float x2;
+ if (m_polygon.isEmpty() || !overlapsYRange(m_polygon.boundingBox(), y1 - shapeMargin(), y2 + shapeMargin()))
+ return;
- if (edge->minY() < y1) {
- computeXIntersection(edge, y1, intersection);
- x1 = intersection.point.x();
- } else {
- x1 = (edge->vertex1().y() < edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
- }
+ Vector<const FloatPolygonEdge*> overlappingEdges;
+ if (!m_polygon.overlappingEdges(y1 - shapeMargin(), y2 + shapeMargin(), overlappingEdges))
+ return;
- if (edge->maxY() > y2) {
- computeXIntersection(edge, y2, intersection);
- x2 = intersection.point.x();
+ FloatShapeInterval excludedInterval;
+ for (unsigned i = 0; i < overlappingEdges.size(); i++) {
+ const FloatPolygonEdge& edge = *(overlappingEdges[i]);
+ if (edge.maxY() == edge.minY())
+ continue;
+ if (!shapeMargin()) {
+ excludedInterval.unite(OffsetPolygonEdge(edge, FloatSize()).clippedEdgeXRange(y1, y2));
} else {
- x2 = (edge->vertex1().y() > edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
+ excludedInterval.unite(OffsetPolygonEdge(edge, outwardEdgeNormal(edge) * shapeMargin()).clippedEdgeXRange(y1, y2));
+ excludedInterval.unite(OffsetPolygonEdge(edge, inwardEdgeNormal(edge) * shapeMargin()).clippedEdgeXRange(y1, y2));
+ excludedInterval.unite(clippedCircleXRange(edge.vertex1(), shapeMargin(), y1, y2));
}
-
- if (x1 > x2)
- std::swap(x1, x2);
-
- if (x2 > x1)
- result.append(FloatShapeInterval(x1, x2));
}
- sortAndMergeShapeIntervals(result);
-}
-
-void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
-{
- const FloatPolygon& polygon = shapeMarginBounds();
- if (polygon.isEmpty())
- return;
-
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
-
- FloatShapeIntervals y1XIntervals, y2XIntervals;
- computeXIntersections(polygon, y1, true, y1XIntervals);
- computeXIntersections(polygon, y2, false, y2XIntervals);
-
- FloatShapeIntervals mergedIntervals;
- FloatShapeInterval::uniteShapeIntervals(y1XIntervals, y2XIntervals, mergedIntervals);
-
- FloatShapeIntervals edgeIntervals;
- computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
-
- FloatShapeIntervals excludedIntervals;
- FloatShapeInterval::uniteShapeIntervals(mergedIntervals, edgeIntervals, excludedIntervals);
-
- for (unsigned i = 0; i < excludedIntervals.size(); ++i) {
- const FloatShapeInterval& interval = excludedIntervals[i];
- result.append(LineSegment(interval.x1(), interval.x2()));
- }
+ if (!excludedInterval.isEmpty())
+ result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2()));
}
-void PolygonShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+void PolygonShape::buildDisplayPaths(DisplayPaths& paths) const
{
- const FloatPolygon& polygon = shapePaddingBounds();
- if (polygon.isEmpty())
+ if (!m_polygon.numberOfVertices())
return;
-
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
-
- FloatShapeIntervals y1XIntervals, y2XIntervals;
- computeXIntersections(polygon, y1, true, y1XIntervals);
- computeXIntersections(polygon, y2, false, y2XIntervals);
-
- FloatShapeIntervals commonIntervals;
- FloatShapeInterval::intersectShapeIntervals(y1XIntervals, y2XIntervals, commonIntervals);
-
- FloatShapeIntervals edgeIntervals;
- computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
-
- FloatShapeIntervals includedIntervals;
- FloatShapeInterval::subtractShapeIntervals(commonIntervals, edgeIntervals, includedIntervals);
-
- for (unsigned i = 0; i < includedIntervals.size(); ++i) {
- const FloatShapeInterval& interval = includedIntervals[i];
- result.append(LineSegment(interval.x1(), interval.x2()));
- }
-}
-
-static inline bool firstFitRectInPolygon(const FloatPolygon& polygon, const FloatRect& rect, unsigned offsetEdgeIndex1, unsigned offsetEdgeIndex2)
-{
- Vector<const FloatPolygonEdge*> edges;
- if (!polygon.overlappingEdges(rect.y(), rect.maxY(), edges))
- return true;
-
- for (unsigned i = 0; i < edges.size(); ++i) {
- const FloatPolygonEdge* edge = edges[i];
- if (edge->edgeIndex() != offsetEdgeIndex1 && edge->edgeIndex() != offsetEdgeIndex2 && edge->overlapsRect(rect))
- return false;
- }
-
- return true;
-}
-
-static inline bool aboveOrToTheLeft(const FloatRect& r1, const FloatRect& r2)
-{
- if (r1.y() < r2.y())
- return true;
- if (r1.y() == r2.y())
- return r1.x() < r2.x();
- return false;
-}
-
-bool PolygonShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
- float minIntervalTop = minLogicalIntervalTop;
- float minIntervalHeight = minLogicalIntervalSize.height();
- float minIntervalWidth = minLogicalIntervalSize.width();
-
- const FloatPolygon& polygon = shapePaddingBounds();
- const FloatRect boundingBox = polygon.boundingBox();
- if (minIntervalWidth > boundingBox.width())
- return false;
-
- float minY = std::max(boundingBox.y(), minIntervalTop);
- float maxY = minY + minIntervalHeight;
-
- if (maxY > boundingBox.maxY())
- return false;
-
- Vector<const FloatPolygonEdge*> edges;
- polygon.overlappingEdges(minIntervalTop, boundingBox.maxY(), edges);
-
- float dx = minIntervalWidth / 2;
- float dy = minIntervalHeight / 2;
- Vector<OffsetPolygonEdge> offsetEdges;
-
- for (unsigned i = 0; i < edges.size(); ++i) {
- const FloatPolygonEdge& edge = *(edges[i]);
- const FloatPoint& vertex0 = edge.previousEdge().vertex1();
- const FloatPoint& vertex1 = edge.vertex1();
- const FloatPoint& vertex2 = edge.vertex2();
- Vector<OffsetPolygonEdge> offsetEdgeBuffer;
-
- if (vertex2.y() > vertex1.y() ? vertex2.x() >= vertex1.x() : vertex1.x() >= vertex2.x()) {
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(dx, -dy)));
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(-dx, dy)));
- } else {
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(dx, dy)));
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(-dx, -dy)));
- }
-
- if (isReflexVertex(vertex0, vertex1, vertex2)) {
- if (vertex2.x() <= vertex1.x() && vertex0.x() <= vertex1.x())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(dx, -dy), FloatSize(dx, dy)));
- else if (vertex2.x() >= vertex1.x() && vertex0.x() >= vertex1.x())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, -dy), FloatSize(-dx, dy)));
- if (vertex2.y() <= vertex1.y() && vertex0.y() <= vertex1.y())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, dy), FloatSize(dx, dy)));
- else if (vertex2.y() >= vertex1.y() && vertex0.y() >= vertex1.y())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, -dy), FloatSize(dx, -dy)));
- }
-
- for (unsigned j = 0; j < offsetEdgeBuffer.size(); ++j) {
- if (offsetEdgeBuffer[j].maxY() >= minY)
- offsetEdges.append(offsetEdgeBuffer[j]);
- }
- }
-
- offsetEdges.append(OffsetPolygonEdge(polygon, minIntervalTop, FloatSize(0, dy)));
-
- FloatPoint offsetEdgesIntersection;
- FloatRect firstFitRect;
- bool firstFitFound = false;
-
- for (unsigned i = 0; i < offsetEdges.size() - 1; ++i) {
- for (unsigned j = i + 1; j < offsetEdges.size(); ++j) {
- if (offsetEdges[i].intersection(offsetEdges[j], offsetEdgesIntersection)) {
- FloatPoint potentialFirstFitLocation(offsetEdgesIntersection.x() - dx, offsetEdgesIntersection.y() - dy);
- FloatRect potentialFirstFitRect(potentialFirstFitLocation, minLogicalIntervalSize);
- if ((offsetEdges[i].basis() == OffsetPolygonEdge::LineTop
- || offsetEdges[j].basis() == OffsetPolygonEdge::LineTop
- || potentialFirstFitLocation.y() >= minIntervalTop)
- && (!firstFitFound || aboveOrToTheLeft(potentialFirstFitRect, firstFitRect))
- && polygon.contains(offsetEdgesIntersection)
- && firstFitRectInPolygon(polygon, potentialFirstFitRect, offsetEdges[i].edgeIndex(), offsetEdges[j].edgeIndex())) {
- firstFitFound = true;
- firstFitRect = potentialFirstFitRect;
- }
- }
- }
- }
-
- if (firstFitFound)
- result = LayoutUnit::fromFloatCeil(firstFitRect.y());
- return firstFitFound;
+ paths.shape.moveTo(m_polygon.vertexAt(0));
+ for (size_t i = 1; i < m_polygon.numberOfVertices(); ++i)
+ paths.shape.addLineTo(m_polygon.vertexAt(i));
+ paths.shape.closeSubpath();
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h
index 38b0d8e75c7..f7171c929f4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h
@@ -31,79 +31,48 @@
#define PolygonShape_h
#include "core/rendering/shapes/Shape.h"
+#include "core/rendering/shapes/ShapeInterval.h"
#include "platform/geometry/FloatPolygon.h"
namespace WebCore {
-class OffsetPolygonEdge : public VertexPair {
+class OffsetPolygonEdge FINAL : public VertexPair {
public:
- enum Basis {
- Edge,
- Vertex,
- LineTop
- };
-
OffsetPolygonEdge(const FloatPolygonEdge& edge, const FloatSize& offset)
: m_vertex1(edge.vertex1() + offset)
, m_vertex2(edge.vertex2() + offset)
- , m_edgeIndex(edge.edgeIndex())
- , m_basis(Edge)
- {
- }
-
- OffsetPolygonEdge(const FloatPoint& reflexVertex, const FloatSize& offset1, const FloatSize& offset2)
- : m_vertex1(reflexVertex + offset1)
- , m_vertex2(reflexVertex + offset2)
- , m_edgeIndex(-1)
- , m_basis(Vertex)
- {
- }
-
- OffsetPolygonEdge(const FloatPolygon& polygon, float minLogicalIntervalTop, const FloatSize& offset)
- : m_vertex1(FloatPoint(polygon.boundingBox().x(), minLogicalIntervalTop) + offset)
- , m_vertex2(FloatPoint(polygon.boundingBox().maxX(), minLogicalIntervalTop) + offset)
- , m_edgeIndex(-1)
- , m_basis(LineTop)
{
}
virtual const FloatPoint& vertex1() const OVERRIDE { return m_vertex1; }
virtual const FloatPoint& vertex2() const OVERRIDE { return m_vertex2; }
- int edgeIndex() const { return m_edgeIndex; }
- Basis basis() const { return m_basis; }
+
+ bool isWithinYRange(float y1, float y2) const { return y1 <= minY() && y2 >= maxY(); }
+ bool overlapsYRange(float y1, float y2) const { return y2 >= minY() && y1 <= maxY(); }
+ float xIntercept(float y) const;
+ FloatShapeInterval clippedEdgeXRange(float y1, float y2) const;
private:
FloatPoint m_vertex1;
FloatPoint m_vertex2;
- int m_edgeIndex;
- Basis m_basis;
};
-class PolygonShape : public Shape {
+class PolygonShape FINAL : public Shape {
WTF_MAKE_NONCOPYABLE(PolygonShape);
public:
PolygonShape(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
: Shape()
, m_polygon(vertices, fillRule)
- , m_marginBounds(nullptr)
- , m_paddingBounds(nullptr)
{
}
- virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapeMarginBounds().boundingBox()); }
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapePaddingBounds().boundingBox()); }
+ virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE;
virtual bool isEmpty() const OVERRIDE { return m_polygon.isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths&) const OVERRIDE;
private:
- const FloatPolygon& shapeMarginBounds() const;
- const FloatPolygon& shapePaddingBounds() const;
-
FloatPolygon m_polygon;
- mutable OwnPtr<FloatPolygon> m_marginBounds;
- mutable OwnPtr<FloatPolygon> m_paddingBounds;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp
index 78b00211519..8dda343bc66 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp
@@ -73,182 +73,67 @@ IntShapeInterval MarginIntervalGenerator::intervalAt(int y) const
return IntShapeInterval(m_x1 - dx, m_x2 + dx);
}
-void RasterShapeIntervals::appendInterval(int y, int x1, int x2)
+PassOwnPtr<RasterShapeIntervals> RasterShapeIntervals::computeShapeMarginIntervals(int shapeMargin) const
{
- ASSERT(x2 > x1 && (intervalsAt(y).isEmpty() || x1 > intervalsAt(y).last().x2()));
- m_bounds.unite(IntRect(x1, y, x2 - x1, 1));
- intervalsAt(y).append(IntShapeInterval(x1, x2));
-}
-
-void RasterShapeIntervals::uniteMarginInterval(int y, const IntShapeInterval& interval)
-{
- ASSERT(intervalsAt(y).size() <= 1); // Each m_intervalLists entry has 0 or one interval.
-
- if (intervalsAt(y).isEmpty()) {
- intervalsAt(y).append(interval);
- } else {
- IntShapeInterval& resultInterval = intervalsAt(y)[0];
- resultInterval.set(std::min(resultInterval.x1(), interval.x1()), std::max(resultInterval.x2(), interval.x2()));
- }
-
- m_bounds.unite(IntRect(interval.x1(), y, interval.width(), 1));
-}
-
-static inline bool shapeIntervalsContain(const IntShapeIntervals& intervals, const IntShapeInterval& interval)
-{
- for (unsigned i = 0; i < intervals.size(); i++) {
- if (intervals[i].x1() > interval.x2())
- return false;
- if (intervals[i].contains(interval))
- return true;
- }
-
- return false;
-}
-
-bool RasterShapeIntervals::contains(const IntRect& rect) const
-{
- if (!bounds().contains(rect))
- return false;
-
- const IntShapeInterval& rectInterval = IntShapeInterval(rect.x(), rect.maxX());
- for (int y = rect.y(); y < rect.maxY(); y++) {
- if (!shapeIntervalsContain(intervalsAt(y), rectInterval))
- return false;
- }
-
- return true;
-}
-
-static inline void appendX1Values(const IntShapeIntervals& intervals, int minIntervalWidth, Vector<int>& result)
-{
- for (unsigned i = 0; i < intervals.size(); i++) {
- if (intervals[i].width() >= minIntervalWidth)
- result.append(intervals[i].x1());
- }
-}
-
-bool RasterShapeIntervals::getIntervalX1Values(int y1, int y2, int minIntervalWidth, Vector<int>& result) const
-{
- ASSERT(y1 >= 0 && y2 > y1);
-
- for (int y = y1; y < y2; y++) {
- if (intervalsAt(y).isEmpty())
- return false;
- }
-
- appendX1Values(intervalsAt(y1), minIntervalWidth, result);
- for (int y = y1 + 1; y < y2; y++) {
- if (intervalsAt(y) != intervalsAt(y - 1))
- appendX1Values(intervalsAt(y), minIntervalWidth, result);
- }
-
- return true;
-}
-
-bool RasterShapeIntervals::firstIncludedIntervalY(int minY, const IntSize& minSize, LayoutUnit& result) const
-{
- minY = std::max<int>(bounds().y(), minY);
-
- ASSERT(minY >= 0 && minY < size());
-
- if (minSize.isEmpty() || minSize.width() > bounds().width())
- return false;
+ int marginIntervalsSize = (offset() > shapeMargin) ? size() : size() - offset() * 2 + shapeMargin * 2;
+ OwnPtr<RasterShapeIntervals> result = adoptPtr(new RasterShapeIntervals(marginIntervalsSize, std::max(shapeMargin, offset())));
+ MarginIntervalGenerator marginIntervalGenerator(shapeMargin);
- for (int lineY = minY; lineY <= bounds().maxY() - minSize.height(); lineY++) {
- Vector<int> intervalX1Values;
- if (!getIntervalX1Values(lineY, lineY + minSize.height(), minSize.width(), intervalX1Values))
+ for (int y = bounds().y(); y < bounds().maxY(); ++y) {
+ const IntShapeInterval& intervalAtY = intervalAt(y);
+ if (intervalAtY.isEmpty())
continue;
- std::sort(intervalX1Values.begin(), intervalX1Values.end());
+ marginIntervalGenerator.set(y, intervalAtY);
+ int marginY0 = std::max(minY(), y - shapeMargin);
+ int marginY1 = std::min(maxY(), y + shapeMargin + 1);
- IntRect firstFitRect(IntPoint(0, 0), minSize);
- for (unsigned i = 0; i < intervalX1Values.size(); i++) {
- int lineX = intervalX1Values[i];
- if (i > 0 && lineX == intervalX1Values[i - 1])
- continue;
- firstFitRect.setLocation(IntPoint(lineX, lineY));
- if (contains(firstFitRect)) {
- result = lineY;
- return true;
- }
+ for (int marginY = y - 1; marginY >= marginY0; --marginY) {
+ if (marginY > bounds().y() && intervalAt(marginY).contains(intervalAtY))
+ break;
+ result->intervalAt(marginY).unite(marginIntervalGenerator.intervalAt(marginY));
}
- }
-
- return false;
-}
-
-void RasterShapeIntervals::getIncludedIntervals(int y1, int y2, IntShapeIntervals& result) const
-{
- ASSERT(y2 >= y1);
- if (y1 < bounds().y() || y2 > bounds().maxY())
- return;
+ result->intervalAt(y).unite(marginIntervalGenerator.intervalAt(y));
- for (int y = y1; y < y2; y++) {
- if (intervalsAt(y).isEmpty())
- return;
+ for (int marginY = y + 1; marginY < marginY1; ++marginY) {
+ if (marginY < bounds().maxY() && intervalAt(marginY).contains(intervalAtY))
+ break;
+ result->intervalAt(marginY).unite(marginIntervalGenerator.intervalAt(marginY));
+ }
}
- result = intervalsAt(y1);
- for (int y = y1 + 1; y < y2 && !result.isEmpty(); y++) {
- IntShapeIntervals intervals;
- IntShapeInterval::intersectShapeIntervals(result, intervalsAt(y), intervals);
- result.swap(intervals);
- }
+ result->initializeBounds();
+ return result.release();
}
-void RasterShapeIntervals::getExcludedIntervals(int y1, int y2, IntShapeIntervals& result) const
+void RasterShapeIntervals::initializeBounds()
{
- ASSERT(y2 >= y1);
-
- if (y2 < bounds().y() || y1 >= bounds().maxY())
- return;
-
- y1 = std::max(y1, bounds().y());
- y2 = std::min(y2, bounds().maxY());
-
- result = intervalsAt(y1);
- for (int y = y1 + 1; y < y2; y++) {
- IntShapeIntervals intervals;
- IntShapeInterval::uniteShapeIntervals(result, intervalsAt(y), intervals);
- result.swap(intervals);
+ m_bounds = IntRect();
+ for (int y = minY(); y < maxY(); ++y) {
+ const IntShapeInterval& intervalAtY = intervalAt(y);
+ if (intervalAtY.isEmpty())
+ continue;
+ m_bounds.unite(IntRect(intervalAtY.x1(), y, intervalAtY.width(), 1));
}
}
-PassOwnPtr<RasterShapeIntervals> RasterShapeIntervals::computeShapeMarginIntervals(unsigned shapeMargin) const
+void RasterShapeIntervals::buildBoundsPath(Path& path) const
{
- OwnPtr<RasterShapeIntervals> result = adoptPtr(new RasterShapeIntervals(size(), shapeMargin));
- MarginIntervalGenerator marginIntervalGenerator(shapeMargin);
-
- int minY = bounds().y();
int maxY = bounds().maxY();
-
- for (int y = minY; y < maxY; ++y) {
- const IntShapeInterval& intervalAtY = limitIntervalAt(y);
- if (intervalAtY.isEmpty())
+ for (int y = bounds().y(); y < maxY; y++) {
+ if (intervalAt(y).isEmpty())
continue;
- marginIntervalGenerator.set(y, intervalAtY);
- int marginY0 = y - clampToInteger(shapeMargin);
- int marginY1 = y + clampToInteger(shapeMargin);
-
- for (int marginY = y - 1; marginY >= marginY0; --marginY) {
- if (marginY > minY && limitIntervalAt(marginY).contains(intervalAtY))
+ IntShapeInterval extent = intervalAt(y);
+ int endY = y + 1;
+ for (; endY < maxY; endY++) {
+ if (intervalAt(endY).isEmpty() || intervalAt(endY) != extent)
break;
- result->uniteMarginInterval(marginY, marginIntervalGenerator.intervalAt(marginY));
- }
-
- result->uniteMarginInterval(y, marginIntervalGenerator.intervalAt(y));
-
- for (int marginY = y + 1; marginY <= marginY1; ++marginY) {
- if (marginY < maxY && limitIntervalAt(marginY).contains(intervalAtY))
- break;
- result->uniteMarginInterval(marginY, marginIntervalGenerator.intervalAt(marginY));
}
+ path.addRect(FloatRect(extent.x1(), y, extent.width(), endY - y));
+ y = endY - 1;
}
-
- return result.release();
}
const RasterShapeIntervals& RasterShape::marginIntervals() const
@@ -257,58 +142,37 @@ const RasterShapeIntervals& RasterShape::marginIntervals() const
if (!shapeMargin())
return *m_intervals;
- unsigned marginBoundaryRadius = std::min(clampToUnsigned(ceil(shapeMargin())), std::max<unsigned>(m_imageSize.width(), m_imageSize.height()));
+ int shapeMarginInt = clampToPositiveInteger(ceil(shapeMargin()));
+ int maxShapeMarginInt = std::max(m_marginRectSize.width(), m_marginRectSize.height()) * sqrtf(2);
if (!m_marginIntervals)
- m_marginIntervals = m_intervals->computeShapeMarginIntervals(marginBoundaryRadius);
+ m_marginIntervals = m_intervals->computeShapeMarginIntervals(std::min(shapeMarginInt, maxShapeMarginInt));
return *m_marginIntervals;
}
-const RasterShapeIntervals& RasterShape::paddingIntervals() const
-{
- ASSERT(shapePadding() >= 0);
- if (!shapePadding())
- return *m_intervals;
-
- // FIXME: Add support for non-zero padding, see https://bugs.webkit.org/show_bug.cgi?id=116348.
- return *m_intervals;
-}
-
-static inline void appendLineSegments(const IntShapeIntervals& intervals, SegmentList& result)
-{
- for (unsigned i = 0; i < intervals.size(); i++)
- result.append(LineSegment(intervals[i].x1(), intervals[i].x2() + 1));
-}
-
void RasterShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
const RasterShapeIntervals& intervals = marginIntervals();
if (intervals.isEmpty())
return;
- IntShapeIntervals excludedIntervals;
- intervals.getExcludedIntervals(logicalTop, logicalTop + logicalHeight, excludedIntervals);
- appendLineSegments(excludedIntervals, result);
-}
-
-void RasterShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
-{
- const RasterShapeIntervals& intervals = paddingIntervals();
- if (intervals.isEmpty())
+ int y1 = logicalTop;
+ int y2 = logicalTop + logicalHeight;
+ ASSERT(y2 >= y1);
+ if (y2 < intervals.bounds().y() || y1 >= intervals.bounds().maxY())
return;
- IntShapeIntervals includedIntervals;
- intervals.getIncludedIntervals(logicalTop, logicalTop + logicalHeight, includedIntervals);
- appendLineSegments(includedIntervals, result);
-}
+ y1 = std::max(y1, intervals.bounds().y());
+ y2 = std::min(y2, intervals.bounds().maxY());
+ IntShapeInterval excludedInterval;
-bool RasterShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
- const RasterShapeIntervals& intervals = paddingIntervals();
- if (intervals.isEmpty())
- return false;
+ for (int y = y1; y < y2; y++)
+ excludedInterval.unite(intervals.intervalAt(y));
- return intervals.firstIncludedIntervalY(minLogicalIntervalTop.floor(), flooredIntSize(minLogicalIntervalSize), result);
+ // Note: |marginIntervals()| returns end-point exclusive
+ // intervals. |excludedInterval.x2()| contains the left-most pixel
+ // offset to the right of the calculated union.
+ result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2()));
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h
index 903eabb0527..0ca8d8a5ba9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h
@@ -40,74 +40,69 @@ namespace WebCore {
class RasterShapeIntervals {
public:
- RasterShapeIntervals(unsigned size, unsigned shapeMargin = 0)
- : m_shapeMargin(shapeMargin)
+ RasterShapeIntervals(unsigned size, int offset = 0)
+ : m_offset(offset)
{
- m_intervalLists.resize(size + shapeMargin * 2);
+ m_intervals.resize(clampTo<int>(size));
}
+ void initializeBounds();
const IntRect& bounds() const { return m_bounds; }
bool isEmpty() const { return m_bounds.isEmpty(); }
- void appendInterval(int y, int x1, int x2);
- void getIncludedIntervals(int y1, int y2, IntShapeIntervals& result) const;
- void getExcludedIntervals(int y1, int y2, IntShapeIntervals& result) const;
- bool firstIncludedIntervalY(int minY, const IntSize& minSize, LayoutUnit& result) const;
- PassOwnPtr<RasterShapeIntervals> computeShapeMarginIntervals(unsigned shapeMargin) const;
-
-private:
- int size() const { return m_intervalLists.size(); }
-
- IntShapeIntervals& intervalsAt(int y)
+ IntShapeInterval& intervalAt(int y)
{
- ASSERT(y + m_shapeMargin >= 0 && y + m_shapeMargin < m_intervalLists.size());
- return m_intervalLists[y + m_shapeMargin];
+ ASSERT(y + m_offset >= 0 && static_cast<unsigned>(y + m_offset) < m_intervals.size());
+ return m_intervals[y + m_offset];
}
- const IntShapeIntervals& intervalsAt(int y) const
+ const IntShapeInterval& intervalAt(int y) const
{
- ASSERT(y + m_shapeMargin >= 0 && y + m_shapeMargin < m_intervalLists.size());
- return m_intervalLists[y + m_shapeMargin];
+ ASSERT(y + m_offset >= 0 && static_cast<unsigned>(y + m_offset) < m_intervals.size());
+ return m_intervals[y + m_offset];
}
- IntShapeInterval limitIntervalAt(int y) const
- {
- const IntShapeIntervals& intervals = intervalsAt(y);
- return intervals.size() ? IntShapeInterval(intervals[0].x1(), intervals.last().x2()) : IntShapeInterval();
- }
+ PassOwnPtr<RasterShapeIntervals> computeShapeMarginIntervals(int shapeMargin) const;
+
+ void buildBoundsPath(Path&) const;
+
+private:
+ int size() const { return m_intervals.size(); }
+ int offset() const { return m_offset; }
+ int minY() const { return -m_offset; }
+ int maxY() const { return -m_offset + m_intervals.size(); }
- bool contains(const IntRect&) const;
- bool getIntervalX1Values(int minY, int maxY, int minIntervalWidth, Vector<int>& result) const;
- void uniteMarginInterval(int y, const IntShapeInterval&);
IntRect m_bounds;
- Vector<IntShapeIntervals> m_intervalLists;
- unsigned m_shapeMargin;
+ Vector<IntShapeInterval> m_intervals;
+ int m_offset;
};
-class RasterShape : public Shape {
+class RasterShape FINAL : public Shape {
WTF_MAKE_NONCOPYABLE(RasterShape);
public:
- RasterShape(PassOwnPtr<RasterShapeIntervals> intervals, const IntSize& imageSize)
- : Shape()
- , m_intervals(intervals)
- , m_imageSize(imageSize)
+ RasterShape(PassOwnPtr<RasterShapeIntervals> intervals, const IntSize& marginRectSize)
+ : m_intervals(intervals)
+ , m_marginRectSize(marginRectSize)
{
+ m_intervals->initializeBounds();
}
virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(marginIntervals().bounds()); }
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(paddingIntervals().bounds()); }
virtual bool isEmpty() const OVERRIDE { return m_intervals->isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths& paths) const OVERRIDE
+ {
+ m_intervals->buildBoundsPath(paths.shape);
+ if (shapeMargin())
+ marginIntervals().buildBoundsPath(paths.marginShape);
+ }
private:
const RasterShapeIntervals& marginIntervals() const;
- const RasterShapeIntervals& paddingIntervals() const;
OwnPtr<RasterShapeIntervals> m_intervals;
mutable OwnPtr<RasterShapeIntervals> m_marginIntervals;
- IntSize m_imageSize;
+ IntSize m_marginRectSize;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp
index efe1f69831b..eaf51424c83 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp
@@ -40,26 +40,6 @@ static inline float ellipseXIntercept(float y, float rx, float ry)
return rx * sqrt(1 - (y * y) / (ry * ry));
}
-static inline float ellipseYIntercept(float x, float rx, float ry)
-{
- ASSERT(rx > 0);
- return ry * sqrt(1 - (x * x) / (rx * rx));
-}
-
-FloatRect RectangleShape::shapePaddingBounds() const
-{
- ASSERT(shapePadding() >= 0);
- if (!shapePadding() || isEmpty())
- return m_bounds;
-
- float boundsX = x() + std::min(width() / 2, shapePadding());
- float boundsY = y() + std::min(height() / 2, shapePadding());
- float boundsWidth = std::max(0.0f, width() - shapePadding() * 2);
- float boundsHeight = std::max(0.0f, height() - shapePadding() * 2);
-
- return FloatRect(boundsX, boundsY, boundsWidth, boundsHeight);
-}
-
FloatRect RectangleShape::shapeMarginBounds() const
{
ASSERT(shapeMargin() >= 0);
@@ -79,8 +59,8 @@ void RectangleShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logi
if (bounds.isEmpty())
return;
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
+ float y1 = logicalTop.toFloat();
+ float y2 = (logicalTop + logicalHeight).toFloat();
if (y2 < bounds.y() || y1 >= bounds.maxY())
return;
@@ -108,112 +88,11 @@ void RectangleShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logi
result.append(LineSegment(x1, x2));
}
-void RectangleShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+void RectangleShape::buildDisplayPaths(DisplayPaths& paths) const
{
- const FloatRect& bounds = shapePaddingBounds();
- if (bounds.isEmpty())
- return;
-
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
-
- if (y1 < bounds.y() || y2 > bounds.maxY())
- return;
-
- float x1 = bounds.x();
- float x2 = bounds.maxX();
-
- float paddingRadiusX = std::max(0.0f, rx() - shapePadding());
- float paddingRadiusY = std::max(0.0f, ry() - shapePadding());
-
- if (paddingRadiusX > 0) {
- bool y1InterceptsCorner = y1 < bounds.y() + paddingRadiusY;
- bool y2InterceptsCorner = y2 > bounds.maxY() - paddingRadiusY;
- float xi = 0;
-
- if (y1InterceptsCorner && y2InterceptsCorner) {
- if (y1 < bounds.height() + 2 * bounds.y() - y2) {
- float yi = y1 - bounds.y() - paddingRadiusY;
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- } else {
- float yi = y2 - (bounds.maxY() - paddingRadiusY);
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- }
- } else if (y1InterceptsCorner) {
- float yi = y1 - bounds.y() - paddingRadiusY;
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- } else if (y2InterceptsCorner) {
- float yi = y2 - (bounds.maxY() - paddingRadiusY);
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- }
-
- if (y1InterceptsCorner || y2InterceptsCorner) {
- x1 = bounds.x() + paddingRadiusX - xi;
- x2 = bounds.maxX() - paddingRadiusX + xi;
- }
- }
-
- result.append(LineSegment(x1, x2));
-}
-
-static FloatPoint cornerInterceptForWidth(float width, float widthAtIntercept, float rx, float ry)
-{
- float xi = (width - widthAtIntercept) / 2;
- float yi = ry - ellipseYIntercept(rx - xi, rx, ry);
- return FloatPoint(xi, yi);
-}
-
-bool RectangleShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
- float minIntervalTop = minLogicalIntervalTop;
- float minIntervalHeight = minLogicalIntervalSize.height();
- float minIntervalWidth = minLogicalIntervalSize.width();
-
- const FloatRect& bounds = shapePaddingBounds();
- if (bounds.isEmpty() || minIntervalWidth > bounds.width())
- return false;
-
- float minY = LayoutUnit::fromFloatCeil(std::max(bounds.y(), minIntervalTop));
- float maxY = minY + minIntervalHeight;
-
- if (maxY > bounds.maxY())
- return false;
-
- float paddingRadiusX = std::max(0.0f, rx() - shapePadding());
- float paddingRadiusY = std::max(0.0f, ry() - shapePadding());
-
- bool intervalOverlapsMinCorner = minY < bounds.y() + paddingRadiusY;
- bool intervalOverlapsMaxCorner = maxY > bounds.maxY() - paddingRadiusY;
-
- if (!intervalOverlapsMinCorner && !intervalOverlapsMaxCorner) {
- result = minY;
- return true;
- }
-
- float centerY = bounds.y() + bounds.height() / 2;
- bool minCornerDefinesX = fabs(centerY - minY) > fabs(centerY - maxY);
- bool intervalFitsWithinCorners = minIntervalWidth + 2 * paddingRadiusX <= bounds.width();
- FloatPoint cornerIntercept = cornerInterceptForWidth(bounds.width(), minIntervalWidth, paddingRadiusX, paddingRadiusY);
-
- if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDefinesX)) {
- if (intervalFitsWithinCorners || bounds.y() + cornerIntercept.y() < minY) {
- result = minY;
- return true;
- }
- if (minIntervalHeight < bounds.height() - (2 * cornerIntercept.y())) {
- result = LayoutUnit::fromFloatCeil(bounds.y() + cornerIntercept.y());
- return true;
- }
- }
-
- if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDefinesX)) {
- if (intervalFitsWithinCorners || minY <= bounds.maxY() - cornerIntercept.y() - minIntervalHeight) {
- result = minY;
- return true;
- }
- }
-
- return false;
+ paths.shape.addRoundedRect(m_bounds, m_radii);
+ if (shapeMargin())
+ paths.marginShape.addRoundedRect(shapeMarginBounds(), FloatSize(m_radii.width() + shapeMargin(), m_radii.height() + shapeMargin()));
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h
index 9a9dae5522e..d47471da48f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h
@@ -39,7 +39,7 @@
namespace WebCore {
-class RectangleShape : public Shape {
+class RectangleShape FINAL : public Shape {
public:
RectangleShape(const FloatRect& bounds, const FloatSize& radii)
: Shape()
@@ -49,15 +49,12 @@ public:
}
virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapeMarginBounds()); }
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapePaddingBounds()); }
virtual bool isEmpty() const OVERRIDE { return m_bounds.isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths&) const OVERRIDE;
private:
FloatRect shapeMarginBounds() const;
- FloatRect shapePaddingBounds() const;
float rx() const { return m_radii.width(); }
float ry() const { return m_radii.height(); }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
index ffe05053133..6e382254b9a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
@@ -30,14 +30,16 @@
#include "config.h"
#include "core/rendering/shapes/Shape.h"
+#include "core/css/BasicShapeFunctions.h"
#include "core/fetch/ImageResource.h"
#include "core/rendering/shapes/BoxShape.h"
#include "core/rendering/shapes/PolygonShape.h"
#include "core/rendering/shapes/RasterShape.h"
#include "core/rendering/shapes/RectangleShape.h"
+#include "core/rendering/style/RenderStyle.h"
#include "platform/LengthFunctions.h"
-#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/FloatSize.h"
+#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/WindRule.h"
#include "wtf/MathExtras.h"
@@ -45,18 +47,12 @@
namespace WebCore {
-static PassOwnPtr<Shape> createBoxShape(const FloatRoundedRect& bounds)
+static PassOwnPtr<Shape> createInsetShape(const FloatRoundedRect& bounds)
{
ASSERT(bounds.rect().width() >= 0 && bounds.rect().height() >= 0);
return adoptPtr(new BoxShape(bounds));
}
-static PassOwnPtr<Shape> createRectangleShape(const FloatRect& bounds, const FloatSize& radii)
-{
- ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0);
- return adoptPtr(new RectangleShape(bounds, radii));
-}
-
static PassOwnPtr<Shape> createCircleShape(const FloatPoint& center, float radius)
{
ASSERT(radius >= 0);
@@ -99,55 +95,22 @@ static inline FloatSize physicalSizeToLogical(const FloatSize& size, WritingMode
return size.transposedSize();
}
-static inline void ensureRadiiDoNotOverlap(FloatRect &bounds, FloatSize &radii)
-{
- float widthRatio = bounds.width() / (2 * radii.width());
- float heightRatio = bounds.height() / (2 * radii.height());
- float reductionRatio = std::min<float>(widthRatio, heightRatio);
- if (reductionRatio < 1) {
- radii.setWidth(reductionRatio * radii.width());
- radii.setHeight(reductionRatio * radii.height());
- }
-}
-
-PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, Length margin, Length padding)
+PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, float margin)
{
ASSERT(basicShape);
bool horizontalWritingMode = isHorizontalWritingMode(writingMode);
- float boxWidth = horizontalWritingMode ? logicalBoxSize.width() : logicalBoxSize.height();
- float boxHeight = horizontalWritingMode ? logicalBoxSize.height() : logicalBoxSize.width();
+ float boxWidth = horizontalWritingMode ? logicalBoxSize.width().toFloat() : logicalBoxSize.height().toFloat();
+ float boxHeight = horizontalWritingMode ? logicalBoxSize.height().toFloat() : logicalBoxSize.width().toFloat();
OwnPtr<Shape> shape;
switch (basicShape->type()) {
- case BasicShape::BasicShapeRectangleType: {
- const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape);
- FloatRect bounds(
- floatValueForLength(rectangle->x(), boxWidth),
- floatValueForLength(rectangle->y(), boxHeight),
- floatValueForLength(rectangle->width(), boxWidth),
- floatValueForLength(rectangle->height(), boxHeight));
- FloatSize cornerRadii(
- floatValueForLength(rectangle->cornerRadiusX(), boxWidth),
- floatValueForLength(rectangle->cornerRadiusY(), boxHeight));
- ensureRadiiDoNotOverlap(bounds, cornerRadii);
- FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxSize.height(), writingMode);
-
- shape = createRectangleShape(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
- break;
- }
-
case BasicShape::BasicShapeCircleType: {
const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape);
- float centerX = floatValueForLength(circle->centerX(), boxWidth);
- float centerY = floatValueForLength(circle->centerY(), boxHeight);
- // This method of computing the radius is as defined in SVG
- // (http://www.w3.org/TR/SVG/coords.html#Units). It bases the radius
- // off of the diagonal of the box and ensures that if the box is
- // square, the radius is equal to half the diagonal.
- float radius = floatValueForLength(circle->radius(), sqrtf((boxWidth * boxWidth + boxHeight * boxHeight) / 2));
- FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode);
+ FloatPoint center = floatPointForCenterCoordinate(circle->centerX(), circle->centerY(), FloatSize(boxWidth, boxHeight));
+ float radius = circle->floatValueForRadiusInBox(FloatSize(boxWidth, boxHeight));
+ FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
shape = createCircleShape(logicalCenter, radius);
break;
@@ -155,14 +118,12 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
case BasicShape::BasicShapeEllipseType: {
const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape);
- float centerX = floatValueForLength(ellipse->centerX(), boxWidth);
- float centerY = floatValueForLength(ellipse->centerY(), boxHeight);
- float radiusX = floatValueForLength(ellipse->radiusX(), boxWidth);
- float radiusY = floatValueForLength(ellipse->radiusY(), boxHeight);
- FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode);
- FloatSize logicalRadii = physicalSizeToLogical(FloatSize(radiusX, radiusY), writingMode);
-
- shape = createEllipseShape(logicalCenter, logicalRadii);
+ FloatPoint center = floatPointForCenterCoordinate(ellipse->centerX(), ellipse->centerY(), FloatSize(boxWidth, boxHeight));
+ float radiusX = ellipse->floatValueForRadiusInBox(ellipse->radiusX(), center.x(), boxWidth);
+ float radiusY = ellipse->floatValueForRadiusInBox(ellipse->radiusY(), center.y(), boxHeight);
+ FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
+
+ shape = createEllipseShape(logicalCenter, FloatSize(radiusX, radiusY));
break;
}
@@ -176,28 +137,31 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
FloatPoint vertex(
floatValueForLength(values.at(i), boxWidth),
floatValueForLength(values.at(i + 1), boxHeight));
- (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height(), writingMode);
+ (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height().toFloat(), writingMode);
}
shape = createPolygonShape(vertices.release(), polygon->windRule());
break;
}
- case BasicShape::BasicShapeInsetRectangleType: {
- const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape);
- float left = floatValueForLength(rectangle->left(), boxWidth);
- float top = floatValueForLength(rectangle->top(), boxHeight);
- FloatRect bounds(
- left,
- top,
- boxWidth - left - floatValueForLength(rectangle->right(), boxWidth),
- boxHeight - top - floatValueForLength(rectangle->bottom(), boxHeight));
- FloatSize cornerRadii(
- floatValueForLength(rectangle->cornerRadiusX(), boxWidth),
- floatValueForLength(rectangle->cornerRadiusY(), boxHeight));
- ensureRadiiDoNotOverlap(bounds, cornerRadii);
- FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxSize.height(), writingMode);
-
- shape = createRectangleShape(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
+ case BasicShape::BasicShapeInsetType: {
+ const BasicShapeInset& inset = *static_cast<const BasicShapeInset*>(basicShape);
+ float left = floatValueForLength(inset.left(), boxWidth);
+ float top = floatValueForLength(inset.top(), boxHeight);
+ float right = floatValueForLength(inset.right(), boxWidth);
+ float bottom = floatValueForLength(inset.bottom(), boxHeight);
+ FloatRect rect(left, top, std::max<float>(boxWidth - left - right, 0), std::max<float>(boxHeight - top - bottom, 0));
+ FloatRect logicalRect = physicalRectToLogical(rect, logicalBoxSize.height().toFloat(), writingMode);
+
+ FloatSize boxSize(boxWidth, boxHeight);
+ FloatSize topLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topLeftRadius(), boxSize), writingMode);
+ FloatSize topRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topRightRadius(), boxSize), writingMode);
+ FloatSize bottomLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomLeftRadius(), boxSize), writingMode);
+ FloatSize bottomRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomRightRadius(), boxSize), writingMode);
+ FloatRoundedRect::Radii cornerRadii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ cornerRadii.scale(calcBorderRadiiConstraintScaleFor(logicalRect, cornerRadii));
+
+ shape = createInsetShape(FloatRoundedRect(logicalRect, cornerRadii));
break;
}
@@ -206,61 +170,60 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
}
shape->m_writingMode = writingMode;
- shape->m_margin = floatValueForLength(margin, 0);
- shape->m_padding = floatValueForLength(padding, 0);
+ shape->m_margin = margin;
return shape.release();
}
-PassOwnPtr<Shape> Shape::createShape(const StyleImage* styleImage, float threshold, const LayoutSize&, WritingMode writingMode, Length margin, Length padding)
+PassOwnPtr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin)
{
- ASSERT(styleImage && styleImage->isImageResource() && styleImage->cachedImage() && styleImage->cachedImage()->image());
+ IntRect imageRect = pixelSnappedIntRect(imageR);
+ IntRect marginRect = pixelSnappedIntRect(marginR);
+ OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(marginRect.height(), -marginRect.y()));
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size());
- Image* image = styleImage->cachedImage()->image();
- const IntSize& imageSize = image->size();
- OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(imageSize.height()));
- OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageSize);
if (imageBuffer) {
GraphicsContext* graphicsContext = imageBuffer->context();
- graphicsContext->drawImage(image, IntPoint());
+ graphicsContext->drawImage(image, IntRect(IntPoint(), imageRect.size()));
- RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageSize));
- unsigned pixelArrayLength = pixelArray->length();
+ RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageRect.size()));
unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
uint8_t alphaPixelThreshold = threshold * 255;
- ASSERT(static_cast<unsigned>(imageSize.width() * imageSize.height() * 4) == pixelArrayLength);
+ ASSERT(static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArray->length());
+
+ int minBufferY = std::max(0, marginRect.y() - imageRect.y());
+ int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
- for (int y = 0; y < imageSize.height(); ++y) {
+ for (int y = minBufferY; y < maxBufferY; ++y) {
int startX = -1;
- for (int x = 0; x < imageSize.width() && pixelArrayOffset < pixelArrayLength; ++x, pixelArrayOffset += 4) {
+ for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
uint8_t alpha = pixelArray->item(pixelArrayOffset);
- if ((startX == -1) && alpha > alphaPixelThreshold) {
+ bool alphaAboveThreshold = alpha > alphaPixelThreshold;
+ if (startX == -1 && alphaAboveThreshold) {
startX = x;
- } else if (startX != -1 && (alpha <= alphaPixelThreshold || x == imageSize.width() - 1)) {
- intervals->appendInterval(y, startX, x);
+ } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
+ int endX = alphaAboveThreshold ? x + 1 : x;
+ intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
startX = -1;
}
}
}
}
- OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), imageSize));
+ OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), marginRect.size()));
rasterShape->m_writingMode = writingMode;
- rasterShape->m_margin = floatValueForLength(margin, 0);
- rasterShape->m_padding = floatValueForLength(padding, 0);
+ rasterShape->m_margin = margin;
return rasterShape.release();
}
-PassOwnPtr<Shape> Shape::createLayoutBoxShape(const LayoutSize& logicalSize, WritingMode writingMode, const Length& margin, const Length& padding)
+PassOwnPtr<Shape> Shape::createLayoutBoxShape(const RoundedRect& roundedRect, WritingMode writingMode, float margin)
{
- FloatRect rect(0, 0, logicalSize.width(), logicalSize.height());
- FloatSize radii(0, 0);
- FloatRoundedRect bounds(rect, radii, radii, radii, radii);
- OwnPtr<Shape> shape = createBoxShape(bounds);
+ FloatRect rect(0, 0, roundedRect.rect().width(), roundedRect.rect().height());
+ FloatRoundedRect bounds(rect, roundedRect.radii());
+ OwnPtr<Shape> shape = createInsetShape(bounds);
shape->m_writingMode = writingMode;
- shape->m_margin = floatValueForLength(margin, 0);
- shape->m_padding = floatValueForLength(padding, 0);
+ shape->m_margin = margin;
return shape.release();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h
index de9aef9f99d..fb649957671 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h
@@ -33,6 +33,8 @@
#include "core/rendering/style/BasicShapes.h"
#include "core/rendering/style/StyleImage.h"
#include "platform/geometry/LayoutRect.h"
+#include "platform/geometry/RoundedRect.h"
+#include "platform/graphics/Path.h"
#include "platform/text/WritingMode.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/Vector.h"
@@ -60,24 +62,25 @@ typedef Vector<LineSegment> SegmentList;
class Shape {
public:
- static PassOwnPtr<Shape> createShape(const BasicShape*, const LayoutSize& logicalBoxSize, WritingMode, Length margin, Length padding);
- static PassOwnPtr<Shape> createShape(const StyleImage*, float threshold, const LayoutSize& logicalBoxSize, WritingMode, Length margin, Length padding);
- static PassOwnPtr<Shape> createLayoutBoxShape(const LayoutSize& logicalBoxSize, WritingMode, const Length& margin, const Length& padding);
+ struct DisplayPaths {
+ Path shape;
+ Path marginShape;
+ };
+ static PassOwnPtr<Shape> createShape(const BasicShape*, const LayoutSize& logicalBoxSize, WritingMode, float margin);
+ static PassOwnPtr<Shape> createRasterShape(Image*, float threshold, const LayoutRect& imageRect, const LayoutRect& marginRect, WritingMode, float margin);
+ static PassOwnPtr<Shape> createLayoutBoxShape(const RoundedRect&, WritingMode, float margin);
virtual ~Shape() { }
virtual LayoutRect shapeMarginLogicalBoundingBox() const = 0;
- virtual LayoutRect shapePaddingLogicalBoundingBox() const = 0;
virtual bool isEmpty() const = 0;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const = 0;
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const = 0;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const = 0;
+
bool lineOverlapsShapeMarginBounds(LayoutUnit lineTop, LayoutUnit lineHeight) const { return lineOverlapsBoundingBox(lineTop, lineHeight, shapeMarginLogicalBoundingBox()); }
- bool lineOverlapsShapePaddingBounds(LayoutUnit lineTop, LayoutUnit lineHeight) const { return lineOverlapsBoundingBox(lineTop, lineHeight, shapePaddingLogicalBoundingBox()); }
+ virtual void buildDisplayPaths(DisplayPaths&) const = 0;
protected:
float shapeMargin() const { return m_margin; }
- float shapePadding() const { return m_padding; }
private:
bool lineOverlapsBoundingBox(LayoutUnit lineTop, LayoutUnit lineHeight, const LayoutRect& rect) const
@@ -89,7 +92,6 @@ private:
WritingMode m_writingMode;
float m_margin;
- float m_padding;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp
deleted file mode 100644
index e2668712991..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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 "core/rendering/shapes/ShapeInfo.h"
-
-#include "core/rendering/RenderRegion.h"
-
-namespace WebCore {
-
-bool checkShapeImageOrigin(Document& document, ImageResource& imageResource)
-{
- if (imageResource.isAccessAllowed(document.securityOrigin()))
- return true;
-
- const KURL& url = imageResource.url();
- String urlString = url.isNull() ? "''" : url.elidedString();
- document.addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + ".");
-
- return false;
-}
-
-template<class RenderType>
-const Shape* ShapeInfo<RenderType>::computedShape() const
-{
- if (Shape* shape = m_shape.get())
- return shape;
-
- WritingMode writingMode = m_renderer->style()->writingMode();
- Length margin = m_renderer->style()->shapeMargin();
- Length padding = m_renderer->style()->shapePadding();
- float shapeImageThreshold = m_renderer->style()->shapeImageThreshold();
- const ShapeValue* shapeValue = this->shapeValue();
- ASSERT(shapeValue);
-
- switch (shapeValue->type()) {
- case ShapeValue::Shape:
- ASSERT(shapeValue->shape());
- m_shape = Shape::createShape(shapeValue->shape(), m_shapeLogicalSize, writingMode, margin, padding);
- break;
- case ShapeValue::Image:
- ASSERT(shapeValue->image());
- m_shape = Shape::createShape(shapeValue->image(), shapeImageThreshold, m_shapeLogicalSize, writingMode, margin, padding);
- break;
- case ShapeValue::Box:
- m_shape = Shape::createLayoutBoxShape(m_shapeLogicalSize, writingMode, margin, padding);
- break;
- case ShapeValue::Outside:
- // Outside should have already resolved to a different shape value.
- ASSERT_NOT_REACHED();
- }
-
- ASSERT(m_shape);
- return m_shape.get();
-}
-
-template<class RenderType>
-SegmentList ShapeInfo<RenderType>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
-{
- ASSERT(lineHeight >= 0);
- SegmentList segments;
-
- getIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
-
- for (size_t i = 0; i < segments.size(); i++) {
- segments[i].logicalLeft += logicalLeftOffset();
- segments[i].logicalRight += logicalLeftOffset();
- }
-
- return segments;
-}
-
-template class ShapeInfo<RenderBlock>;
-template class ShapeInfo<RenderBox>;
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h
deleted file mode 100644
index 1314f3409c1..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-* 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 ShapeInfo_h
-#define ShapeInfo_h
-
-#include "core/rendering/shapes/Shape.h"
-#include "core/rendering/style/RenderStyle.h"
-#include "core/rendering/style/ShapeValue.h"
-#include "platform/LayoutUnit.h"
-#include "platform/geometry/FloatRect.h"
-#include "wtf/OwnPtr.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-template<class KeyType, class InfoType>
-class MappedInfo {
-public:
- static InfoType* ensureInfo(const KeyType* key)
- {
- InfoMap& infoMap = MappedInfo<KeyType, InfoType>::infoMap();
- if (InfoType* info = infoMap.get(key))
- return info;
- typename InfoMap::AddResult result = infoMap.add(key, InfoType::createInfo(key));
- return result.iterator->value.get();
- }
- static void removeInfo(const KeyType* key) { infoMap().remove(key); }
- static InfoType* info(const KeyType* key) { return infoMap().get(key); }
-private:
- typedef HashMap<const KeyType*, OwnPtr<InfoType> > InfoMap;
- static InfoMap& infoMap()
- {
- DEFINE_STATIC_LOCAL(InfoMap, staticInfoMap, ());
- return staticInfoMap;
- }
-};
-
-template<class RenderType>
-class ShapeInfo {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- virtual ~ShapeInfo() { }
-
- void setShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight)
- {
- if (shapeValue()->type() == ShapeValue::Box) {
- switch (shapeValue()->layoutBox()) {
- case MarginBox:
- logicalHeight += m_renderer->marginLogicalHeight();
- logicalWidth += m_renderer->marginLogicalWidth();
- break;
- case BorderBox:
- break;
- case PaddingBox:
- logicalHeight -= m_renderer->borderLogicalHeight();
- logicalWidth -= m_renderer->borderLogicalWidth();
- break;
- case ContentBox:
- logicalHeight -= m_renderer->borderAndPaddingLogicalHeight();
- logicalWidth -= m_renderer->borderAndPaddingLogicalWidth();
- break;
- }
- } else if (m_renderer->style()->boxSizing() == CONTENT_BOX) {
- logicalHeight -= m_renderer->borderAndPaddingLogicalHeight();
- logicalWidth -= m_renderer->borderAndPaddingLogicalWidth();
- }
-
- LayoutSize newLogicalSize(logicalWidth, logicalHeight);
- if (m_shapeLogicalSize == newLogicalSize)
- return;
- dirtyShapeSize();
- m_shapeLogicalSize = newLogicalSize;
- }
-
- SegmentList computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const;
-
- LayoutUnit shapeLogicalTop() const { return computedShapeLogicalBoundingBox().y() + logicalTopOffset(); }
- LayoutUnit shapeLogicalBottom() const { return computedShapeLogicalBoundingBox().maxY() + logicalTopOffset(); }
- LayoutUnit shapeLogicalLeft() const { return computedShapeLogicalBoundingBox().x() + logicalLeftOffset(); }
- LayoutUnit shapeLogicalRight() const { return computedShapeLogicalBoundingBox().maxX() + logicalLeftOffset(); }
- LayoutUnit shapeLogicalWidth() const { return computedShapeLogicalBoundingBox().width(); }
- LayoutUnit shapeLogicalHeight() const { return computedShapeLogicalBoundingBox().height(); }
-
- LayoutUnit logicalLineTop() const { return m_shapeLineTop + logicalTopOffset(); }
- LayoutUnit logicalLineBottom() const { return m_shapeLineTop + m_lineHeight + logicalTopOffset(); }
-
- LayoutUnit shapeContainingBlockHeight() const { return (m_renderer->style()->boxSizing() == CONTENT_BOX) ? (m_shapeLogicalSize.height() + m_renderer->borderAndPaddingLogicalHeight()) : m_shapeLogicalSize.height(); }
-
- virtual bool lineOverlapsShapeBounds() const = 0;
-
- void dirtyShapeSize() { m_shape.clear(); }
- bool shapeSizeDirty() { return !m_shape.get(); }
- const RenderType* owner() const { return m_renderer; }
- LayoutSize shapeSize() const { return m_shapeLogicalSize; }
-
-protected:
- ShapeInfo(const RenderType* renderer): m_renderer(renderer) { }
-
- const Shape* computedShape() const;
-
- virtual LayoutRect computedShapeLogicalBoundingBox() const = 0;
- virtual ShapeValue* shapeValue() const = 0;
- virtual void getIntervals(LayoutUnit, LayoutUnit, SegmentList&) const = 0;
-
- LayoutUnit logicalTopOffset() const
- {
- if (shapeValue()->type() == ShapeValue::Box) {
- switch (shapeValue()->layoutBox()) {
- case MarginBox:
- return -m_renderer->marginBefore();
- case BorderBox:
- return LayoutUnit();
- case PaddingBox:
- return m_renderer->borderBefore();
- case ContentBox:
- return m_renderer->borderAndPaddingBefore();
- }
- }
- return m_renderer->style()->boxSizing() == CONTENT_BOX ? m_renderer->borderAndPaddingBefore() : LayoutUnit();
- }
-
- LayoutUnit logicalLeftOffset() const
- {
- if (shapeValue()->type() == ShapeValue::Box) {
- switch (shapeValue()->layoutBox()) {
- case MarginBox:
- return -m_renderer->marginStart();
- case BorderBox:
- return LayoutUnit();
- case PaddingBox:
- return m_renderer->borderStart();
- case ContentBox:
- return m_renderer->borderAndPaddingStart();
- }
- }
- return (m_renderer->style()->boxSizing() == CONTENT_BOX && !m_renderer->isRenderRegion()) ? m_renderer->borderAndPaddingStart() : LayoutUnit();
- }
-
- LayoutUnit m_shapeLineTop;
- LayoutUnit m_lineHeight;
-
- const RenderType* m_renderer;
-
-private:
- mutable OwnPtr<Shape> m_shape;
- LayoutSize m_shapeLogicalSize;
-};
-
-bool checkShapeImageOrigin(Document&, ImageResource&);
-
-}
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp
deleted file mode 100644
index 301200b19e7..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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 "core/rendering/shapes/ShapeInsideInfo.h"
-
-#include "core/rendering/InlineIterator.h"
-#include "core/rendering/RenderBlock.h"
-
-namespace WebCore {
-
-LineSegmentRange::LineSegmentRange(const InlineIterator& start, const InlineIterator& end)
- : start(start.root(), start.object(), start.offset())
- , end(end.root(), end.object(), end.offset())
- {
- }
-
-bool ShapeInsideInfo::isEnabledFor(const RenderBlock* renderer)
-{
- ShapeValue* shapeValue = renderer->style()->resolvedShapeInside();
- if (!shapeValue)
- return false;
-
- switch (shapeValue->type()) {
- case ShapeValue::Shape:
- return shapeValue->shape() && shapeValue->shape()->type() != BasicShape::BasicShapeInsetRectangleType;
- case ShapeValue::Image:
- return shapeValue->isImageValid() && checkShapeImageOrigin(renderer->document(), *(shapeValue->image()->cachedImage()));
- case ShapeValue::Box:
- case ShapeValue::Outside:
- return false;
- }
-
- return false;
-}
-
-bool ShapeInsideInfo::updateSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight)
-{
- bool result = updateSegmentsForLine(lineOffset.height(), lineHeight);
- for (size_t i = 0; i < m_segments.size(); i++) {
- m_segments[i].logicalLeft -= lineOffset.width();
- m_segments[i].logicalRight -= lineOffset.width();
- }
- return result;
-}
-
-bool ShapeInsideInfo::updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
-{
- ASSERT(lineHeight >= 0);
- m_shapeLineTop = lineTop - logicalTopOffset();
- m_lineHeight = lineHeight;
- m_segments.clear();
- m_segmentRanges.clear();
-
- if (lineOverlapsShapeBounds())
- m_segments = computeSegmentsForLine(lineTop, lineHeight);
-
- return m_segments.size();
-}
-
-bool ShapeInsideInfo::adjustLogicalLineTop(float minSegmentWidth)
-{
- const Shape* shape = computedShape();
- if (!shape || m_lineHeight <= 0 || logicalLineTop() > shapeLogicalBottom())
- return false;
-
- LayoutUnit newLineTop;
- if (shape->firstIncludedIntervalLogicalTop(m_shapeLineTop, LayoutSize(minSegmentWidth, m_lineHeight), newLineTop)) {
- if (newLineTop > m_shapeLineTop) {
- m_shapeLineTop = newLineTop;
- return true;
- }
- }
-
- return false;
-}
-
-ShapeValue* ShapeInsideInfo::shapeValue() const
-{
- return m_renderer->style()->resolvedShapeInside();
-}
-
-LayoutUnit ShapeInsideInfo::computeFirstFitPositionForFloat(const LayoutSize floatSize) const
-{
- if (!computedShape() || !floatSize.width() || shapeLogicalBottom() < logicalLineTop())
- return 0;
-
- LayoutUnit firstFitPosition = 0;
- if (computedShape()->firstIncludedIntervalLogicalTop(m_shapeLineTop, floatSize, firstFitPosition) && (m_shapeLineTop <= firstFitPosition))
- return firstFitPosition;
-
- return 0;
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h
deleted file mode 100644
index 0f0f3855266..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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 ShapeInsideInfo_h
-#define ShapeInsideInfo_h
-
-#include "core/rendering/shapes/ShapeInfo.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-class InlineIterator;
-class RenderBlock;
-class RenderObject;
-
-struct LineSegmentIterator {
- RenderObject* root;
- RenderObject* object;
- unsigned offset;
- LineSegmentIterator(RenderObject* root, RenderObject* object, unsigned offset)
- : root(root)
- , object(object)
- , offset(offset)
- {
- }
-};
-
-struct LineSegmentRange {
- LineSegmentIterator start;
- LineSegmentIterator end;
- LineSegmentRange(const InlineIterator& start, const InlineIterator& end);
-};
-
-typedef Vector<LineSegmentRange> SegmentRangeList;
-
-class ShapeInsideInfo FINAL : public ShapeInfo<RenderBlock> {
-public:
- static PassOwnPtr<ShapeInsideInfo> createInfo(const RenderBlock* renderer) { return adoptPtr(new ShapeInsideInfo(renderer)); }
-
- static bool isEnabledFor(const RenderBlock* renderer);
-
- bool updateSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight);
- bool updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
-
- bool hasSegments() const
- {
- return lineOverlapsShapeBounds() && m_segments.size();
- }
- const SegmentList& segments() const
- {
- ASSERT(hasSegments());
- return m_segments;
- }
- SegmentRangeList& segmentRanges() { return m_segmentRanges; }
- const SegmentRangeList& segmentRanges() const { return m_segmentRanges; }
- const LineSegment* currentSegment() const
- {
- if (!hasSegments())
- return 0;
- ASSERT(m_segmentRanges.size() < m_segments.size());
- return &m_segments[m_segmentRanges.size()];
- }
- void clearSegments() { m_segments.clear(); }
- bool adjustLogicalLineTop(float minSegmentWidth);
- LayoutUnit computeFirstFitPositionForFloat(const LayoutSize) const;
-
- void setNeedsLayout(bool value) { m_needsLayout = value; }
- bool needsLayout() { return m_needsLayout; }
-
- virtual bool lineOverlapsShapeBounds() const OVERRIDE
- {
- return computedShape()->lineOverlapsShapePaddingBounds(m_shapeLineTop, m_lineHeight);
- }
-
-protected:
- virtual LayoutRect computedShapeLogicalBoundingBox() const OVERRIDE { return computedShape()->shapePaddingLogicalBoundingBox(); }
- virtual ShapeValue* shapeValue() const OVERRIDE;
- virtual void getIntervals(LayoutUnit lineTop, LayoutUnit lineHeight, SegmentList& segments) const OVERRIDE
- {
- return computedShape()->getIncludedIntervals(lineTop, lineHeight, segments);
- }
-
-private:
- ShapeInsideInfo(const RenderBlock* renderer)
- : ShapeInfo<RenderBlock> (renderer)
- , m_needsLayout(false)
- { }
-
- SegmentRangeList m_segmentRanges;
- bool m_needsLayout;
- SegmentList m_segments;
-};
-
-}
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h
index efeb7d862c0..47c20178f0f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h
@@ -38,29 +38,27 @@ template <typename T>
class ShapeInterval {
WTF_MAKE_FAST_ALLOCATED;
public:
- ShapeInterval(T x1 = 0, T x2 = 0)
- : m_x1(x1)
- , m_x2(x2)
+ ShapeInterval()
+ : m_x1(-1)
+ , m_x2(-2)
{
- ASSERT(x2 >= x1);
+ // The initial values of m_x1,x2 don't matter (unless you're looking
+ // at them in the debugger) so long as isUndefined() is true.
+ ASSERT(isUndefined());
}
- T x1() const { return m_x1; }
- T x2() const { return m_x2; }
- T width() const { return m_x2 - m_x1; }
- bool isEmpty() const { return m_x1 == m_x2; }
-
- void setX1(T x1)
+ ShapeInterval(T x1, T x2)
+ : m_x1(x1)
+ , m_x2(x2)
{
- ASSERT(m_x2 >= x1);
- m_x1 = x1;
+ ASSERT(x2 >= x1);
}
- void setX2(T x2)
- {
- ASSERT(x2 >= m_x1);
- m_x2 = x2;
- }
+ bool isUndefined() const { return m_x2 < m_x1; }
+ T x1() const { return isUndefined() ? 0 : m_x1; }
+ T x2() const { return isUndefined() ? 0 : m_x2; }
+ T width() const { return isUndefined() ? 0 : m_x2 - m_x1; }
+ bool isEmpty() const { return isUndefined() ? true : m_x1 == m_x2; }
void set(T x1, T x2)
{
@@ -71,155 +69,34 @@ public:
bool overlaps(const ShapeInterval<T>& interval) const
{
+ if (isUndefined() || interval.isUndefined())
+ return false;
return x2() >= interval.x1() && x1() <= interval.x2();
}
bool contains(const ShapeInterval<T>& interval) const
{
+ if (isUndefined() || interval.isUndefined())
+ return false;
return x1() <= interval.x1() && x2() >= interval.x2();
}
- ShapeInterval<T> intersect(const ShapeInterval<T>& interval) const
- {
- ASSERT(overlaps(interval));
- return ShapeInterval<T>(std::max<T>(x1(), interval.x1()), std::min<T>(x2(), interval.x2()));
- }
-
- typedef Vector<ShapeInterval<T> > ShapeIntervals;
- typedef typename ShapeIntervals::const_iterator const_iterator;
- typedef typename ShapeIntervals::iterator iterator;
-
- static void uniteShapeIntervals(const ShapeIntervals& a, const ShapeIntervals& b, ShapeIntervals& result)
- {
- ASSERT(shapeIntervalsAreSortedAndDisjoint(a) && shapeIntervalsAreSortedAndDisjoint(b));
-
- if (a.isEmpty() || a == b) {
- result.appendRange(b.begin(), b.end());
- return;
- }
-
- if (b.isEmpty()) {
- result.appendRange(a.begin(), a.end());
- return;
- }
-
- const_iterator aNext = a.begin();
- const_iterator bNext = b.begin();
-
- while (aNext != a.end() || bNext != b.end()) {
- const_iterator next = (bNext == b.end() || (aNext != a.end() && aNext->x1() < bNext->x1())) ? aNext++ : bNext++;
- if (result.isEmpty() || !result.last().overlaps(*next))
- result.append(*next);
- else
- result.last().setX2(std::max<T>(result.last().x2(), next->x2()));
- }
- }
-
- static void intersectShapeIntervals(const ShapeIntervals& a, const ShapeIntervals& b, ShapeIntervals& result)
- {
- ASSERT(shapeIntervalsAreSortedAndDisjoint(a) && shapeIntervalsAreSortedAndDisjoint(b));
-
- if (a.isEmpty() || b.isEmpty())
- return;
-
- if (a == b) {
- result.appendRange(a.begin(), a.end());
- return;
- }
-
- const_iterator aNext = a.begin();
- const_iterator bNext = b.begin();
- const_iterator working = aNext->x1() < bNext->x1() ? aNext++ : bNext++;
-
- while (aNext != a.end() || bNext != b.end()) {
- const_iterator next = (bNext == b.end() || (aNext != a.end() && aNext->x1() < bNext->x1())) ? aNext++ : bNext++;
- if (working->overlaps(*next)) {
- result.append(working->intersect(*next));
- if (next->x2() > working->x2())
- working = next;
- } else {
- working = next;
- }
- }
- }
+ bool operator==(const ShapeInterval<T>& other) const { return x1() == other.x1() && x2() == other.x2(); }
+ bool operator!=(const ShapeInterval<T>& other) const { return !operator==(other); }
- static void subtractShapeIntervals(const ShapeIntervals& a, const ShapeIntervals& b, ShapeIntervals& result)
+ void unite(const ShapeInterval<T>& interval)
{
- ASSERT(shapeIntervalsAreSortedAndDisjoint(a) && shapeIntervalsAreSortedAndDisjoint(b));
-
- if (a.isEmpty() || a == b)
- return;
-
- if (b.isEmpty()) {
- result.appendRange(a.begin(), a.end());
+ if (interval.isUndefined())
return;
- }
-
- const_iterator aNext = a.begin();
- const_iterator bNext = b.begin();
- ShapeInterval<T> aValue = *aNext;
- ShapeInterval<T> bValue = *bNext;
-
- do {
- bool aIncrement = false;
- bool bIncrement = false;
-
- if (bValue.contains(aValue)) {
- aIncrement = true;
- } else if (aValue.contains(bValue)) {
- if (bValue.x1() > aValue.x1())
- result.append(ShapeInterval<T>(aValue.x1(), bValue.x1()));
- if (aValue.x2() > bValue.x2())
- aValue.setX1(bValue.x2());
- else
- aIncrement = true;
- bIncrement = true;
- } else if (aValue.overlaps(bValue)) {
- if (aValue.x1() < bValue.x1()) {
- result.append(ShapeInterval<T>(aValue.x1(), bValue.x1()));
- aIncrement = true;
- } else {
- aValue.setX1(bValue.x2());
- bIncrement = true;
- }
- } else {
- if (aValue.x1() < bValue.x1()) {
- result.append(aValue);
- aIncrement = true;
- } else {
- bIncrement = true;
- }
- }
-
- if (aIncrement && ++aNext != a.end())
- aValue = *aNext;
- if (bIncrement && ++bNext != b.end())
- bValue = *bNext;
-
- } while (aNext != a.end() && bNext != b.end());
-
- if (aNext != a.end()) {
- result.append(aValue);
- result.appendRange(++aNext, a.end());
- }
+ if (isUndefined())
+ set(interval.x1(), interval.x2());
+ else
+ set(std::min<T>(x1(), interval.x1()), std::max<T>(x2(), interval.x2()));
}
- bool operator==(const ShapeInterval<T>& other) const { return x1() == other.x1() && x2() == other.x2(); }
- bool operator!=(const ShapeInterval<T>& other) const { return !operator==(other); }
-
private:
T m_x1;
T m_x2;
-
- static bool shapeIntervalsAreSortedAndDisjoint(const ShapeIntervals& intervals)
- {
- for (unsigned i = 1; i < intervals.size(); i++) {
- if (intervals[i - 1].x2() > intervals[i].x1())
- return false;
- }
-
- return true;
- }
};
typedef ShapeInterval<int> IntShapeInterval;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp
index 98bea9a0a16..216d3091acf 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp
@@ -33,48 +33,269 @@
#include "core/rendering/FloatingObjects.h"
#include "core/rendering/RenderBlockFlow.h"
#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderImage.h"
+#include "platform/LengthFunctions.h"
namespace WebCore {
-bool ShapeOutsideInfo::isEnabledFor(const RenderBox* box)
+
+CSSBoxType referenceBox(const ShapeValue& shapeValue)
+{
+ if (shapeValue.cssBox() == BoxMissing)
+ return MarginBox;
+ return shapeValue.cssBox();
+}
+
+void ShapeOutsideInfo::setReferenceBoxLogicalSize(LayoutSize newReferenceBoxLogicalSize)
+{
+ bool isHorizontalWritingMode = m_renderer.containingBlock()->style()->isHorizontalWritingMode();
+ switch (referenceBox(*m_renderer.style()->shapeOutside())) {
+ case MarginBox:
+ if (isHorizontalWritingMode)
+ newReferenceBoxLogicalSize.expand(m_renderer.marginWidth(), m_renderer.marginHeight());
+ else
+ newReferenceBoxLogicalSize.expand(m_renderer.marginHeight(), m_renderer.marginWidth());
+ break;
+ case BorderBox:
+ break;
+ case PaddingBox:
+ if (isHorizontalWritingMode)
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderWidth(), m_renderer.borderHeight());
+ else
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderHeight(), m_renderer.borderWidth());
+ break;
+ case ContentBox:
+ if (isHorizontalWritingMode)
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingWidth(), m_renderer.borderAndPaddingHeight());
+ else
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingHeight(), m_renderer.borderAndPaddingWidth());
+ break;
+ case BoxMissing:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ if (m_referenceBoxLogicalSize == newReferenceBoxLogicalSize)
+ return;
+ markShapeAsDirty();
+ m_referenceBoxLogicalSize = newReferenceBoxLogicalSize;
+}
+
+static bool checkShapeImageOrigin(Document& document, const StyleImage& styleImage)
{
- ShapeValue* shapeValue = box->style()->shapeOutside();
- if (!box->isFloating() || !shapeValue)
+ if (styleImage.isGeneratedImage())
+ return true;
+
+ ASSERT(styleImage.cachedImage());
+ ImageResource& imageResource = *(styleImage.cachedImage());
+ if (imageResource.isAccessAllowed(document.securityOrigin()))
+ return true;
+
+ const KURL& url = imageResource.url();
+ String urlString = url.isNull() ? "''" : url.elidedString();
+ document.addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + ".");
+
+ return false;
+}
+
+static LayoutRect getShapeImageMarginRect(const RenderBox& renderBox, const LayoutSize& referenceBoxLogicalSize)
+{
+ LayoutPoint marginBoxOrigin(-renderBox.marginLogicalLeft() - renderBox.borderAndPaddingLogicalLeft(), -renderBox.marginBefore() - renderBox.borderBefore() - renderBox.paddingBefore());
+ LayoutSize marginBoxSizeDelta(renderBox.marginLogicalWidth() + renderBox.borderAndPaddingLogicalWidth(), renderBox.marginLogicalHeight() + renderBox.borderAndPaddingLogicalHeight());
+ return LayoutRect(marginBoxOrigin, referenceBoxLogicalSize + marginBoxSizeDelta);
+}
+
+PassOwnPtr<Shape> ShapeOutsideInfo::createShapeForImage(StyleImage* styleImage, float shapeImageThreshold, WritingMode writingMode, float margin) const
+{
+ const IntSize& imageSize = m_renderer.calculateImageIntrinsicDimensions(styleImage, roundedIntSize(m_referenceBoxLogicalSize), RenderImage::ScaleByEffectiveZoom);
+ styleImage->setContainerSizeForRenderer(&m_renderer, imageSize, m_renderer.style()->effectiveZoom());
+
+ const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referenceBoxLogicalSize);
+ const LayoutRect& imageRect = (m_renderer.isRenderImage())
+ ? toRenderImage(&m_renderer)->replacedContentRect()
+ : LayoutRect(LayoutPoint(), imageSize);
+
+ ASSERT(!styleImage->isPendingImage());
+ RefPtr<Image> image = styleImage->image(const_cast<RenderBox*>(&m_renderer), imageSize);
+
+ return Shape::createRasterShape(image.get(), shapeImageThreshold, imageRect, marginRect, writingMode, margin);
+}
+
+const Shape& ShapeOutsideInfo::computedShape() const
+{
+ if (Shape* shape = m_shape.get())
+ return *shape;
+
+ const RenderStyle& style = *m_renderer.style();
+ ASSERT(m_renderer.containingBlock());
+ const RenderStyle& containingBlockStyle = *m_renderer.containingBlock()->style();
+
+ WritingMode writingMode = containingBlockStyle.writingMode();
+ LayoutUnit maximumValue = m_renderer.containingBlock() ? m_renderer.containingBlock()->contentWidth() : LayoutUnit();
+ float margin = floatValueForLength(m_renderer.style()->shapeMargin(), maximumValue.toFloat());
+
+ float shapeImageThreshold = style.shapeImageThreshold();
+ ASSERT(style.shapeOutside());
+ const ShapeValue& shapeValue = *style.shapeOutside();
+
+ switch (shapeValue.type()) {
+ case ShapeValue::Shape:
+ ASSERT(shapeValue.shape());
+ m_shape = Shape::createShape(shapeValue.shape(), m_referenceBoxLogicalSize, writingMode, margin);
+ break;
+ case ShapeValue::Image:
+ ASSERT(shapeValue.isImageValid());
+ m_shape = createShapeForImage(shapeValue.image(), shapeImageThreshold, writingMode, margin);
+ break;
+ case ShapeValue::Box: {
+ const RoundedRect& shapeRect = style.getRoundedBorderFor(LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize), m_renderer.view());
+ m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin);
+ break;
+ }
+ }
+
+ ASSERT(m_shape);
+ return *m_shape;
+}
+
+SegmentList ShapeOutsideInfo::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
+{
+ ASSERT(lineHeight >= 0);
+ SegmentList segments;
+
+ computedShape().getExcludedIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
+
+ for (size_t i = 0; i < segments.size(); i++) {
+ segments[i].logicalLeft += logicalLeftOffset();
+ segments[i].logicalRight += logicalLeftOffset();
+ }
+
+ return segments;
+}
+
+inline LayoutUnit borderBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
+{
+ switch (writingMode) {
+ case TopToBottomWritingMode: return renderer.borderTop();
+ case BottomToTopWritingMode: return renderer.borderBottom();
+ case LeftToRightWritingMode: return renderer.borderLeft();
+ case RightToLeftWritingMode: return renderer.borderRight();
+ }
+
+ ASSERT_NOT_REACHED();
+ return renderer.borderBefore();
+}
+
+inline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
+{
+ switch (writingMode) {
+ case TopToBottomWritingMode: return renderer.borderTop() + renderer.paddingTop();
+ case BottomToTopWritingMode: return renderer.borderBottom() + renderer.paddingBottom();
+ case LeftToRightWritingMode: return renderer.borderLeft() + renderer.paddingLeft();
+ case RightToLeftWritingMode: return renderer.borderRight() + renderer.paddingRight();
+ }
+
+ ASSERT_NOT_REACHED();
+ return renderer.borderAndPaddingBefore();
+}
+
+LayoutUnit ShapeOutsideInfo::logicalTopOffset() const
+{
+ switch (referenceBox(*m_renderer.style()->shapeOutside())) {
+ case MarginBox: return -m_renderer.marginBefore(m_renderer.containingBlock()->style());
+ case BorderBox: return LayoutUnit();
+ case PaddingBox: return borderBeforeInWritingMode(m_renderer, m_renderer.containingBlock()->style()->writingMode());
+ case ContentBox: return borderAndPaddingBeforeInWritingMode(m_renderer, m_renderer.containingBlock()->style()->writingMode());
+ case BoxMissing: break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return LayoutUnit();
+}
+
+inline LayoutUnit borderStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
+{
+ if (style->isHorizontalWritingMode()) {
+ if (style->isLeftToRightDirection())
+ return renderer.borderLeft();
+
+ return renderer.borderRight();
+ }
+ if (style->isLeftToRightDirection())
+ return renderer.borderTop();
+
+ return renderer.borderBottom();
+}
+
+inline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
+{
+ if (style->isHorizontalWritingMode()) {
+ if (style->isLeftToRightDirection())
+ return renderer.borderLeft() + renderer.paddingLeft();
+
+ return renderer.borderRight() + renderer.paddingRight();
+ }
+ if (style->isLeftToRightDirection())
+ return renderer.borderTop() + renderer.paddingTop();
+
+ return renderer.borderBottom() + renderer.paddingBottom();
+}
+
+LayoutUnit ShapeOutsideInfo::logicalLeftOffset() const
+{
+ switch (referenceBox(*m_renderer.style()->shapeOutside())) {
+ case MarginBox: return -m_renderer.marginStart(m_renderer.containingBlock()->style());
+ case BorderBox: return LayoutUnit();
+ case PaddingBox: return borderStartWithStyleForWritingMode(m_renderer, m_renderer.containingBlock()->style());
+ case ContentBox: return borderAndPaddingStartWithStyleForWritingMode(m_renderer, m_renderer.containingBlock()->style());
+ case BoxMissing: break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return LayoutUnit();
+}
+
+
+bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box)
+{
+ ShapeValue* shapeValue = box.style()->shapeOutside();
+ if (!box.isFloating() || !shapeValue)
return false;
switch (shapeValue->type()) {
case ShapeValue::Shape:
return shapeValue->shape();
case ShapeValue::Image:
- return shapeValue->isImageValid() && checkShapeImageOrigin(box->document(), *(shapeValue->image()->cachedImage()));
+ return shapeValue->isImageValid() && checkShapeImageOrigin(box.document(), *(shapeValue->image()));
case ShapeValue::Box:
return true;
- case ShapeValue::Outside:
- return false;
}
return false;
}
-void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow* containingBlock, const FloatingObject* floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight)
+void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight)
{
- LayoutUnit shapeTop = containingBlock->logicalTopForFloat(floatingObject) + std::max(LayoutUnit(), containingBlock->marginBeforeForChild(m_renderer));
- LayoutUnit floatRelativeLineTop = lineTop - shapeTop;
+ LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(&m_renderer);
+ LayoutUnit borderBoxLineTop = lineTop - borderBoxTop;
- if (shapeSizeDirty() || m_lineTop != floatRelativeLineTop || m_lineHeight != lineHeight) {
- m_lineTop = floatRelativeLineTop;
- m_shapeLineTop = floatRelativeLineTop - logicalTopOffset();
+ if (isShapeDirty() || m_borderBoxLineTop != borderBoxLineTop || m_lineHeight != lineHeight) {
+ m_borderBoxLineTop = borderBoxLineTop;
+ m_referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
m_lineHeight = lineHeight;
- LayoutUnit floatMarginBoxWidth = containingBlock->logicalWidthForFloat(floatingObject);
+ LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject);
if (lineOverlapsShapeBounds()) {
- SegmentList segments = computeSegmentsForLine(floatRelativeLineTop, lineHeight);
+ SegmentList segments = computeSegmentsForLine(borderBoxLineTop, lineHeight);
if (segments.size()) {
- LayoutUnit rawLeftMarginBoxDelta = segments.first().logicalLeft + containingBlock->marginStartForChild(m_renderer);
- m_leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth);
+ LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(&m_renderer) : containingBlock.marginEndForChild(&m_renderer);
+ LayoutUnit rawLeftMarginBoxDelta = segments.first().logicalLeft + logicalLeftMargin;
+ m_leftMarginBoxDelta = clampToLayoutUnit(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth);
- LayoutUnit rawRightMarginBoxDelta = segments.last().logicalRight - containingBlock->logicalWidthForChild(m_renderer) - containingBlock->marginEndForChild(m_renderer);
- m_rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
+ LayoutUnit logicalRightMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginEndForChild(&m_renderer) : containingBlock.marginStartForChild(&m_renderer);
+ LayoutUnit rawRightMarginBoxDelta = segments.last().logicalRight - containingBlock.logicalWidthForChild(&m_renderer) - logicalRightMargin;
+ m_rightMarginBoxDelta = clampToLayoutUnit(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
+ m_lineOverlapsShape = true;
return;
}
}
@@ -82,19 +303,45 @@ void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow*
// Lines that do not overlap the shape should act as if the float
// wasn't there for layout purposes. So we set the deltas to remove the
// entire width of the float.
- // FIXME: The latest CSS Shapes spec says that in this case, the
- // content should interact with previously stacked floats on the line
- // as if this outermost float did not exist. Perhaps obviously, this
- // solution cannot do that, and will be revisted when that part of the
- // spec is implemented.
m_leftMarginBoxDelta = floatMarginBoxWidth;
m_rightMarginBoxDelta = -floatMarginBoxWidth;
+ m_lineOverlapsShape = false;
}
}
-ShapeValue* ShapeOutsideInfo::shapeValue() const
+LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const
+{
+ LayoutRect physicalBoundingBox = computedShape().shapeMarginLogicalBoundingBox();
+ physicalBoundingBox.setX(physicalBoundingBox.x() + logicalLeftOffset());
+
+ if (m_renderer.style()->isFlippedBlocksWritingMode())
+ physicalBoundingBox.setY(m_renderer.logicalHeight() - physicalBoundingBox.maxY());
+ else
+ physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset());
+
+ if (!m_renderer.style()->isHorizontalWritingMode())
+ physicalBoundingBox = physicalBoundingBox.transposedRect();
+ else
+ physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset());
+
+ return physicalBoundingBox;
+}
+
+FloatPoint ShapeOutsideInfo::shapeToRendererPoint(FloatPoint point) const
+{
+ FloatPoint result = FloatPoint(point.x() + logicalLeftOffset(), point.y() + logicalTopOffset());
+ if (m_renderer.style()->isFlippedBlocksWritingMode())
+ result.setY(m_renderer.logicalHeight() - result.y());
+ if (!m_renderer.style()->isHorizontalWritingMode())
+ result = result.transposedPoint();
+ return result;
+}
+
+FloatSize ShapeOutsideInfo::shapeToRendererSize(FloatSize size) const
{
- return m_renderer->style()->shapeOutside();
+ if (!m_renderer.style()->isHorizontalWritingMode())
+ return size.transposedSize();
+ return size;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h
index 82b31f65f69..36276e91fdb 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h
@@ -30,8 +30,13 @@
#ifndef ShapeOutsideInfo_h
#define ShapeOutsideInfo_h
-#include "core/rendering/shapes/ShapeInfo.h"
+#include "core/rendering/shapes/Shape.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/ShapeValue.h"
+#include "platform/geometry/FloatRect.h"
#include "platform/geometry/LayoutSize.h"
+#include "wtf/OwnPtr.h"
+#include "wtf/Vector.h"
namespace WebCore {
@@ -39,35 +44,85 @@ class RenderBlockFlow;
class RenderBox;
class FloatingObject;
-class ShapeOutsideInfo FINAL : public ShapeInfo<RenderBox>, public MappedInfo<RenderBox, ShapeOutsideInfo> {
+class ShapeOutsideInfo FINAL {
+ WTF_MAKE_FAST_ALLOCATED;
public:
+ void setReferenceBoxLogicalSize(LayoutSize);
+
+ SegmentList computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const;
+
+ LayoutUnit shapeLogicalTop() const { return computedShape().shapeMarginLogicalBoundingBox().y() + logicalTopOffset(); }
+ LayoutUnit shapeLogicalBottom() const { return computedShape().shapeMarginLogicalBoundingBox().maxY() + logicalTopOffset(); }
+ LayoutUnit shapeLogicalLeft() const { return computedShape().shapeMarginLogicalBoundingBox().x() + logicalLeftOffset(); }
+ LayoutUnit shapeLogicalRight() const { return computedShape().shapeMarginLogicalBoundingBox().maxX() + logicalLeftOffset(); }
+ LayoutUnit shapeLogicalWidth() const { return computedShape().shapeMarginLogicalBoundingBox().width(); }
+ LayoutUnit shapeLogicalHeight() const { return computedShape().shapeMarginLogicalBoundingBox().height(); }
+
+ LayoutUnit logicalLineTop() const { return m_referenceBoxLineTop + logicalTopOffset(); }
+ LayoutUnit logicalLineBottom() const { return m_referenceBoxLineTop + m_lineHeight + logicalTopOffset(); }
+
LayoutUnit leftMarginBoxDelta() const { return m_leftMarginBoxDelta; }
LayoutUnit rightMarginBoxDelta() const { return m_rightMarginBoxDelta; }
+ bool lineOverlapsShape() const { return m_lineOverlapsShape; }
- void updateDeltasForContainingBlockLine(const RenderBlockFlow*, const FloatingObject*, LayoutUnit lineTop, LayoutUnit lineHeight);
+ static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox& renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); }
+ static bool isEnabledFor(const RenderBox&);
+ void updateDeltasForContainingBlockLine(const RenderBlockFlow&, const FloatingObject&, LayoutUnit lineTop, LayoutUnit lineHeight);
- static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox* renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); }
- static bool isEnabledFor(const RenderBox*);
+ bool lineOverlapsShapeBounds() const
+ {
+ return computedShape().lineOverlapsShapeMarginBounds(m_referenceBoxLineTop, m_lineHeight);
+ }
- virtual bool lineOverlapsShapeBounds() const OVERRIDE
+ static ShapeOutsideInfo& ensureInfo(const RenderBox& key)
{
- return computedShape()->lineOverlapsShapeMarginBounds(m_shapeLineTop, m_lineHeight);
+ InfoMap& infoMap = ShapeOutsideInfo::infoMap();
+ if (ShapeOutsideInfo* info = infoMap.get(&key))
+ return *info;
+ InfoMap::AddResult result = infoMap.add(&key, ShapeOutsideInfo::createInfo(key));
+ return *result.storedValue->value;
}
+ static void removeInfo(const RenderBox& key) { infoMap().remove(&key); }
+ static ShapeOutsideInfo* info(const RenderBox& key) { return infoMap().get(&key); }
+
+ void markShapeAsDirty() { m_shape.clear(); }
+ bool isShapeDirty() { return !m_shape.get(); }
+ LayoutSize shapeSize() const { return m_referenceBoxLogicalSize; }
+
+ LayoutRect computedShapePhysicalBoundingBox() const;
+ FloatPoint shapeToRendererPoint(FloatPoint) const;
+ FloatSize shapeToRendererSize(FloatSize) const;
+ const Shape& computedShape() const;
protected:
- virtual LayoutRect computedShapeLogicalBoundingBox() const OVERRIDE { return computedShape()->shapeMarginLogicalBoundingBox(); }
- virtual ShapeValue* shapeValue() const OVERRIDE;
- virtual void getIntervals(LayoutUnit lineTop, LayoutUnit lineHeight, SegmentList& segments) const OVERRIDE
+ ShapeOutsideInfo(const RenderBox& renderer)
+ : m_renderer(renderer)
+ , m_lineOverlapsShape(false)
+ { }
+
+private:
+ PassOwnPtr<Shape> createShapeForImage(StyleImage*, float shapeImageThreshold, WritingMode, float margin) const;
+
+ LayoutUnit logicalTopOffset() const;
+ LayoutUnit logicalLeftOffset() const;
+
+ typedef HashMap<const RenderBox*, OwnPtr<ShapeOutsideInfo> > InfoMap;
+ static InfoMap& infoMap()
{
- return computedShape()->getExcludedIntervals(lineTop, lineHeight, segments);
+ DEFINE_STATIC_LOCAL(InfoMap, staticInfoMap, ());
+ return staticInfoMap;
}
-private:
- ShapeOutsideInfo(const RenderBox* renderer) : ShapeInfo<RenderBox>(renderer) { }
+ LayoutUnit m_referenceBoxLineTop;
+ LayoutUnit m_lineHeight;
+ const RenderBox& m_renderer;
+ mutable OwnPtr<Shape> m_shape;
+ LayoutSize m_referenceBoxLogicalSize;
LayoutUnit m_leftMarginBoxDelta;
LayoutUnit m_rightMarginBoxDelta;
- LayoutUnit m_lineTop;
+ LayoutUnit m_borderBoxLineTop;
+ bool m_lineOverlapsShape;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.cpp
new file mode 100644
index 00000000000..ea8be8483a8
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.cpp
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/rendering/style/AppliedTextDecoration.h"
+
+namespace WebCore {
+
+AppliedTextDecoration::AppliedTextDecoration(TextDecoration line, TextDecorationStyle style, StyleColor color)
+ : m_line(line)
+ , m_style(style)
+ , m_color(color)
+{
+}
+
+AppliedTextDecoration::AppliedTextDecoration(TextDecoration line)
+ : m_line(line)
+ , m_style(TextDecorationStyleSolid)
+ , m_color(StyleColor::currentColor())
+{
+}
+
+AppliedTextDecoration::AppliedTextDecoration()
+ : m_line(TextDecorationUnderline)
+ , m_style(TextDecorationStyleSolid)
+ , m_color(StyleColor::currentColor())
+{
+}
+
+bool AppliedTextDecoration::operator==(const AppliedTextDecoration& o) const
+{
+ return m_color == o.m_color && m_line == o.m_line && m_style == o.m_style;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.h b/chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.h
new file mode 100644
index 00000000000..fd0df809194
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/AppliedTextDecoration.h
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef AppliedTextDecoration_h
+#define AppliedTextDecoration_h
+
+#include "core/css/StyleColor.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+class AppliedTextDecoration {
+public:
+ AppliedTextDecoration(TextDecoration, TextDecorationStyle, StyleColor);
+ explicit AppliedTextDecoration(TextDecoration);
+ AppliedTextDecoration();
+
+ TextDecoration line() const { return static_cast<TextDecoration>(m_line); }
+ TextDecorationStyle style() const { return static_cast<TextDecorationStyle>(m_style); }
+
+ bool isSimpleUnderline() const { return m_line == TextDecorationUnderline && m_style == TextDecorationStyleSolid && m_color.isCurrentColor(); }
+ bool operator==(const AppliedTextDecoration&) const;
+ bool operator!=(const AppliedTextDecoration& o) const { return !(*this == o); }
+
+private:
+ unsigned m_line : TextDecorationBits;
+ unsigned m_style : 3; // TextDecorationStyle
+ StyleColor m_color;
+};
+
+} // namespace WebCore
+
+#endif // AppliedTextDecoration_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.cpp
index 1eed605f291..a41a1d6393c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.cpp
@@ -28,70 +28,90 @@
*/
#include "config.h"
-
#include "core/rendering/style/BasicShapes.h"
+
+#include "core/css/BasicShapeFunctions.h"
+#include "platform/CalculationValue.h"
#include "platform/LengthFunctions.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/Path.h"
namespace WebCore {
+void BasicShapeCenterCoordinate::updateComputedLength()
+{
+ if (m_direction == TopLeft) {
+ m_computedLength = m_length.isUndefined() ? Length(0, Fixed) : m_length;
+ return;
+ }
+ if (m_length.isUndefined()) {
+ m_computedLength = Length(100, Percent);
+ return;
+ }
+
+ m_computedLength = m_length.subtractFromOneHundredPercent();
+}
+
bool BasicShape::canBlend(const BasicShape* other) const
{
// FIXME: Support animations between different shapes in the future.
- if (type() != other->type())
+ if (!other || !isSameType(*other))
return false;
// Just polygons with same number of vertices can be animated.
if (type() == BasicShape::BasicShapePolygonType
- && static_cast<const BasicShapePolygon*>(this)->values().size() != static_cast<const BasicShapePolygon*>(other)->values().size())
+ && (static_cast<const BasicShapePolygon*>(this)->values().size() != static_cast<const BasicShapePolygon*>(other)->values().size()
+ || static_cast<const BasicShapePolygon*>(this)->windRule() != static_cast<const BasicShapePolygon*>(other)->windRule()))
return false;
- return true;
+ // Circles with keywords for radii or center coordinates cannot be animated.
+ if (type() == BasicShape::BasicShapeCircleType) {
+ const BasicShapeCircle* thisCircle = static_cast<const BasicShapeCircle*>(this);
+ const BasicShapeCircle* otherCircle = static_cast<const BasicShapeCircle*>(other);
+ if (!thisCircle->radius().canBlend(otherCircle->radius()))
+ return false;
+ }
+
+ // Ellipses with keywords for radii or center coordinates cannot be animated.
+ if (type() != BasicShape::BasicShapeEllipseType)
+ return true;
+
+ const BasicShapeEllipse* thisEllipse = static_cast<const BasicShapeEllipse*>(this);
+ const BasicShapeEllipse* otherEllipse = static_cast<const BasicShapeEllipse*>(other);
+ return (thisEllipse->radiusX().canBlend(otherEllipse->radiusX())
+ && thisEllipse->radiusY().canBlend(otherEllipse->radiusY()));
}
-void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox)
+bool BasicShapeCircle::operator==(const BasicShape& o) const
{
- ASSERT(path.isEmpty());
- path.addRoundedRect(
- FloatRect(
- floatValueForLength(m_x, boundingBox.width()) + boundingBox.x(),
- floatValueForLength(m_y, boundingBox.height()) + boundingBox.y(),
- floatValueForLength(m_width, boundingBox.width()),
- floatValueForLength(m_height, boundingBox.height())
- ),
- FloatSize(
- floatValueForLength(m_cornerRadiusX, boundingBox.width()),
- floatValueForLength(m_cornerRadiusY, boundingBox.height())
- )
- );
+ if (!isSameType(o))
+ return false;
+ const BasicShapeCircle& other = toBasicShapeCircle(o);
+ return m_centerX == other.m_centerX && m_centerY == other.m_centerY && m_radius == other.m_radius;
}
-PassRefPtr<BasicShape> BasicShapeRectangle::blend(const BasicShape* other, double progress) const
+float BasicShapeCircle::floatValueForRadiusInBox(FloatSize boxSize) const
{
- ASSERT(type() == other->type());
+ if (m_radius.type() == BasicShapeRadius::Value)
+ return floatValueForLength(m_radius.value(), hypotf(boxSize.width(), boxSize.height()) / sqrtf(2));
- const BasicShapeRectangle* o = static_cast<const BasicShapeRectangle*>(other);
- RefPtr<BasicShapeRectangle> result = BasicShapeRectangle::create();
- result->setX(m_x.blend(o->x(), progress, ValueRangeAll));
- result->setY(m_y.blend(o->y(), progress, ValueRangeAll));
- result->setWidth(m_width.blend(o->width(), progress, ValueRangeNonNegative));
- result->setHeight(m_height.blend(o->height(), progress, ValueRangeNonNegative));
- result->setCornerRadiusX(m_cornerRadiusX.blend(o->cornerRadiusX(), progress, ValueRangeNonNegative));
- result->setCornerRadiusY(m_cornerRadiusY.blend(o->cornerRadiusY(), progress, ValueRangeNonNegative));
- return result.release();
+ FloatPoint center = floatPointForCenterCoordinate(m_centerX, m_centerY, boxSize);
+
+ if (m_radius.type() == BasicShapeRadius::ClosestSide)
+ return std::min(std::min(center.x(), boxSize.width() - center.x()), std::min(center.y(), boxSize.height() - center.y()));
+
+ // If radius.type() == BasicShapeRadius::FarthestSide.
+ return std::max(std::max(center.x(), boxSize.width() - center.x()), std::max(center.y(), boxSize.height() - center.y()));
}
void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
- float diagonal = sqrtf((boundingBox.width() * boundingBox.width() + boundingBox.height() * boundingBox.height()) / 2);
- float centerX = floatValueForLength(m_centerX, boundingBox.width());
- float centerY = floatValueForLength(m_centerY, boundingBox.height());
- float radius = floatValueForLength(m_radius, diagonal);
+ FloatPoint center = floatPointForCenterCoordinate(m_centerX, m_centerY, boundingBox.size());
+ float radius = floatValueForRadiusInBox(boundingBox.size());
path.addEllipse(FloatRect(
- centerX - radius + boundingBox.x(),
- centerY - radius + boundingBox.y(),
+ center.x() - radius + boundingBox.x(),
+ center.y() - radius + boundingBox.y(),
radius * 2,
radius * 2
));
@@ -100,25 +120,44 @@ void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
PassRefPtr<BasicShape> BasicShapeCircle::blend(const BasicShape* other, double progress) const
{
ASSERT(type() == other->type());
-
const BasicShapeCircle* o = static_cast<const BasicShapeCircle*>(other);
RefPtr<BasicShapeCircle> result = BasicShapeCircle::create();
- result->setCenterX(m_centerX.blend(o->centerX(), progress, ValueRangeAll));
- result->setCenterY(m_centerY.blend(o->centerY(), progress, ValueRangeAll));
- result->setRadius(m_radius.blend(o->radius(), progress, ValueRangeNonNegative));
+
+ result->setCenterX(m_centerX.blend(o->centerX(), progress));
+ result->setCenterY(m_centerY.blend(o->centerY(), progress));
+ result->setRadius(m_radius.blend(o->radius(), progress));
return result.release();
}
+bool BasicShapeEllipse::operator==(const BasicShape& o) const
+{
+ if (!isSameType(o))
+ return false;
+ const BasicShapeEllipse& other = toBasicShapeEllipse(o);
+ return m_centerX == other.m_centerX && m_centerY == other.m_centerY && m_radiusX == other.m_radiusX && m_radiusY == other.m_radiusY;
+}
+
+float BasicShapeEllipse::floatValueForRadiusInBox(const BasicShapeRadius& radius, float center, float boxWidthOrHeight) const
+{
+ if (radius.type() == BasicShapeRadius::Value)
+ return floatValueForLength(radius.value(), boxWidthOrHeight);
+
+ if (radius.type() == BasicShapeRadius::ClosestSide)
+ return std::min(center, boxWidthOrHeight - center);
+
+ ASSERT(radius.type() == BasicShapeRadius::FarthestSide);
+ return std::max(center, boxWidthOrHeight - center);
+}
+
void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
- float centerX = floatValueForLength(m_centerX, boundingBox.width());
- float centerY = floatValueForLength(m_centerY, boundingBox.height());
- float radiusX = floatValueForLength(m_radiusX, boundingBox.width());
- float radiusY = floatValueForLength(m_radiusY, boundingBox.height());
+ FloatPoint center = floatPointForCenterCoordinate(m_centerX, m_centerY, boundingBox.size());
+ float radiusX = floatValueForRadiusInBox(m_radiusX, center.x(), boundingBox.width());
+ float radiusY = floatValueForRadiusInBox(m_radiusY, center.y(), boundingBox.height());
path.addEllipse(FloatRect(
- centerX - radiusX + boundingBox.x(),
- centerY - radiusY + boundingBox.y(),
+ center.x() - radiusX + boundingBox.x(),
+ center.y() - radiusY + boundingBox.y(),
radiusX * 2,
radiusY * 2
));
@@ -127,13 +166,22 @@ void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
PassRefPtr<BasicShape> BasicShapeEllipse::blend(const BasicShape* other, double progress) const
{
ASSERT(type() == other->type());
-
const BasicShapeEllipse* o = static_cast<const BasicShapeEllipse*>(other);
RefPtr<BasicShapeEllipse> result = BasicShapeEllipse::create();
- result->setCenterX(m_centerX.blend(o->centerX(), progress, ValueRangeAll));
- result->setCenterY(m_centerY.blend(o->centerY(), progress, ValueRangeAll));
- result->setRadiusX(m_radiusX.blend(o->radiusX(), progress, ValueRangeNonNegative));
- result->setRadiusY(m_radiusY.blend(o->radiusY(), progress, ValueRangeNonNegative));
+
+ if (m_radiusX.type() != BasicShapeRadius::Value || o->radiusX().type() != BasicShapeRadius::Value
+ || m_radiusY.type() != BasicShapeRadius::Value || o->radiusY().type() != BasicShapeRadius::Value) {
+ result->setCenterX(o->centerX());
+ result->setCenterY(o->centerY());
+ result->setRadiusX(o->radiusX());
+ result->setRadiusY(o->radiusY());
+ return result;
+ }
+
+ result->setCenterX(m_centerX.blend(o->centerX(), progress));
+ result->setCenterY(m_centerY.blend(o->centerY(), progress));
+ result->setRadiusX(m_radiusX.blend(o->radiusX(), progress));
+ result->setRadiusY(m_radiusY.blend(o->radiusY(), progress));
return result.release();
}
@@ -157,7 +205,7 @@ void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
PassRefPtr<BasicShape> BasicShapePolygon::blend(const BasicShape* other, double progress) const
{
- ASSERT(type() == other->type());
+ ASSERT(other && isSameType(*other));
const BasicShapePolygon* o = static_cast<const BasicShapePolygon*>(other);
ASSERT(m_values.size() == o->values().size());
@@ -178,7 +226,21 @@ PassRefPtr<BasicShape> BasicShapePolygon::blend(const BasicShape* other, double
return result.release();
}
-void BasicShapeInsetRectangle::path(Path& path, const FloatRect& boundingBox)
+bool BasicShapePolygon::operator==(const BasicShape& o) const
+{
+ if (!isSameType(o))
+ return false;
+ const BasicShapePolygon& other = toBasicShapePolygon(o);
+ return m_windRule == other.m_windRule && m_values == other.m_values;
+}
+
+static FloatSize floatSizeForLengthSize(const LengthSize& lengthSize, const FloatRect& boundingBox)
+{
+ return FloatSize(floatValueForLength(lengthSize.width(), boundingBox.width()),
+ floatValueForLength(lengthSize.height(), boundingBox.height()));
+}
+
+void BasicShapeInset::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
float left = floatValueForLength(m_left, boundingBox.width());
@@ -190,25 +252,33 @@ void BasicShapeInsetRectangle::path(Path& path, const FloatRect& boundingBox)
std::max<float>(boundingBox.width() - left - floatValueForLength(m_right, boundingBox.width()), 0),
std::max<float>(boundingBox.height() - top - floatValueForLength(m_bottom, boundingBox.height()), 0)
),
- FloatSize(
- floatValueForLength(m_cornerRadiusX, boundingBox.width()),
- floatValueForLength(m_cornerRadiusY, boundingBox.height())
- )
+ floatSizeForLengthSize(m_topLeftRadius, boundingBox),
+ floatSizeForLengthSize(m_topRightRadius, boundingBox),
+ floatSizeForLengthSize(m_bottomLeftRadius, boundingBox),
+ floatSizeForLengthSize(m_bottomRightRadius, boundingBox)
);
}
-PassRefPtr<BasicShape> BasicShapeInsetRectangle::blend(const BasicShape* other, double progress) const
+PassRefPtr<BasicShape> BasicShapeInset::blend(const BasicShape* other, double) const
{
ASSERT(type() == other->type());
+ // FIXME: Implement blend for BasicShapeInset.
+ return nullptr;
+}
- const BasicShapeInsetRectangle* o = static_cast<const BasicShapeInsetRectangle*>(other);
- RefPtr<BasicShapeInsetRectangle> result = BasicShapeInsetRectangle::create();
- result->setTop(m_top.blend(o->top(), progress, ValueRangeNonNegative));
- result->setRight(m_right.blend(o->right(), progress, ValueRangeNonNegative));
- result->setBottom(m_bottom.blend(o->bottom(), progress, ValueRangeNonNegative));
- result->setLeft(m_left.blend(o->left(), progress, ValueRangeNonNegative));
- result->setCornerRadiusX(m_cornerRadiusX.blend(o->cornerRadiusX(), progress, ValueRangeNonNegative));
- result->setCornerRadiusY(m_cornerRadiusY.blend(o->cornerRadiusY(), progress, ValueRangeNonNegative));
- return result.release();
+bool BasicShapeInset::operator==(const BasicShape& o) const
+{
+ if (!isSameType(o))
+ return false;
+ const BasicShapeInset& other = toBasicShapeInset(o);
+ return m_right == other.m_right
+ && m_top == other.m_top
+ && m_bottom == other.m_bottom
+ && m_left == other.m_left
+ && m_topLeftRadius == other.m_topLeftRadius
+ && m_topRightRadius == other.m_topRightRadius
+ && m_bottomRightRadius == other.m_bottomRightRadius
+ && m_bottomLeftRadius == other.m_bottomLeftRadius;
}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.h b/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.h
index b8735a82095..6f414688e28 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/BasicShapes.h
@@ -30,7 +30,9 @@
#ifndef BasicShapes_h
#define BasicShapes_h
+#include "core/rendering/style/RenderStyleConstants.h"
#include "platform/Length.h"
+#include "platform/LengthSize.h"
#include "platform/graphics/WindRule.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
@@ -39,6 +41,7 @@
namespace WebCore {
class FloatRect;
+class FloatSize;
class Path;
class BasicShape : public RefCounted<BasicShape> {
@@ -46,117 +49,174 @@ public:
virtual ~BasicShape() { }
enum Type {
- BasicShapeRectangleType = 1,
- BasicShapeCircleType = 2,
- BasicShapeEllipseType = 3,
- BasicShapePolygonType = 4,
- BasicShapeInsetRectangleType = 5
+ BasicShapeEllipseType,
+ BasicShapePolygonType,
+ BasicShapeCircleType,
+ BasicShapeInsetType
};
bool canBlend(const BasicShape*) const;
+ bool isSameType(const BasicShape& other) const { return type() == other.type(); }
virtual void path(Path&, const FloatRect&) = 0;
virtual WindRule windRule() const { return RULE_NONZERO; }
virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const = 0;
+ virtual bool operator==(const BasicShape&) const = 0;
virtual Type type() const = 0;
+
protected:
- BasicShape() { }
+ BasicShape()
+ {
+ }
+
};
-class BasicShapeRectangle : public BasicShape {
+#define DEFINE_BASICSHAPE_TYPE_CASTS(thisType) \
+ DEFINE_TYPE_CASTS(thisType, BasicShape, value, value->type() == BasicShape::thisType##Type, value.type() == BasicShape::thisType##Type)
+
+class BasicShapeCenterCoordinate {
public:
- static PassRefPtr<BasicShapeRectangle> create() { return adoptRef(new BasicShapeRectangle); }
-
- Length x() const { return m_x; }
- Length y() const { return m_y; }
- Length width() const { return m_width; }
- Length height() const { return m_height; }
- Length cornerRadiusX() const { return m_cornerRadiusX; }
- Length cornerRadiusY() const { return m_cornerRadiusY; }
-
- void setX(Length x) { m_x = x; }
- void setY(Length y) { m_y = y; }
- void setWidth(Length width) { m_width = width; }
- void setHeight(Length height) { m_height = height; }
- void setCornerRadiusX(Length radiusX)
+ enum Direction {
+ TopLeft,
+ BottomRight
+ };
+ BasicShapeCenterCoordinate()
+ : m_direction(TopLeft)
+ , m_length(Undefined)
{
- ASSERT(!radiusX.isUndefined());
- m_cornerRadiusX = radiusX;
+ updateComputedLength();
}
- void setCornerRadiusY(Length radiusY)
+
+ BasicShapeCenterCoordinate(Direction direction, const Length& length)
+ : m_direction(direction)
+ , m_length(length)
{
- ASSERT(!radiusY.isUndefined());
- m_cornerRadiusY = radiusY;
+ updateComputedLength();
}
- virtual void path(Path&, const FloatRect&) OVERRIDE;
- virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+ BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate& other)
+ : m_direction(other.direction())
+ , m_length(other.length())
+ , m_computedLength(other.m_computedLength)
+ {
+ }
+
+ bool operator==(const BasicShapeCenterCoordinate& other) const { return m_direction == other.m_direction && m_length == other.m_length && m_computedLength == other.m_computedLength; }
+
+ Direction direction() const { return m_direction; }
+ const Length& length() const { return m_length; }
+ const Length& computedLength() const { return m_computedLength; }
+
+ BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& other, double progress) const
+ {
+ return BasicShapeCenterCoordinate(TopLeft, m_computedLength.blend(other.m_computedLength, progress, ValueRangeAll));
+ }
- virtual Type type() const { return BasicShapeRectangleType; }
private:
- BasicShapeRectangle() { }
-
- Length m_y;
- Length m_x;
- Length m_width;
- Length m_height;
- Length m_cornerRadiusX;
- Length m_cornerRadiusY;
+ Direction m_direction;
+ Length m_length;
+ Length m_computedLength;
+
+ void updateComputedLength();
};
-class BasicShapeCircle : public BasicShape {
+class BasicShapeRadius {
+public:
+ enum Type {
+ Value,
+ ClosestSide,
+ FarthestSide
+ };
+ BasicShapeRadius() : m_value(Undefined), m_type(ClosestSide) { }
+ explicit BasicShapeRadius(const Length& v) : m_value(v), m_type(Value) { }
+ explicit BasicShapeRadius(Type t) : m_value(Undefined), m_type(t) { }
+ BasicShapeRadius(const BasicShapeRadius& other) : m_value(other.value()), m_type(other.type()) { }
+ bool operator==(const BasicShapeRadius& other) const { return m_type == other.m_type && m_value == other.m_value; }
+
+ const Length& value() const { return m_value; }
+ Type type() const { return m_type; }
+
+ bool canBlend(const BasicShapeRadius& other) const
+ {
+ // FIXME determine how to interpolate between keywords. See issue 330248.
+ return m_type == Value && other.type() == Value;
+ }
+
+ BasicShapeRadius blend(const BasicShapeRadius& other, double progress) const
+ {
+ if (m_type != Value || other.type() != Value)
+ return BasicShapeRadius(other);
+
+ return BasicShapeRadius(m_value.blend(other.value(), progress, ValueRangeNonNegative));
+ }
+
+private:
+ Length m_value;
+ Type m_type;
+
+};
+
+class BasicShapeCircle FINAL : public BasicShape {
public:
static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); }
- Length centerX() const { return m_centerX; }
- Length centerY() const { return m_centerY; }
- Length radius() const { return m_radius; }
+ const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
+ const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
+ const BasicShapeRadius& radius() const { return m_radius; }
- void setCenterX(Length centerX) { m_centerX = centerX; }
- void setCenterY(Length centerY) { m_centerY = centerY; }
- void setRadius(Length radius) { m_radius = radius; }
+ float floatValueForRadiusInBox(FloatSize) const;
+ void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
+ void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
+ void setRadius(BasicShapeRadius radius) { m_radius = radius; }
virtual void path(Path&, const FloatRect&) OVERRIDE;
virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+ virtual bool operator==(const BasicShape&) const OVERRIDE;
- virtual Type type() const { return BasicShapeCircleType; }
+ virtual Type type() const OVERRIDE { return BasicShapeCircleType; }
private:
BasicShapeCircle() { }
- Length m_centerX;
- Length m_centerY;
- Length m_radius;
+ BasicShapeCenterCoordinate m_centerX;
+ BasicShapeCenterCoordinate m_centerY;
+ BasicShapeRadius m_radius;
};
-class BasicShapeEllipse : public BasicShape {
+DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeCircle);
+
+class BasicShapeEllipse FINAL : public BasicShape {
public:
static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); }
- Length centerX() const { return m_centerX; }
- Length centerY() const { return m_centerY; }
- Length radiusX() const { return m_radiusX; }
- Length radiusY() const { return m_radiusY; }
+ const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
+ const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
+ const BasicShapeRadius& radiusX() const { return m_radiusX; }
+ const BasicShapeRadius& radiusY() const { return m_radiusY; }
+ float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const;
- void setCenterX(Length centerX) { m_centerX = centerX; }
- void setCenterY(Length centerY) { m_centerY = centerY; }
- void setRadiusX(Length radiusX) { m_radiusX = radiusX; }
- void setRadiusY(Length radiusY) { m_radiusY = radiusY; }
+ void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
+ void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
+ void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = radiusX; }
+ void setRadiusY(BasicShapeRadius radiusY) { m_radiusY = radiusY; }
virtual void path(Path&, const FloatRect&) OVERRIDE;
virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+ virtual bool operator==(const BasicShape&) const OVERRIDE;
- virtual Type type() const { return BasicShapeEllipseType; }
+ virtual Type type() const OVERRIDE { return BasicShapeEllipseType; }
private:
BasicShapeEllipse() { }
- Length m_centerX;
- Length m_centerY;
- Length m_radiusX;
- Length m_radiusY;
+ BasicShapeCenterCoordinate m_centerX;
+ BasicShapeCenterCoordinate m_centerY;
+ BasicShapeRadius m_radiusX;
+ BasicShapeRadius m_radiusY;
};
-class BasicShapePolygon : public BasicShape {
+DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeEllipse);
+
+class BasicShapePolygon FINAL : public BasicShape {
public:
static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); }
@@ -165,14 +225,15 @@ public:
Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); }
void setWindRule(WindRule windRule) { m_windRule = windRule; }
- void appendPoint(Length x, Length y) { m_values.append(x); m_values.append(y); }
+ void appendPoint(const Length& x, const Length& y) { m_values.append(x); m_values.append(y); }
virtual void path(Path&, const FloatRect&) OVERRIDE;
virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+ virtual bool operator==(const BasicShape&) const OVERRIDE;
- virtual WindRule windRule() const { return m_windRule; }
+ virtual WindRule windRule() const OVERRIDE { return m_windRule; }
- virtual Type type() const { return BasicShapePolygonType; }
+ virtual Type type() const OVERRIDE { return BasicShapePolygonType; }
private:
BasicShapePolygon()
: m_windRule(RULE_NONZERO)
@@ -182,45 +243,52 @@ private:
Vector<Length> m_values;
};
-class BasicShapeInsetRectangle : public BasicShape {
+DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapePolygon);
+
+class BasicShapeInset : public BasicShape {
public:
- static PassRefPtr<BasicShapeInsetRectangle> create() { return adoptRef(new BasicShapeInsetRectangle); }
-
- Length top() const { return m_top; }
- Length right() const { return m_right; }
- Length bottom() const { return m_bottom; }
- Length left() const { return m_left; }
- Length cornerRadiusX() const { return m_cornerRadiusX; }
- Length cornerRadiusY() const { return m_cornerRadiusY; }
-
- void setTop(Length top) { m_top = top; }
- void setRight(Length right) { m_right = right; }
- void setBottom(Length bottom) { m_bottom = bottom; }
- void setLeft(Length left) { m_left = left; }
- void setCornerRadiusX(Length radiusX)
- {
- ASSERT(!radiusX.isUndefined());
- m_cornerRadiusX = radiusX;
- }
- void setCornerRadiusY(Length radiusY)
- {
- ASSERT(!radiusY.isUndefined());
- m_cornerRadiusY = radiusY;
- }
+ static PassRefPtr<BasicShapeInset> create() { return adoptRef(new BasicShapeInset); }
+
+ const Length& top() const { return m_top; }
+ const Length& right() const { return m_right; }
+ const Length& bottom() const { return m_bottom; }
+ const Length& left() const { return m_left; }
+
+ const LengthSize& topLeftRadius() const { return m_topLeftRadius; }
+ const LengthSize& topRightRadius() const { return m_topRightRadius; }
+ const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; }
+ const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; }
+
+ void setTop(const Length& top) { m_top = top; }
+ void setRight(const Length& right) { m_right = right; }
+ void setBottom(const Length& bottom) { m_bottom = bottom; }
+ void setLeft(const Length& left) { m_left = left; }
+
+ void setTopLeftRadius(const LengthSize& radius) { m_topLeftRadius = radius; }
+ void setTopRightRadius(const LengthSize& radius) { m_topRightRadius = radius; }
+ void setBottomRightRadius(const LengthSize& radius) { m_bottomRightRadius = radius; }
+ void setBottomLeftRadius(const LengthSize& radius) { m_bottomLeftRadius = radius; }
virtual void path(Path&, const FloatRect&) OVERRIDE;
virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+ virtual bool operator==(const BasicShape&) const OVERRIDE;
- virtual Type type() const { return BasicShapeInsetRectangleType; }
+ virtual Type type() const OVERRIDE { return BasicShapeInsetType; }
private:
- BasicShapeInsetRectangle() { }
+ BasicShapeInset() { }
Length m_right;
Length m_top;
Length m_bottom;
Length m_left;
- Length m_cornerRadiusX;
- Length m_cornerRadiusY;
+
+ LengthSize m_topLeftRadius;
+ LengthSize m_topRightRadius;
+ LengthSize m_bottomRightRadius;
+ LengthSize m_bottomLeftRadius;
};
+
+DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeInset);
+
}
#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/BorderData.h b/chromium/third_party/WebKit/Source/core/rendering/style/BorderData.h
index bf96bcf797c..4df4644ebfe 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/BorderData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/BorderData.h
@@ -94,6 +94,19 @@ public:
&& m_topLeft == o.m_topLeft && m_topRight == o.m_topRight && m_bottomLeft == o.m_bottomLeft && m_bottomRight == o.m_bottomRight;
}
+ bool visuallyEqual(const BorderData& o) const
+ {
+ return m_left.visuallyEqual(o.m_left)
+ && m_right.visuallyEqual(o.m_right)
+ && m_top.visuallyEqual(o.m_top)
+ && m_bottom.visuallyEqual(o.m_bottom)
+ && m_image == o.m_image
+ && m_topLeft == o.m_topLeft
+ && m_topRight == o.m_topRight
+ && m_bottomLeft == o.m_bottomLeft
+ && m_bottomRight == o.m_bottomRight;
+ }
+
bool operator!=(const BorderData& o) const
{
return !(*this == o);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/BorderValue.h b/chromium/third_party/WebKit/Source/core/rendering/style/BorderValue.h
index dcd5096df0b..211f0be97f9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/BorderValue.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/BorderValue.h
@@ -25,6 +25,7 @@
#ifndef BorderValue_h
#define BorderValue_h
+#include "core/css/StyleColor.h"
#include "core/rendering/style/RenderStyleConstants.h"
#include "platform/graphics/Color.h"
@@ -35,7 +36,7 @@ friend class RenderStyle;
public:
BorderValue()
: m_color(0)
- , m_colorIsValid(false)
+ , m_colorIsCurrentColor(true)
, m_width(3)
, m_style(BNONE)
, m_isAuto(AUTO_OFF)
@@ -49,7 +50,7 @@ public:
bool isTransparent() const
{
- return m_colorIsValid && !alphaChannel(m_color);
+ return !m_colorIsCurrentColor && !m_color.alpha();
}
bool isVisible(bool checkStyle = true) const
@@ -59,7 +60,17 @@ public:
bool operator==(const BorderValue& o) const
{
- return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_colorIsValid == o.m_colorIsValid;
+ return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_colorIsCurrentColor == o.m_colorIsCurrentColor;
+ }
+
+ // The default width is 3px, but if the style is none we compute a value of 0 (in RenderStyle itself)
+ bool visuallyEqual(const BorderValue& o) const
+ {
+ if (m_style == BNONE && o.m_style == BNONE)
+ return true;
+ if (m_style == BHIDDEN && o.m_style == BHIDDEN)
+ return true;
+ return *this == o;
}
bool operator!=(const BorderValue& o) const
@@ -67,20 +78,20 @@ public:
return !(*this == o);
}
- void setColor(const Color& color)
+ void setColor(const StyleColor& color)
{
- m_color = color.rgb();
- m_colorIsValid = color.isValid();
+ m_color = color.resolve(Color());
+ m_colorIsCurrentColor = color.isCurrentColor();
}
- Color color() const { return Color(m_color, m_colorIsValid); }
+ StyleColor color() const { return m_colorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_color); }
unsigned width() const { return m_width; }
EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); }
protected:
- RGBA32 m_color;
- unsigned m_colorIsValid : 1;
+ Color m_color;
+ unsigned m_colorIsCurrentColor : 1;
unsigned m_width : 26;
unsigned m_style : 4; // EBorderStyle
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/CachedUAStyle.h b/chromium/third_party/WebKit/Source/core/rendering/style/CachedUAStyle.h
index f56d66f3395..10bed857f56 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/CachedUAStyle.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/CachedUAStyle.h
@@ -32,32 +32,31 @@ namespace WebCore {
// applyMatchedProperties for later use during adjustRenderStyle.
class CachedUAStyle {
public:
- CachedUAStyle()
- : hasAppearance(false)
- , backgroundLayers(BackgroundFillLayer)
- { }
+ static PassOwnPtr<CachedUAStyle> create(const RenderStyle* style)
+ {
+ return adoptPtr(new CachedUAStyle(style));
+ }
+
+ bool hasAppearance;
+ BorderData border;
+ FillLayer backgroundLayers;
+ StyleColor backgroundColor;
+private:
explicit CachedUAStyle(const RenderStyle* style)
- : hasAppearance(style->hasAppearance())
+ : hasAppearance(true)
, backgroundLayers(BackgroundFillLayer)
+ , backgroundColor(StyleColor::currentColor())
{
- // RenderTheme::adjustStyle is the only consumer of this data.
- // It only cares about the styles if appearance is set,
- // so we cheat and don't bother to copy them when !hasAppearance.
- if (!hasAppearance)
- return;
+ ASSERT(style->hasAppearance());
border = style->border();
backgroundLayers = *style->backgroundLayers();
backgroundColor = style->backgroundColor();
}
-
- bool hasAppearance;
- BorderData border;
- FillLayer backgroundLayers;
- Color backgroundColor;
};
+
} // namespace WebCore
#endif // CachedUAStyle_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/CollapsedBorderValue.h b/chromium/third_party/WebKit/Source/core/rendering/style/CollapsedBorderValue.h
index ef16dba2322..ac7b0575557 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/CollapsedBorderValue.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/CollapsedBorderValue.h
@@ -33,7 +33,7 @@ class CollapsedBorderValue {
public:
CollapsedBorderValue()
: m_color(0)
- , m_colorIsValid(false)
+ , m_colorIsCurrentColor(true)
, m_width(0)
, m_style(BNONE)
, m_precedence(BOFF)
@@ -41,9 +41,9 @@ public:
{
}
- CollapsedBorderValue(const BorderValue& border, const Color& color, EBorderPrecedence precedence)
- : m_color(color.rgb())
- , m_colorIsValid(color.isValid())
+ CollapsedBorderValue(const BorderValue& border, const StyleColor& color, EBorderPrecedence precedence)
+ : m_color(color.resolve(Color()))
+ , m_colorIsCurrentColor(color.isCurrentColor())
, m_width(border.nonZero() ? border.width() : 0)
, m_style(border.style())
, m_precedence(precedence)
@@ -54,7 +54,7 @@ public:
unsigned width() const { return m_style > BHIDDEN ? m_width : 0; }
EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); }
bool exists() const { return m_precedence != BOFF; }
- Color color() const { return Color(m_color, m_colorIsValid); }
+ StyleColor color() const { return m_colorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_color); }
bool isTransparent() const { return m_transparent; }
EBorderPrecedence precedence() const { return static_cast<EBorderPrecedence>(m_precedence); }
@@ -64,8 +64,8 @@ public:
}
private:
- RGBA32 m_color;
- unsigned m_colorIsValid : 1;
+ Color m_color;
+ unsigned m_colorIsCurrentColor : 1;
unsigned m_width : 23;
unsigned m_style : 4; // EBorderStyle
unsigned m_precedence : 3; // EBorderPrecedence
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/ContentData.h b/chromium/third_party/WebKit/Source/core/rendering/style/ContentData.h
index 77dd5619e9c..a01f6cc018f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/ContentData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/ContentData.h
@@ -66,7 +66,7 @@ private:
OwnPtr<ContentData> m_next;
};
-class ImageContentData : public ContentData {
+class ImageContentData FINAL : public ContentData {
friend class ContentData;
public:
const StyleImage* image() const { return m_image.get(); }
@@ -89,7 +89,7 @@ private:
{
}
- virtual PassOwnPtr<ContentData> cloneInternal() const
+ virtual PassOwnPtr<ContentData> cloneInternal() const OVERRIDE
{
RefPtr<StyleImage> image = const_cast<StyleImage*>(this->image());
return create(image.release());
@@ -98,7 +98,7 @@ private:
RefPtr<StyleImage> m_image;
};
-class TextContentData : public ContentData {
+class TextContentData FINAL : public ContentData {
friend class ContentData;
public:
const String& text() const { return m_text; }
@@ -120,12 +120,12 @@ private:
{
}
- virtual PassOwnPtr<ContentData> cloneInternal() const { return create(text()); }
+ virtual PassOwnPtr<ContentData> cloneInternal() const OVERRIDE { return create(text()); }
String m_text;
};
-class CounterContentData : public ContentData {
+class CounterContentData FINAL : public ContentData {
friend class ContentData;
public:
const CounterContent* counter() const { return m_counter.get(); }
@@ -140,7 +140,7 @@ private:
{
}
- virtual PassOwnPtr<ContentData> cloneInternal() const
+ virtual PassOwnPtr<ContentData> cloneInternal() const OVERRIDE
{
OwnPtr<CounterContent> counterData = adoptPtr(new CounterContent(*counter()));
return create(counterData.release());
@@ -156,7 +156,7 @@ private:
OwnPtr<CounterContent> m_counter;
};
-class QuoteContentData : public ContentData {
+class QuoteContentData FINAL : public ContentData {
friend class ContentData;
public:
QuoteType quote() const { return m_quote; }
@@ -178,7 +178,7 @@ private:
{
}
- virtual PassOwnPtr<ContentData> cloneInternal() const { return create(quote()); }
+ virtual PassOwnPtr<ContentData> cloneInternal() const OVERRIDE { return create(quote()); }
QuoteType m_quote;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/CursorList.h b/chromium/third_party/WebKit/Source/core/rendering/style/CursorList.h
deleted file mode 100644
index 90bd00c181d..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/CursorList.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 CursorList_h
-#define CursorList_h
-
-#include "core/rendering/style/CursorData.h"
-#include "wtf/RefCounted.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-class CursorList : public RefCounted<CursorList> {
-public:
- static PassRefPtr<CursorList> create()
- {
- return adoptRef(new CursorList);
- }
-
- const CursorData& operator[](int i) const { return m_vector[i]; }
- CursorData& operator[](int i) { return m_vector[i]; }
- const CursorData& at(size_t i) const { return m_vector.at(i); }
- CursorData& at(size_t i) { return m_vector.at(i); }
-
- bool operator==(const CursorList& o) const { return m_vector == o.m_vector; }
- bool operator!=(const CursorList& o) const { return m_vector != o.m_vector; }
-
- size_t size() const { return m_vector.size(); }
- void append(const CursorData& cursorData) { m_vector.append(cursorData); }
-
-private:
- CursorList()
- {
- }
-
- Vector<CursorData> m_vector;
-};
-
-} // namespace WebCore
-
-#endif // CursorList_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/DataEquivalency.h b/chromium/third_party/WebKit/Source/core/rendering/style/DataEquivalency.h
new file mode 100644
index 00000000000..87d92388bbe
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/DataEquivalency.h
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DataEquivalency_h
+#define DataEquivalency_h
+
+#include "wtf/OwnPtr.h"
+#include "wtf/RefPtr.h"
+
+namespace WebCore {
+
+template <typename T>
+bool dataEquivalent(const T* a, const T* b)
+{
+ if (a == b)
+ return true;
+ if (!a || !b)
+ return false;
+ return *a == *b;
+}
+
+template <typename T>
+bool dataEquivalent(const RefPtr<T>& a, const RefPtr<T>& b)
+{
+ return dataEquivalent(a.get(), b.get());
+}
+
+template <typename T>
+bool dataEquivalent(const Persistent<T>& a, const Persistent<T>& b)
+{
+ return dataEquivalent(a.get(), b.get());
+}
+
+template <typename T>
+bool dataEquivalent(const Member<T>& a, const Member<T>& b)
+{
+ return dataEquivalent(a.get(), b.get());
+}
+
+template <typename T>
+bool dataEquivalent(const OwnPtr<T>& a, const OwnPtr<T>& b)
+{
+ return dataEquivalent(a.get(), b.get());
+}
+
+} // namespace WebCore
+
+#endif // DataEquivalency_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.cpp
index 5a621e0c1f2..907a80d5b52 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.cpp
@@ -22,6 +22,8 @@
#include "config.h"
#include "core/rendering/style/FillLayer.h"
+#include "core/rendering/style/DataEquivalency.h"
+
namespace WebCore {
struct SameSizeAsFillLayer {
@@ -34,8 +36,8 @@ struct SameSizeAsFillLayer {
LengthSize m_sizeLength;
- unsigned m_bitfields: 32;
- unsigned m_bitfields2: 1;
+ unsigned m_bitfields1;
+ unsigned m_bitfields2;
};
COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
@@ -159,7 +161,7 @@ bool FillLayer::operator==(const FillLayer& o) const
{
// We do not check the "isSet" booleans for each property, since those are only used during initial construction
// to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway.
- return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
+ return dataEquivalent(m_image, o.m_image) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
&& m_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
&& m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
&& m_blendMode == o.m_blendMode && m_origin == o.m_origin && m_repeatX == o.m_repeatX
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.h b/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.h
index 790f202db1b..f79abaf9588 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/FillLayer.h
@@ -40,7 +40,7 @@ struct FillSize {
{
}
- FillSize(EFillSizeType t, LengthSize l)
+ FillSize(EFillSizeType t, const LengthSize& l)
: type(t)
, size(l)
{
@@ -66,8 +66,8 @@ public:
~FillLayer();
StyleImage* image() const { return m_image.get(); }
- Length xPosition() const { return m_xPosition; }
- Length yPosition() const { return m_yPosition; }
+ const Length& xPosition() const { return m_xPosition; }
+ const Length& yPosition() const { return m_yPosition; }
BackgroundEdgeOrigin backgroundXOrigin() const { return static_cast<BackgroundEdgeOrigin>(m_backgroundXOrigin); }
BackgroundEdgeOrigin backgroundYOrigin() const { return static_cast<BackgroundEdgeOrigin>(m_backgroundYOrigin); }
EFillAttachment attachment() const { return static_cast<EFillAttachment>(m_attachment); }
@@ -77,7 +77,7 @@ public:
EFillRepeat repeatY() const { return static_cast<EFillRepeat>(m_repeatY); }
CompositeOperator composite() const { return static_cast<CompositeOperator>(m_composite); }
blink::WebBlendMode blendMode() const { return static_cast<blink::WebBlendMode>(m_blendMode); }
- LengthSize sizeLength() const { return m_sizeLength; }
+ const LengthSize& sizeLength() const { return m_sizeLength; }
EFillSizeType sizeType() const { return static_cast<EFillSizeType>(m_sizeType); }
FillSize size() const { return FillSize(static_cast<EFillSizeType>(m_sizeType), m_sizeLength); }
EMaskSourceType maskSourceType() const { return static_cast<EMaskSourceType>(m_maskSourceType); }
@@ -101,8 +101,8 @@ public:
bool isMaskSourceTypeSet() const { return m_maskSourceTypeSet; }
void setImage(PassRefPtr<StyleImage> i) { m_image = i; m_imageSet = true; }
- void setXPosition(Length position) { m_xPosition = position; m_xPosSet = true; m_backgroundXOriginSet = false; m_backgroundXOrigin = LeftEdge; }
- void setYPosition(Length position) { m_yPosition = position; m_yPosSet = true; m_backgroundYOriginSet = false; m_backgroundYOrigin = TopEdge; }
+ void setXPosition(const Length& position) { m_xPosition = position; m_xPosSet = true; m_backgroundXOriginSet = false; m_backgroundXOrigin = LeftEdge; }
+ void setYPosition(const Length& position) { m_yPosition = position; m_yPosSet = true; m_backgroundYOriginSet = false; m_backgroundYOrigin = TopEdge; }
void setBackgroundXOrigin(BackgroundEdgeOrigin origin) { m_backgroundXOrigin = origin; m_backgroundXOriginSet = true; }
void setBackgroundYOrigin(BackgroundEdgeOrigin origin) { m_backgroundYOrigin = origin; m_backgroundYOriginSet = true; }
void setAttachment(EFillAttachment attachment) { m_attachment = attachment; m_attachmentSet = true; }
@@ -113,7 +113,7 @@ public:
void setComposite(CompositeOperator c) { m_composite = c; m_compositeSet = true; }
void setBlendMode(blink::WebBlendMode b) { m_blendMode = b; m_blendModeSet = true; }
void setSizeType(EFillSizeType b) { m_sizeType = b; }
- void setSizeLength(LengthSize l) { m_sizeLength = l; }
+ void setSizeLength(const LengthSize& l) { m_sizeLength = l; }
void setSize(FillSize f) { m_sizeType = f.type; m_sizeLength = f.size; }
void setMaskSourceType(EMaskSourceType m) { m_maskSourceType = m; m_maskSourceTypeSet = true; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/GridCoordinate.h b/chromium/third_party/WebKit/Source/core/rendering/style/GridCoordinate.h
index 937d3f08b9b..fa78aa22a79 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/GridCoordinate.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/GridCoordinate.h
@@ -31,36 +31,36 @@
#ifndef GridCoordinate_h
#define GridCoordinate_h
-#include "core/rendering/style/GridPosition.h"
+#include "core/rendering/style/GridResolvedPosition.h"
#include "wtf/HashMap.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
-// A span in a single direction (either rows or columns). Note that |initialPositionIndex|
-// and |finalPositionIndex| are grid areas' indexes, NOT grid lines'. Iterating over the
-// span should include both |initialPositionIndex| and |finalPositionIndex| to be correct.
+// A span in a single direction (either rows or columns). Note that |resolvedInitialPosition|
+// and |resolvedFinalPosition| are grid areas' indexes, NOT grid lines'. Iterating over the
+// span should include both |resolvedInitialPosition| and |resolvedFinalPosition| to be correct.
struct GridSpan {
- static PassOwnPtr<GridSpan> create(size_t initialPosition, size_t finalPosition)
+ static PassOwnPtr<GridSpan> create(const GridResolvedPosition& resolvedInitialPosition, const GridResolvedPosition& resolvedFinalPosition)
{
- return adoptPtr(new GridSpan(initialPosition, finalPosition));
+ return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
}
- static PassOwnPtr<GridSpan> createWithSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
+ static PassOwnPtr<GridSpan> createWithSpanAgainstOpposite(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
{
// 'span 1' is contained inside a single grid track regardless of the direction.
// That's why the CSS span value is one more than the offset we apply.
size_t positionOffset = position.spanPosition() - 1;
if (side == ColumnStartSide || side == RowStartSide) {
- size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition - positionOffset);
+ GridResolvedPosition initialResolvedPosition = GridResolvedPosition(std::max<int>(0, resolvedOppositePosition.toInt() - positionOffset));
return GridSpan::create(initialResolvedPosition, resolvedOppositePosition);
}
- return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition + positionOffset);
+ return GridSpan::create(resolvedOppositePosition, GridResolvedPosition(resolvedOppositePosition.toInt() + positionOffset));
}
- static PassOwnPtr<GridSpan> createWithNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side, const Vector<size_t>& gridLines)
+ static PassOwnPtr<GridSpan> createWithNamedSpanAgainstOpposite(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side, const Vector<size_t>& gridLines)
{
if (side == RowStartSide || side == ColumnStartSide)
return createWithInitialNamedSpanAgainstOpposite(resolvedOppositePosition, position, gridLines);
@@ -68,50 +68,71 @@ struct GridSpan {
return createWithFinalNamedSpanAgainstOpposite(resolvedOppositePosition, position, gridLines);
}
- static PassOwnPtr<GridSpan> createWithInitialNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
+ static PassOwnPtr<GridSpan> createWithInitialNamedSpanAgainstOpposite(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
{
// The grid line inequality needs to be strict (which doesn't match the after / end case) because |resolvedOppositePosition|
// is already converted to an index in our grid representation (ie one was removed from the grid line to account for the side).
size_t firstLineBeforeOppositePositionIndex = 0;
- const size_t* firstLineBeforeOppositePosition = std::lower_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition);
- if (firstLineBeforeOppositePosition != gridLines.end())
+ const size_t* firstLineBeforeOppositePosition = std::lower_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition.toInt());
+ if (firstLineBeforeOppositePosition != gridLines.end()) {
+ if (*firstLineBeforeOppositePosition > resolvedOppositePosition.toInt() && firstLineBeforeOppositePosition != gridLines.begin())
+ --firstLineBeforeOppositePosition;
+
firstLineBeforeOppositePositionIndex = firstLineBeforeOppositePosition - gridLines.begin();
+ }
size_t gridLineIndex = std::max<int>(0, firstLineBeforeOppositePositionIndex - position.spanPosition() + 1);
- size_t resolvedGridLinePosition = gridLines[gridLineIndex];
+ GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition(gridLines[gridLineIndex]);
if (resolvedGridLinePosition > resolvedOppositePosition)
resolvedGridLinePosition = resolvedOppositePosition;
return GridSpan::create(resolvedGridLinePosition, resolvedOppositePosition);
}
- static PassOwnPtr<GridSpan> createWithFinalNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
+ static PassOwnPtr<GridSpan> createWithFinalNamedSpanAgainstOpposite(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
{
size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1;
- const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition);
+ const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition.toInt());
if (firstLineAfterOppositePosition != gridLines.end())
firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - gridLines.begin();
size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
- size_t resolvedGridLinePosition = GridPosition::adjustGridPositionForAfterEndSide(gridLines[gridLineIndex]);
+ GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition::adjustGridPositionForAfterEndSide(gridLines[gridLineIndex]);
if (resolvedGridLinePosition < resolvedOppositePosition)
resolvedGridLinePosition = resolvedOppositePosition;
return GridSpan::create(resolvedOppositePosition, resolvedGridLinePosition);
}
- GridSpan(size_t initialPosition, size_t finalPosition)
- : initialPositionIndex(initialPosition)
- , finalPositionIndex(finalPosition)
+ GridSpan(const GridResolvedPosition& resolvedInitialPosition, const GridResolvedPosition& resolvedFinalPosition)
+ : resolvedInitialPosition(resolvedInitialPosition)
+ , resolvedFinalPosition(resolvedFinalPosition)
{
- ASSERT(initialPositionIndex <= finalPositionIndex);
+ ASSERT(resolvedInitialPosition <= resolvedFinalPosition);
}
bool operator==(const GridSpan& o) const
{
- return initialPositionIndex == o.initialPositionIndex && finalPositionIndex == o.finalPositionIndex;
+ return resolvedInitialPosition == o.resolvedInitialPosition && resolvedFinalPosition == o.resolvedFinalPosition;
+ }
+
+ size_t integerSpan() const
+ {
+ return resolvedFinalPosition.toInt() - resolvedInitialPosition.toInt() + 1;
+ }
+
+ GridResolvedPosition resolvedInitialPosition;
+ GridResolvedPosition resolvedFinalPosition;
+
+ typedef GridResolvedPosition iterator;
+
+ iterator begin() const
+ {
+ return resolvedInitialPosition;
}
- size_t initialPositionIndex;
- size_t finalPositionIndex;
+ iterator end() const
+ {
+ return resolvedFinalPosition.next();
+ }
};
// This represents a grid area that spans in both rows' and columns' direction.
@@ -139,6 +160,22 @@ struct GridCoordinate {
return !(*this == o);
}
+ GridResolvedPosition positionForSide(GridPositionSide side) const
+ {
+ switch (side) {
+ case ColumnStartSide:
+ return columns.resolvedInitialPosition;
+ case ColumnEndSide:
+ return columns.resolvedFinalPosition;
+ case RowStartSide:
+ return rows.resolvedInitialPosition;
+ case RowEndSide:
+ return rows.resolvedFinalPosition;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
GridSpan columns;
GridSpan rows;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/GridLength.h b/chromium/third_party/WebKit/Source/core/rendering/style/GridLength.h
index dadf7dac255..e822d08ab0b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/GridLength.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/GridLength.h
@@ -40,17 +40,17 @@ namespace WebCore {
// an new unit to Length.h.
class GridLength {
public:
- GridLength()
- : m_length(Undefined)
+ GridLength(const Length& length)
+ : m_length(length)
, m_flex(0)
, m_type(LengthType)
{
+ ASSERT(!length.isUndefined());
}
- GridLength(const Length& length)
- : m_length(length)
- , m_flex(0)
- , m_type(LengthType)
+ explicit GridLength(double flex)
+ : m_flex(flex)
+ , m_type(FlexType)
{
}
@@ -58,14 +58,8 @@ public:
bool isFlex() const { return m_type == FlexType; }
const Length& length() const { ASSERT(isLength()); return m_length; }
- Length& length() { ASSERT(isLength()); return m_length; }
double flex() const { ASSERT(isFlex()); return m_flex; }
- void setFlex(double flex)
- {
- m_type = FlexType;
- m_flex = flex;
- }
bool operator==(const GridLength& o) const
{
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/GridPosition.h b/chromium/third_party/WebKit/Source/core/rendering/style/GridPosition.h
index 133cdd55123..bb404909546 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/GridPosition.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/GridPosition.h
@@ -42,13 +42,6 @@ enum GridPositionType {
NamedGridAreaPosition // <ident>
};
-enum GridPositionSide {
- ColumnStartSide,
- ColumnEndSide,
- RowStartSide,
- RowEndSide
-};
-
class GridPosition {
public:
GridPosition()
@@ -57,20 +50,6 @@ public:
{
}
- static size_t adjustGridPositionForAfterEndSide(size_t resolvedPosition)
- {
- return resolvedPosition ? resolvedPosition - 1 : 0;
- }
-
- static size_t adjustGridPositionForSide(size_t resolvedPosition, GridPositionSide side)
- {
- // An item finishing on the N-th line belongs to the N-1-th cell.
- if (side == ColumnEndSide || side == RowEndSide)
- return adjustGridPositionForAfterEndSide(resolvedPosition);
-
- return resolvedPosition;
- }
-
bool isPositive() const { return integerPosition() > 0; }
GridPositionType type() const { return m_type; }
@@ -85,6 +64,12 @@ public:
m_namedGridLine = namedGridLine;
}
+ void setAutoPosition()
+ {
+ m_type = AutoPosition;
+ m_integerPosition = 0;
+ }
+
// 'span' values cannot be negative, yet we reuse the <integer> position which can
// be. This means that we have to convert the span position to an integer, losing
// some precision here. It shouldn't be an issue in practice though.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.cpp
new file mode 100644
index 00000000000..b537048b75c
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.cpp
@@ -0,0 +1,253 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/rendering/style/GridResolvedPosition.h"
+
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/style/GridCoordinate.h"
+
+namespace WebCore {
+
+static const NamedGridLinesMap& gridLinesForSide(const RenderStyle& style, GridPositionSide side)
+{
+ return (side == ColumnStartSide || side == ColumnEndSide) ? style.namedGridColumnLines() : style.namedGridRowLines();
+}
+
+static inline String implicitNamedGridLineForSide(const String& lineName, GridPositionSide side)
+{
+ return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-start" : "-end");
+}
+
+static bool isValidNamedLineOrArea(const String& lineName, const RenderStyle& style, GridPositionSide side)
+{
+ const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side);
+
+ return gridLineNames.contains(implicitNamedGridLineForSide(lineName, side)) || gridLineNames.contains(lineName);
+}
+
+static GridPositionSide calculateInitialPositionSide(GridTrackSizingDirection direction)
+{
+ return (direction == ForColumns) ? ColumnStartSide : RowStartSide;
+}
+
+static GridPositionSide calculateFinalPositionSide(GridTrackSizingDirection direction)
+{
+ return (direction == ForColumns) ? ColumnEndSide : RowEndSide;
+}
+
+void GridResolvedPosition::initialAndFinalPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, GridPosition& initialPosition, GridPosition& finalPosition)
+{
+ initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnStart() : gridItem.style()->gridRowStart();
+ finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd() : gridItem.style()->gridRowEnd();
+ GridPositionSide initialPositionSide = calculateInitialPositionSide(direction);
+ GridPositionSide finalPositionSide = calculateFinalPositionSide(direction);
+
+ // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to
+ // overwrite the specified values.
+ if (initialPosition.isSpan() && finalPosition.isSpan())
+ finalPosition.setAutoPosition();
+
+ // Try to early detect the case of non existing named grid lines. This way we could assume later that
+ // GridResolvedPosition::resolveGrisPositionFromStyle() always return a valid resolved position.
+ if (initialPosition.isNamedGridArea() && !isValidNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, initialPositionSide))
+ initialPosition.setAutoPosition();
+
+ if (finalPosition.isNamedGridArea() && !isValidNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide))
+ finalPosition.setAutoPosition();
+
+ // If the grid item has an automatic position and a grid span for a named line in a given dimension, instead treat the grid span as one.
+ if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.namedGridLine().isNull())
+ finalPosition.setSpanPosition(1, String());
+ if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.namedGridLine().isNull())
+ initialPosition.setSpanPosition(1, String());
+}
+
+GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, const GridResolvedPosition& resolvedInitialPosition)
+{
+ GridPosition initialPosition, finalPosition;
+ initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, initialPosition, finalPosition);
+
+ GridPositionSide finalPositionSide = calculateFinalPositionSide(direction);
+
+ // This method will only be used when both positions need to be resolved against the opposite one.
+ ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition());
+
+ GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition;
+
+ if (initialPosition.isSpan()) {
+ resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, initialPosition, finalPositionSide)->resolvedFinalPosition;
+ } else if (finalPosition.isSpan()) {
+ resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, finalPosition, finalPositionSide)->resolvedFinalPosition;
+ }
+
+ return GridSpan(resolvedInitialPosition, resolvedFinalPosition);
+}
+
+PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction)
+{
+ GridPosition initialPosition, finalPosition;
+ initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, initialPosition, finalPosition);
+
+ GridPositionSide initialPositionSide = calculateInitialPositionSide(direction);
+ GridPositionSide finalPositionSide = calculateFinalPositionSide(direction);
+
+ if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
+ if (gridContainerStyle.gridAutoFlow() == AutoFlowNone)
+ return adoptPtr(new GridSpan(0, 0));
+
+ // We can't get our grid positions without running the auto placement algorithm.
+ return nullptr;
+ }
+
+ if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
+ // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
+ GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide);
+ return resolveGridPositionAgainstOppositePosition(gridContainerStyle, finalResolvedPosition, initialPosition, initialPositionSide);
+ }
+
+ if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
+ // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
+ GridResolvedPosition initialResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide);
+ return resolveGridPositionAgainstOppositePosition(gridContainerStyle, initialResolvedPosition, finalPosition, finalPositionSide);
+ }
+
+ GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide);
+ GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide);
+
+ // If 'grid-after' specifies a line at or before that specified by 'grid-before', it computes to 'span 1'.
+ if (resolvedFinalPosition < resolvedInitialPosition)
+ resolvedFinalPosition = resolvedInitialPosition;
+
+ return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
+}
+
+size_t GridResolvedPosition::explicitGridColumnCount(const RenderStyle& gridContainerStyle)
+{
+ return gridContainerStyle.gridTemplateColumns().size();
+}
+
+size_t GridResolvedPosition::explicitGridRowCount(const RenderStyle& gridContainerStyle)
+{
+ return gridContainerStyle.gridTemplateRows().size();
+}
+
+size_t GridResolvedPosition::explicitGridSizeForSide(const RenderStyle& gridContainerStyle, GridPositionSide side)
+{
+ return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount(gridContainerStyle) : explicitGridRowCount(gridContainerStyle);
+}
+
+GridResolvedPosition GridResolvedPosition::resolveNamedGridLinePositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
+{
+ ASSERT(!position.namedGridLine().isNull());
+
+ const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyle, side);
+ NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
+ if (it == gridLinesNames.end()) {
+ if (position.isPositive())
+ return GridResolvedPosition(0);
+ const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side);
+ return adjustGridPositionForSide(lastLine, side);
+ }
+
+ size_t namedGridLineIndex;
+ if (position.isPositive())
+ namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
+ else
+ namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
+ return adjustGridPositionForSide(it->value[namedGridLineIndex], side);
+}
+
+GridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
+{
+ switch (position.type()) {
+ case ExplicitPosition: {
+ ASSERT(position.integerPosition());
+
+ if (!position.namedGridLine().isNull())
+ return resolveNamedGridLinePositionFromStyle(gridContainerStyle, position, side);
+
+ // Handle <integer> explicit position.
+ if (position.isPositive())
+ return adjustGridPositionForSide(position.integerPosition() - 1, side);
+
+ size_t resolvedPosition = abs(position.integerPosition()) - 1;
+ const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, side);
+
+ // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
+ if (endOfTrack < resolvedPosition)
+ return GridResolvedPosition(0);
+
+ return adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
+ }
+ case NamedGridAreaPosition:
+ {
+ // First attempt to match the grid area’s edge to a named grid area: if there is a named line with the name
+ // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such
+ // line to the grid item’s placement.
+ String namedGridLine = position.namedGridLine();
+ ASSERT(isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side));
+
+ const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerStyle, side);
+ NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side));
+ if (implicitLineIter != gridLineNames.end())
+ return adjustGridPositionForSide(implicitLineIter->value[0], side);
+
+ // Otherwise, if there is a named line with the specified name, contributes the first such line to the grid
+ // item’s placement.
+ NamedGridLinesMap::const_iterator explicitLineIter = gridLineNames.find(namedGridLine);
+ if (explicitLineIter != gridLineNames.end())
+ return adjustGridPositionForSide(explicitLineIter->value[0], side);
+
+ // If none of the above works specs mandate us to treat it as auto BUT we should have detected it before calling
+ // this function in GridResolvedPosition::resolveGridPositionsFromStyle(). We should be also covered by the
+ // ASSERT at the beginning of this block.
+ ASSERT_NOT_REACHED();
+ return GridResolvedPosition(0);
+ }
+ case AutoPosition:
+ case SpanPosition:
+ // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
+ ASSERT_NOT_REACHED();
+ return GridResolvedPosition(0);
+ }
+ ASSERT_NOT_REACHED();
+ return GridResolvedPosition(0);
+}
+
+PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
+{
+ if (position.isAuto())
+ return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
+
+ ASSERT(position.isSpan());
+ ASSERT(position.spanPosition() > 0);
+
+ if (!position.namedGridLine().isNull()) {
+ // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
+ return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, resolvedOppositePosition, position, side);
+ }
+
+ return GridSpan::createWithSpanAgainstOpposite(resolvedOppositePosition, position, side);
+}
+
+PassOwnPtr<GridSpan> GridResolvedPosition::resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
+{
+ ASSERT(position.isSpan());
+ ASSERT(!position.namedGridLine().isNull());
+ // Negative positions are not allowed per the specification and should have been handled during parsing.
+ ASSERT(position.spanPosition() > 0);
+
+ const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyle, side);
+ NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
+
+ // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
+ // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
+ if (it == gridLinesNames.end())
+ return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
+
+ return GridSpan::createWithNamedSpanAgainstOpposite(resolvedOppositePosition, position, side, it->value);
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.h b/chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.h
new file mode 100644
index 00000000000..e9a79566736
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/GridResolvedPosition.h
@@ -0,0 +1,125 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GridResolvedPosition_h
+#define GridResolvedPosition_h
+
+#include "core/rendering/style/GridPosition.h"
+
+namespace WebCore {
+
+struct GridSpan;
+class RenderBox;
+class RenderStyle;
+
+enum GridPositionSide {
+ ColumnStartSide,
+ ColumnEndSide,
+ RowStartSide,
+ RowEndSide
+};
+
+enum GridTrackSizingDirection {
+ ForColumns,
+ ForRows
+};
+
+// This class represents an index into one of the dimensions of the grid array.
+// Wraps a size_t integer just for the purpose of knowing what we manipulate in the grid code.
+class GridResolvedPosition {
+public:
+ static GridResolvedPosition adjustGridPositionForAfterEndSide(size_t resolvedPosition)
+ {
+ return resolvedPosition ? GridResolvedPosition(resolvedPosition - 1) : GridResolvedPosition(0);
+ }
+
+ static GridResolvedPosition adjustGridPositionForSide(size_t resolvedPosition, GridPositionSide side)
+ {
+ // An item finishing on the N-th line belongs to the N-1-th cell.
+ if (side == ColumnEndSide || side == RowEndSide)
+ return adjustGridPositionForAfterEndSide(resolvedPosition);
+
+ return GridResolvedPosition(resolvedPosition);
+ }
+
+ static void initialAndFinalPositionsFromStyle(const RenderStyle&, const RenderBox&, GridTrackSizingDirection, GridPosition &initialPosition, GridPosition &finalPosition);
+ static GridSpan resolveGridPositionsFromAutoPlacementPosition(const RenderStyle&, const RenderBox&, GridTrackSizingDirection, const GridResolvedPosition&);
+ static PassOwnPtr<GridSpan> resolveGridPositionsFromStyle(const RenderStyle&, const RenderBox&, GridTrackSizingDirection);
+ static GridResolvedPosition resolveNamedGridLinePositionFromStyle(const RenderStyle&, const GridPosition&, GridPositionSide);
+ static GridResolvedPosition resolveGridPositionFromStyle(const RenderStyle&, const GridPosition&, GridPositionSide);
+ static PassOwnPtr<GridSpan> resolveGridPositionAgainstOppositePosition(const RenderStyle&, const GridResolvedPosition& resolvedOppositePosition, const GridPosition&, GridPositionSide);
+ static PassOwnPtr<GridSpan> resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle&, const GridResolvedPosition& resolvedOppositePosition, const GridPosition&, GridPositionSide);
+
+ GridResolvedPosition(size_t position)
+ : m_integerPosition(position)
+ {
+ }
+
+ GridResolvedPosition(const GridPosition& position, GridPositionSide side)
+ {
+ ASSERT(position.integerPosition());
+ size_t integerPosition = position.integerPosition() - 1;
+
+ m_integerPosition = adjustGridPositionForSide(integerPosition, side).toInt();
+ }
+
+ GridResolvedPosition& operator++()
+ {
+ m_integerPosition++;
+ return *this;
+ }
+
+ bool operator==(const GridResolvedPosition& other) const
+ {
+ return m_integerPosition == other.m_integerPosition;
+ }
+
+ bool operator!=(const GridResolvedPosition& other) const
+ {
+ return m_integerPosition != other.m_integerPosition;
+ }
+
+ bool operator<(const GridResolvedPosition& other) const
+ {
+ return m_integerPosition < other.m_integerPosition;
+ }
+
+ bool operator>(const GridResolvedPosition& other) const
+ {
+ return m_integerPosition > other.m_integerPosition;
+ }
+
+ bool operator<=(const GridResolvedPosition& other) const
+ {
+ return m_integerPosition <= other.m_integerPosition;
+ }
+
+ bool operator>=(const GridResolvedPosition& other) const
+ {
+ return m_integerPosition >= other.m_integerPosition;
+ }
+
+ size_t toInt() const
+ {
+ return m_integerPosition;
+ }
+
+ GridResolvedPosition next() const
+ {
+ return GridResolvedPosition(m_integerPosition + 1);
+ }
+
+ static size_t explicitGridColumnCount(const RenderStyle&);
+ static size_t explicitGridRowCount(const RenderStyle&);
+
+private:
+
+ static size_t explicitGridSizeForSide(const RenderStyle&, GridPositionSide);
+
+ size_t m_integerPosition;
+};
+
+} // namespace WebCore
+
+#endif // GridResolvedPosition_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/GridTrackSize.h b/chromium/third_party/WebKit/Source/core/rendering/style/GridTrackSize.h
index 584b47a4024..b64e5e3bc21 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/GridTrackSize.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/GridTrackSize.h
@@ -42,30 +42,27 @@ enum GridTrackSizeType {
class GridTrackSize {
public:
- GridTrackSize()
+ GridTrackSize(const GridLength& length)
: m_type(LengthTrackSizing)
- , m_minTrackBreadth(Undefined)
- , m_maxTrackBreadth(Undefined)
+ , m_minTrackBreadth(length)
+ , m_maxTrackBreadth(length)
, m_minTrackBreadthIsMinOrMaxContent(false)
, m_minTrackBreadthIsMaxContent(false)
, m_maxTrackBreadthIsMinOrMaxContent(false)
, m_maxTrackBreadthIsMaxContent(false)
{
- // Someone has to set a valid lenght type through setLength or
- // setMinMax before using the object.
+ cacheMinMaxTrackBreadthTypes();
}
- GridTrackSize(LengthType type)
- : m_type(LengthTrackSizing)
- , m_minTrackBreadth(type)
- , m_maxTrackBreadth(type)
+ GridTrackSize(const GridLength& minTrackBreadth, const GridLength& maxTrackBreadth)
+ : m_type(MinMaxTrackSizing)
+ , m_minTrackBreadth(minTrackBreadth)
+ , m_maxTrackBreadth(maxTrackBreadth)
, m_minTrackBreadthIsMinOrMaxContent(false)
, m_minTrackBreadthIsMaxContent(false)
, m_maxTrackBreadthIsMinOrMaxContent(false)
, m_maxTrackBreadthIsMaxContent(false)
{
- ASSERT(type != Undefined);
-
cacheMinMaxTrackBreadthTypes();
}
@@ -74,24 +71,13 @@ public:
ASSERT(m_type == LengthTrackSizing);
ASSERT(m_minTrackBreadth == m_maxTrackBreadth);
const GridLength& minTrackBreadth = m_minTrackBreadth;
- ASSERT(!minTrackBreadth.isLength() || !minTrackBreadth.length().isUndefined());
return minTrackBreadth;
}
- void setLength(const GridLength& length)
- {
- m_type = LengthTrackSizing;
- m_minTrackBreadth = length;
- m_maxTrackBreadth = length;
-
- cacheMinMaxTrackBreadthTypes();
- }
-
const GridLength& minTrackBreadth() const
{
- ASSERT(!m_minTrackBreadth.isLength() || !m_minTrackBreadth.length().isUndefined());
if (m_minTrackBreadth.isLength() && m_minTrackBreadth.length().isAuto()) {
- DEFINE_STATIC_LOCAL(GridLength, minContent, (MinContent));
+ DEFINE_STATIC_LOCAL(GridLength, minContent, (Length(MinContent)));
return minContent;
}
return m_minTrackBreadth;
@@ -99,27 +85,19 @@ public:
const GridLength& maxTrackBreadth() const
{
- ASSERT(!m_maxTrackBreadth.isLength() || !m_maxTrackBreadth.length().isUndefined());
if (m_maxTrackBreadth.isLength() && m_maxTrackBreadth.length().isAuto()) {
- DEFINE_STATIC_LOCAL(GridLength, maxContent, (MaxContent));
+ DEFINE_STATIC_LOCAL(GridLength, maxContent, (Length(MaxContent)));
return maxContent;
}
return m_maxTrackBreadth;
}
- void setMinMax(const GridLength& minTrackBreadth, const GridLength& maxTrackBreadth)
- {
- m_type = MinMaxTrackSizing;
- m_minTrackBreadth = minTrackBreadth;
- m_maxTrackBreadth = maxTrackBreadth;
-
- cacheMinMaxTrackBreadthTypes();
- }
-
GridTrackSizeType type() const { return m_type; }
bool isContentSized() const { return m_minTrackBreadth.isContentSized() || m_maxTrackBreadth.isContentSized(); }
+ bool isPercentage() const { return m_type == LengthTrackSizing && length().isLength() && length().length().isPercent(); }
+
bool operator==(const GridTrackSize& other) const
{
return m_type == other.m_type && m_minTrackBreadth == other.m_minTrackBreadth && m_maxTrackBreadth == other.m_maxTrackBreadth;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.cpp
index 2ed58360ee1..4ddaf8a5789 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.cpp
@@ -28,27 +28,6 @@
namespace WebCore {
-void KeyframeValue::addProperties(const StylePropertySet* propertySet)
-{
- if (!propertySet)
- return;
- unsigned propertyCount = propertySet->propertyCount();
- for (unsigned i = 0; i < propertyCount; ++i) {
- CSSPropertyID property = propertySet->propertyAt(i).id();
- // Timing-function within keyframes is special, because it is not animated; it just
- // describes the timing function between this keyframe and the next.
- if (property != CSSPropertyWebkitAnimationTimingFunction && property != CSSPropertyAnimationTimingFunction)
- addProperty(property);
- }
-}
-
-TimingFunction* KeyframeValue::timingFunction(const RenderStyle& keyframeStyle)
-{
- const CSSAnimationDataList* animations = keyframeStyle.animations();
- ASSERT(animations && !animations->isEmpty());
- return animations->animation(0)->timingFunction();
-}
-
KeyframeList::~KeyframeList()
{
clear();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.h b/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.h
index ee2d237b505..26f7b9e76d7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/KeyframeList.h
@@ -25,7 +25,7 @@
#ifndef KeyframeList_h
#define KeyframeList_h
-#include "CSSPropertyNames.h"
+#include "core/CSSPropertyNames.h"
#include "core/rendering/style/StyleInheritedData.h"
#include "wtf/HashSet.h"
#include "wtf/RefPtr.h"
@@ -36,8 +36,6 @@ namespace WebCore {
class RenderObject;
class RenderStyle;
-class StylePropertySet;
-class TimingFunction;
class KeyframeValue {
public:
@@ -47,7 +45,6 @@ public:
{
}
- void addProperties(const StylePropertySet*);
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; }
@@ -58,8 +55,6 @@ public:
const RenderStyle* style() const { return m_style.get(); }
void setStyle(PassRefPtr<RenderStyle> style) { m_style = style; }
- static TimingFunction* timingFunction(const RenderStyle& keyframeStyle);
-
private:
double m_key;
HashSet<CSSPropertyID> m_properties; // The properties specified in this keyframe.
@@ -71,8 +66,8 @@ public:
KeyframeList(RenderObject&, const AtomicString& animationName)
: m_animationName(animationName)
{
- insert(KeyframeValue(0, 0));
- insert(KeyframeValue(1, 0));
+ insert(KeyframeValue(0, nullptr));
+ insert(KeyframeValue(1, nullptr));
}
~KeyframeList();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/NinePieceImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/NinePieceImage.cpp
index 383ca14283a..12c050849b1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/NinePieceImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/NinePieceImage.cpp
@@ -24,6 +24,8 @@
#include "config.h"
#include "core/rendering/style/NinePieceImage.h"
+#include "core/rendering/style/DataEquivalency.h"
+
namespace WebCore {
static DataRef<NinePieceImageData>& defaultData()
@@ -55,7 +57,7 @@ NinePieceImageData::NinePieceImageData()
: fill(false)
, horizontalRule(StretchImageRule)
, verticalRule(StretchImageRule)
- , image(0)
+ , image(nullptr)
, imageSlices(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent))
, borderSlices(1.0, 1.0, 1.0, 1.0)
, outset(Length(0, Fixed), Length(0, Fixed), Length(0, Fixed), Length(0, Fixed))
@@ -76,7 +78,7 @@ NinePieceImageData::NinePieceImageData(const NinePieceImageData& other)
bool NinePieceImageData::operator==(const NinePieceImageData& other) const
{
- return StyleImage::imagesEquivalent(image.get(), other.image.get())
+ return dataEquivalent(image, other.image)
&& imageSlices == other.imageSlices
&& fill == other.fill
&& borderSlices == other.borderSlices
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/OutlineValue.h b/chromium/third_party/WebKit/Source/core/rendering/style/OutlineValue.h
index ccf3c272a01..e70b23229e6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/OutlineValue.h
+++ b/chromium/third_party/WebKit/Source/core/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_colorIsValid == o.m_colorIsValid && m_offset == o.m_offset && m_isAuto == o.m_isAuto;
+ return BorderValue::operator==(o) && m_offset == o.m_offset && m_isAuto == o.m_isAuto;
}
bool operator!=(const OutlineValue& o) const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.cpp
index a6ef8e9e120..5ec5c0c9374 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.cpp
@@ -64,13 +64,4 @@ const String QuotesData::getCloseQuote(int index) const
return m_quotePairs.at(index).second;
}
-bool QuotesData::equals(const QuotesData* a, const QuotesData* b)
-{
- if (a == b)
- return true;
- if (!a || !b)
- return false;
- return a->m_quotePairs == b->m_quotePairs;
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.h b/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.h
index 94e89e37e10..f8db17b82b9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/QuotesData.h
@@ -35,8 +35,8 @@ public:
static PassRefPtr<QuotesData> create(const String open, const String close);
static PassRefPtr<QuotesData> create(UChar open1, UChar close1, UChar open2, UChar close2);
- // FIXME: this should be an operator==.
- static bool equals(const QuotesData*, const QuotesData*);
+ bool operator==(const QuotesData& o) const { return m_quotePairs == o.m_quotePairs; }
+ bool operator!=(const QuotesData& o) const { return !(*this == o); }
void addPair(const std::pair<String, String> quotePair);
const String getOpenQuote(int index) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.cpp
index 2bbea394980..6b072146cfb 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.cpp
@@ -24,18 +24,20 @@
#include "core/rendering/style/RenderStyle.h"
#include <algorithm>
-#include "RuntimeEnabledFeatures.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/rendering/RenderTheme.h"
#include "core/rendering/TextAutosizer.h"
+#include "core/rendering/style/AppliedTextDecoration.h"
#include "core/rendering/style/ContentData.h"
-#include "core/rendering/style/CursorList.h"
#include "core/rendering/style/QuotesData.h"
#include "core/rendering/style/ShadowList.h"
#include "core/rendering/style/StyleImage.h"
#include "core/rendering/style/StyleInheritedData.h"
+#include "platform/LengthFunctions.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/Font.h"
#include "platform/fonts/FontSelector.h"
+#include "platform/geometry/FloatRoundedRect.h"
#include "wtf/MathExtras.h"
using namespace std;
@@ -124,6 +126,7 @@ ALWAYS_INLINE RenderStyle::RenderStyle(DefaultStyleTag)
rareNonInheritedData.access()->m_marquee.init();
rareNonInheritedData.access()->m_multiCol.init();
rareNonInheritedData.access()->m_transform.init();
+ rareNonInheritedData.access()->m_willChange.init();
rareNonInheritedData.access()->m_filter.init();
rareNonInheritedData.access()->m_grid.init();
rareNonInheritedData.access()->m_gridItem.init();
@@ -147,7 +150,7 @@ ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
{
}
-static StyleRecalcChange comparePseudoStyles(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+static StyleRecalcChange diffPseudoStyles(const RenderStyle* oldStyle, const RenderStyle* newStyle)
{
// If the pseudoStyles have changed, we want any StyleRecalcChange that is not NoChange
// because setStyle will do the right thing with anything else.
@@ -166,7 +169,7 @@ static StyleRecalcChange comparePseudoStyles(const RenderStyle* oldStyle, const
return NoChange;
}
-StyleRecalcChange RenderStyle::compare(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+StyleRecalcChange RenderStyle::stylePropagationDiff(const RenderStyle* oldStyle, const RenderStyle* newStyle)
{
if ((!oldStyle && newStyle) || (oldStyle && !newStyle))
return Reattach;
@@ -177,15 +180,12 @@ StyleRecalcChange RenderStyle::compare(const RenderStyle* oldStyle, const Render
if (oldStyle->display() != newStyle->display()
|| oldStyle->hasPseudoStyle(FIRST_LETTER) != newStyle->hasPseudoStyle(FIRST_LETTER)
|| oldStyle->columnSpan() != newStyle->columnSpan()
- || oldStyle->specifiesAutoColumns() != newStyle->specifiesAutoColumns()
|| !oldStyle->contentDataEquivalent(newStyle)
- || oldStyle->hasTextCombine() != newStyle->hasTextCombine()
- || oldStyle->flowThread() != newStyle->flowThread()
- || oldStyle->regionThread() != newStyle->regionThread())
+ || oldStyle->hasTextCombine() != newStyle->hasTextCombine())
return Reattach;
if (*oldStyle == *newStyle)
- return comparePseudoStyles(oldStyle, newStyle);
+ return diffPseudoStyles(oldStyle, newStyle);
if (oldStyle->inheritedNotEqual(newStyle)
|| oldStyle->hasExplicitlyInheritedProperties()
@@ -233,6 +233,7 @@ void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
noninherited_flags.currentColor = other->noninherited_flags.currentColor;
+ noninherited_flags.hasViewportUnits = other->noninherited_flags.hasViewportUnits;
if (m_svgStyle != other->m_svgStyle)
m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
ASSERT(zoom() == initialZoom());
@@ -336,7 +337,7 @@ bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
&& rareInheritedData.get() == other->rareInheritedData.get();
}
-static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b, const Length& width)
+static bool positionedObjectMovedOnly(const LengthBox& a, const LengthBox& b, const Length& width)
{
// If any unit types are different, then we can't guarantee
// that this was just a movement.
@@ -353,9 +354,11 @@ static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b, const
return false;
if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
return false;
- // If our width is auto and left or right is specified then this
+ // If our width is auto and left or right is specified and changed then this
// is not just a movement - we need to resize to our container.
- if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
+ if (width.isIntrinsicOrAuto()
+ && ((!a.left().isIntrinsicOrAuto() && a.left() != b.left())
+ || (!a.right().isIntrinsicOrAuto() && a.right() != b.right())))
return false;
// One of the units is fixed or percent in both directions and stayed
@@ -363,328 +366,364 @@ static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b, const
return true;
}
-StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
{
- changedContextSensitiveProperties = ContextSensitivePropertyNone;
+ // Note, we use .get() on each DataRef below because DataRef::operator== will do a deep
+ // compare, which is duplicate work when we're going to compare each property inside
+ // this function anyway.
- StyleDifference svgChange = StyleDifferenceEqual;
- if (m_svgStyle != other->m_svgStyle) {
- svgChange = m_svgStyle->diff(other->m_svgStyle.get());
- if (svgChange == StyleDifferenceLayout)
- return svgChange;
+ StyleDifference diff;
+ if (m_svgStyle.get() != other.m_svgStyle.get())
+ diff = m_svgStyle->diff(other.m_svgStyle.get());
+
+ if ((!diff.needsFullLayout() || !diff.needsRepaint()) && diffNeedsFullLayoutAndRepaint(other)) {
+ diff.setNeedsFullLayout();
+ diff.setNeedsRepaintObject();
+ }
+
+ if (!diff.needsFullLayout() && diffNeedsFullLayout(other))
+ diff.setNeedsFullLayout();
+
+ if (!diff.needsFullLayout() && position() != StaticPosition && surround->offset != other.surround->offset) {
+ // Optimize for the case where a positioned layer is moving but not changing size.
+ if ((position() == AbsolutePosition || position() == FixedPosition)
+ && positionedObjectMovedOnly(surround->offset, other.surround->offset, m_box->width())) {
+ diff.setNeedsPositionedMovementLayout();
+ } else {
+ // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
+ // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
+ // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
+ diff.setNeedsFullLayout();
+ }
+ }
+
+ if (diffNeedsRepaintLayer(other))
+ diff.setNeedsRepaintLayer();
+ else if (diffNeedsRepaintObject(other))
+ diff.setNeedsRepaintObject();
+
+ changedContextSensitiveProperties = computeChangedContextSensitiveProperties(other, diff);
+
+ if (diff.hasNoChange() && diffNeedsRecompositeLayer(other))
+ diff.setNeedsRecompositeLayer();
+
+ // Cursors are not checked, since they will be set appropriately in response to mouse events,
+ // so they don't need to cause any repaint or layout.
+
+ // Animations don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off
+ // the resulting transition properly.
+
+ return diff;
+}
+
+bool RenderStyle::diffNeedsFullLayoutAndRepaint(const RenderStyle& other) const
+{
+ // FIXME: Not all cases in this method need both full layout and repaint.
+ // Should move cases into diffNeedsFullLayout() if
+ // - don't need repaint at all;
+ // - or the renderer knows how to exactly repaint caused by the layout change
+ // instead of forced full repaint.
+
+ if (m_box.get() != other.m_box.get()) {
+ if (m_box->width() != other.m_box->width()
+ || m_box->minWidth() != other.m_box->minWidth()
+ || m_box->maxWidth() != other.m_box->maxWidth()
+ || m_box->height() != other.m_box->height()
+ || m_box->minHeight() != other.m_box->minHeight()
+ || m_box->maxHeight() != other.m_box->maxHeight())
+ return true;
+
+ if (m_box->verticalAlign() != other.m_box->verticalAlign())
+ return true;
+
+ if (m_box->boxSizing() != other.m_box->boxSizing())
+ return true;
+ }
+
+ if (surround.get() != other.surround.get()) {
+ if (surround->margin != other.surround->margin)
+ return true;
+
+ if (surround->padding != other.surround->padding)
+ return true;
+
+ // If our border widths change, then we need to layout. Other changes to borders only necessitate a repaint.
+ if (borderLeftWidth() != other.borderLeftWidth()
+ || borderTopWidth() != other.borderTopWidth()
+ || borderBottomWidth() != other.borderBottomWidth()
+ || borderRightWidth() != other.borderRightWidth())
+ return true;
}
- if (m_box->width() != other->m_box->width()
- || m_box->minWidth() != other->m_box->minWidth()
- || m_box->maxWidth() != other->m_box->maxWidth()
- || m_box->height() != other->m_box->height()
- || m_box->minHeight() != other->m_box->minHeight()
- || m_box->maxHeight() != other->m_box->maxHeight())
- return StyleDifferenceLayout;
-
- if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
- return StyleDifferenceLayout;
-
- if (m_box->boxSizing() != other->m_box->boxSizing())
- return StyleDifferenceLayout;
-
- if (surround->margin != other->surround->margin)
- return StyleDifferenceLayout;
-
- if (surround->padding != other->surround->padding)
- return StyleDifferenceLayout;
-
- if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
- if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance
- || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
- || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
- || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
- || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
- return StyleDifferenceLayout;
-
- if (rareNonInheritedData->m_regionFragment != other->rareNonInheritedData->m_regionFragment)
- return StyleDifferenceLayout;
-
- if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
- || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough
- || rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
- || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
- return StyleDifferenceLayout;
-
- if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
- && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
- return StyleDifferenceLayout;
-
- if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
- && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
- return StyleDifferenceLayout;
- if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
- || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
- || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
- || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
- || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
- return StyleDifferenceLayout;
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (rareNonInheritedData->m_appearance != other.rareNonInheritedData->m_appearance
+ || rareNonInheritedData->marginBeforeCollapse != other.rareNonInheritedData->marginBeforeCollapse
+ || rareNonInheritedData->marginAfterCollapse != other.rareNonInheritedData->marginAfterCollapse
+ || rareNonInheritedData->lineClamp != other.rareNonInheritedData->lineClamp
+ || rareNonInheritedData->textOverflow != other.rareNonInheritedData->textOverflow
+ || rareNonInheritedData->m_wrapFlow != other.rareNonInheritedData->m_wrapFlow
+ || rareNonInheritedData->m_wrapThrough != other.rareNonInheritedData->m_wrapThrough
+ || rareNonInheritedData->m_shapeMargin != other.rareNonInheritedData->m_shapeMargin
+ || rareNonInheritedData->m_order != other.rareNonInheritedData->m_order
+ || rareNonInheritedData->m_alignContent != other.rareNonInheritedData->m_alignContent
+ || rareNonInheritedData->m_alignItems != other.rareNonInheritedData->m_alignItems
+ || rareNonInheritedData->m_alignSelf != other.rareNonInheritedData->m_alignSelf
+ || rareNonInheritedData->m_justifyContent != other.rareNonInheritedData->m_justifyContent
+ || rareNonInheritedData->m_grid.get() != other.rareNonInheritedData->m_grid.get()
+ || rareNonInheritedData->m_gridItem.get() != other.rareNonInheritedData->m_gridItem.get()
+ || rareNonInheritedData->m_textCombine != other.rareNonInheritedData->m_textCombine
+ || rareNonInheritedData->hasFilters() != other.rareNonInheritedData->hasFilters())
+ return true;
+
+ if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other.rareNonInheritedData->m_deprecatedFlexibleBox.get()
+ && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other.rareNonInheritedData->m_deprecatedFlexibleBox.get())
+ return true;
+
+ if (rareNonInheritedData->m_flexibleBox.get() != other.rareNonInheritedData->m_flexibleBox.get()
+ && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get())
+ return true;
// FIXME: We should add an optimized form of layout that just recomputes visual overflow.
- if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
- return StyleDifferenceLayout;
+ if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
+ return true;
+
+ if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheritedData.get()))
+ return true;
- if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
- return StyleDifferenceLayout;
+ if (rareNonInheritedData->m_multiCol.get() != other.rareNonInheritedData->m_multiCol.get()
+ && *rareNonInheritedData->m_multiCol.get() != *other.rareNonInheritedData->m_multiCol.get())
+ return true;
- if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
- && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
- return StyleDifferenceLayout;
+ // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
+ const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
+ const CounterDirectiveMap* mapB = other.rareNonInheritedData->m_counterDirectives.get();
+ if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
+ return true;
- if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
- && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
- // Don't return early here; instead take note of the type of
- // change, and deal with it when looking at compositing.
- changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
+ // We only need do layout for opacity changes if adding or losing opacity could trigger a change
+ // in us being a stacking context.
+ if (hasAutoZIndex() != other.hasAutoZIndex() && rareNonInheritedData->hasOpacity() != other.rareNonInheritedData->hasOpacity()) {
+ // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
+ // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
+ // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
+ // In addition we need to solve the floating object issue when layers come and go. Right now
+ // a full layout is necessary to keep floating object lists sane.
+ return true;
}
+ }
- if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
- || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
- return StyleDifferenceLayout;
+ if (rareInheritedData.get() != other.rareInheritedData.get()) {
+ if (rareInheritedData->highlight != other.rareInheritedData->highlight
+ || rareInheritedData->indent != other.rareInheritedData->indent
+ || rareInheritedData->m_textAlignLast != other.rareInheritedData->m_textAlignLast
+ || rareInheritedData->m_textIndentLine != other.rareInheritedData->m_textIndentLine
+ || rareInheritedData->m_effectiveZoom != other.rareInheritedData->m_effectiveZoom
+ || rareInheritedData->wordBreak != other.rareInheritedData->wordBreak
+ || rareInheritedData->overflowWrap != other.rareInheritedData->overflowWrap
+ || rareInheritedData->lineBreak != other.rareInheritedData->lineBreak
+ || rareInheritedData->textSecurity != other.rareInheritedData->textSecurity
+ || rareInheritedData->hyphens != other.rareInheritedData->hyphens
+ || rareInheritedData->hyphenationLimitBefore != other.rareInheritedData->hyphenationLimitBefore
+ || rareInheritedData->hyphenationLimitAfter != other.rareInheritedData->hyphenationLimitAfter
+ || rareInheritedData->hyphenationString != other.rareInheritedData->hyphenationString
+ || rareInheritedData->locale != other.rareInheritedData->locale
+ || rareInheritedData->m_rubyPosition != other.rareInheritedData->m_rubyPosition
+ || rareInheritedData->textEmphasisMark != other.rareInheritedData->textEmphasisMark
+ || rareInheritedData->textEmphasisPosition != other.rareInheritedData->textEmphasisPosition
+ || rareInheritedData->textEmphasisCustomMark != other.rareInheritedData->textEmphasisCustomMark
+ || rareInheritedData->m_textJustify != other.rareInheritedData->m_textJustify
+ || rareInheritedData->m_textOrientation != other.rareInheritedData->m_textOrientation
+ || rareInheritedData->m_tabSize != other.rareInheritedData->m_tabSize
+ || rareInheritedData->m_lineBoxContain != other.rareInheritedData->m_lineBoxContain
+ || rareInheritedData->listStyleImage != other.rareInheritedData->listStyleImage
+ || rareInheritedData->textStrokeWidth != other.rareInheritedData->textStrokeWidth)
+ return true;
- if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
- return StyleDifferenceLayout;
- }
+ if (!rareInheritedData->shadowDataEquivalent(*other.rareInheritedData.get()))
+ return true;
- if (rareInheritedData.get() != other->rareInheritedData.get()) {
- if (rareInheritedData->highlight != other->rareInheritedData->highlight
- || rareInheritedData->indent != other->rareInheritedData->indent
- || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
- || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
- || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
- || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
- || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
- || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
- || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
- || rareInheritedData->hyphens != other->rareInheritedData->hyphens
- || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
- || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
- || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
- || rareInheritedData->locale != other->rareInheritedData->locale
- || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
- || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
- || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
- || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
- || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
- || rareInheritedData->m_textJustify != other->rareInheritedData->m_textJustify
- || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
- || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
- || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
- || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
- || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
- || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
- || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
- return StyleDifferenceLayout;
-
- if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
- return StyleDifferenceLayout;
-
- if (textStrokeWidth() != other->textStrokeWidth())
- return StyleDifferenceLayout;
+ if (!rareInheritedData->quotesDataEquivalent(*other.rareInheritedData.get()))
+ return true;
}
- if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
- return StyleDifferenceLayout;
+ if (inherited->textAutosizingMultiplier != other.inherited->textAutosizingMultiplier)
+ return true;
- if (inherited->line_height != other->inherited->line_height
- || inherited->font != other->inherited->font
- || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
- || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
- || inherited_flags._box_direction != other->inherited_flags._box_direction
- || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
- || noninherited_flags._position != other->noninherited_flags._position
- || noninherited_flags._floating != other->noninherited_flags._floating
- || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
- return StyleDifferenceLayout;
+ if (inherited.get() != other.inherited.get()) {
+ if (inherited->line_height != other.inherited->line_height
+ || inherited->font != other.inherited->font
+ || inherited->horizontal_border_spacing != other.inherited->horizontal_border_spacing
+ || inherited->vertical_border_spacing != other.inherited->vertical_border_spacing)
+ return true;
+ }
+ if (inherited_flags._box_direction != other.inherited_flags._box_direction
+ || inherited_flags.m_rtlOrdering != other.inherited_flags.m_rtlOrdering
+ || inherited_flags._text_align != other.inherited_flags._text_align
+ || inherited_flags._text_transform != other.inherited_flags._text_transform
+ || inherited_flags._direction != other.inherited_flags._direction
+ || inherited_flags._white_space != other.inherited_flags._white_space
+ || inherited_flags.m_writingMode != other.inherited_flags.m_writingMode)
+ return true;
- if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
- if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
- || inherited_flags._empty_cells != other->inherited_flags._empty_cells
- || inherited_flags._caption_side != other->inherited_flags._caption_side
- || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
- return StyleDifferenceLayout;
+ if (noninherited_flags._overflowX != other.noninherited_flags._overflowX
+ || noninherited_flags._overflowY != other.noninherited_flags._overflowY
+ || noninherited_flags._clear != other.noninherited_flags._clear
+ || noninherited_flags._unicodeBidi != other.noninherited_flags._unicodeBidi
+ || noninherited_flags._position != other.noninherited_flags._position
+ || noninherited_flags._floating != other.noninherited_flags._floating
+ || noninherited_flags._originalDisplay != other.noninherited_flags._originalDisplay
+ || noninherited_flags._vertical_align != other.noninherited_flags._vertical_align)
+ return true;
+
+ if (noninherited_flags._effectiveDisplay >= FIRST_TABLE_DISPLAY && noninherited_flags._effectiveDisplay <= LAST_TABLE_DISPLAY) {
+ if (inherited_flags._border_collapse != other.inherited_flags._border_collapse
+ || inherited_flags._empty_cells != other.inherited_flags._empty_cells
+ || inherited_flags._caption_side != other.inherited_flags._caption_side
+ || noninherited_flags._table_layout != other.noninherited_flags._table_layout)
+ return true;
// In the collapsing border model, 'hidden' suppresses other borders, while 'none'
// does not, so these style differences can be width differences.
if (inherited_flags._border_collapse
- && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
- || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
- || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
- || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
- || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
- || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
- || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
- || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
- return StyleDifferenceLayout;
+ && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE)
+ || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDDEN)
+ || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle() == BNONE)
+ || (borderBottomStyle() == BNONE && other.borderBottomStyle() == BHIDDEN)
+ || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == BNONE)
+ || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHIDDEN)
+ || (borderRightStyle() == BHIDDEN && other.borderRightStyle() == BNONE)
+ || (borderRightStyle() == BNONE && other.borderRightStyle() == BHIDDEN)))
+ return true;
+ } else if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
+ if (inherited_flags._list_style_type != other.inherited_flags._list_style_type
+ || inherited_flags._list_style_position != other.inherited_flags._list_style_position)
+ return true;
}
- if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
- if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
- || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
- return StyleDifferenceLayout;
- }
+ if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
+ return true;
- if (inherited_flags._text_align != other->inherited_flags._text_align
- || inherited_flags._text_transform != other->inherited_flags._text_transform
- || inherited_flags._direction != other->inherited_flags._direction
- || inherited_flags._white_space != other->inherited_flags._white_space
- || noninherited_flags._clear != other->noninherited_flags._clear
- || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
- return StyleDifferenceLayout;
-
- // Check block flow direction.
- if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
- return StyleDifferenceLayout;
-
- // Check text combine mode.
- if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
- return StyleDifferenceLayout;
-
- // Overflow returns a layout hint.
- if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
- || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
- return StyleDifferenceLayout;
-
- // If our border widths change, then we need to layout. Other changes to borders
- // only necessitate a repaint.
- if (borderLeftWidth() != other->borderLeftWidth()
- || borderTopWidth() != other->borderTopWidth()
- || borderBottomWidth() != other->borderBottomWidth()
- || borderRightWidth() != other->borderRightWidth())
- return StyleDifferenceLayout;
-
- // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
- const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
- const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
- if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
- return StyleDifferenceLayout;
-
- if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
- return StyleDifferenceLayout;
-
- if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
- // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
- // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
- // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
- // In addition we need to solve the floating object issue when layers come and go. Right now
- // a full layout is necessary to keep floating object lists sane.
- return StyleDifferenceLayout;
+ if (!m_background->outline().visuallyEqual(other.m_background->outline())) {
+ // FIXME: We only really need to recompute the overflow but we don't have an optimized layout for it.
+ return true;
}
- if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
- return StyleDifferenceLayout;
+ // Movement of non-static-positioned object is special cased in RenderStyle::visualInvalidationDiff().
- if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get()))
- return StyleDifferenceLayout;
+ return false;
+}
+
+bool RenderStyle::diffNeedsFullLayout(const RenderStyle& other) const
+{
+ return false;
+}
- // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
- // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
- // but have to return StyleDifferenceLayout, that's why this if branch comes after all branches
- // that are relevant for SVG and might return StyleDifferenceLayout.
- if (svgChange != StyleDifferenceEqual)
- return svgChange;
+bool RenderStyle::diffNeedsRepaintLayer(const RenderStyle& other) const
+{
+ if (position() != StaticPosition && (visual->clip != other.visual->clip || visual->hasClip != other.visual->hasClip))
+ return true;
- // Make sure these left/top/right/bottom checks stay below all layout checks and above
- // all visible checks.
- if (position() != StaticPosition && surround->offset != other->surround->offset) {
- // Optimize for the case where a positioned layer is moving but not changing size.
- if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset, m_box->width()) && repaintOnlyDiff(other, changedContextSensitiveProperties) == StyleDifferenceEqual)
- return StyleDifferenceLayoutPositionedMovementOnly;
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (RuntimeEnabledFeatures::cssCompositingEnabled()
+ && (rareNonInheritedData->m_effectiveBlendMode != other.rareNonInheritedData->m_effectiveBlendMode
+ || rareNonInheritedData->m_isolation != other.rareNonInheritedData->m_isolation))
+ return true;
- // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
- // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
- // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
- return StyleDifferenceLayout;
+ if (rareNonInheritedData->m_mask != other.rareNonInheritedData->m_mask
+ || rareNonInheritedData->m_maskBoxImage != other.rareNonInheritedData->m_maskBoxImage)
+ return true;
}
- return repaintOnlyDiff(other, changedContextSensitiveProperties);
+
+ return false;
}
-StyleDifference RenderStyle::repaintOnlyDiff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+bool RenderStyle::diffNeedsRepaintObject(const RenderStyle& other) const
{
- if (position() != StaticPosition && (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
- || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip))
- return StyleDifferenceRepaintLayer;
-
- if (RuntimeEnabledFeatures::cssCompositingEnabled() && rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
- return StyleDifferenceRepaintLayer;
+ if (inherited_flags._visibility != other.inherited_flags._visibility
+ || inherited_flags.m_printColorAdjust != other.inherited_flags.m_printColorAdjust
+ || inherited_flags._insideLink != other.inherited_flags._insideLink
+ || !surround->border.visuallyEqual(other.surround->border)
+ || !m_background->visuallyEqual(*other.m_background))
+ return true;
- if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
- // Don't return early here; instead take note of the type of change,
- // and deal with it when looking at compositing.
- changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
+ if (rareInheritedData.get() != other.rareInheritedData.get()) {
+ if (rareInheritedData->userModify != other.rareInheritedData->userModify
+ || rareInheritedData->userSelect != other.rareInheritedData->userSelect
+ || rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering)
+ return true;
}
- if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
- && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
- // Don't return early here; instead take note of the type of change,
- // and deal with it when looking at compositing.
- changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (rareNonInheritedData->userDrag != other.rareNonInheritedData->userDrag
+ || rareNonInheritedData->m_borderFit != other.rareNonInheritedData->m_borderFit
+ || rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit
+ || rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition
+ || rareNonInheritedData->m_shapeOutside != other.rareNonInheritedData->m_shapeOutside
+ || rareNonInheritedData->m_clipPath != other.rareNonInheritedData->m_clipPath)
+ return true;
}
- if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
- || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
- return StyleDifferenceRepaintLayer;
-
- if (inherited_flags._visibility != other->inherited_flags._visibility
- || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
- || inherited_flags._insideLink != other->inherited_flags._insideLink
- || surround->border != other->surround->border
- || *m_background.get() != *other->m_background.get()
- || rareInheritedData->userModify != other->rareInheritedData->userModify
- || rareInheritedData->userSelect != other->rareInheritedData->userSelect
- || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
- || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
- || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
- || rareNonInheritedData->m_objectPosition != other->rareNonInheritedData->m_objectPosition
- || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
- return StyleDifferenceRepaint;
-
- // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected
- // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout
- // the parent container. For sure, I will have to revisit this code, but for now I've added this in order
- // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
- // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
- if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
- return StyleDifferenceRepaint;
-
- if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
- return StyleDifferenceRepaint;
-
- if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
- if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
- || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
- || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
- || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
- || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
- return StyleDifferenceRecompositeLayer;
+ return false;
+}
+
+bool RenderStyle::diffNeedsRecompositeLayer(const RenderStyle& other) const
+{
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (rareNonInheritedData->m_transformStyle3D != other.rareNonInheritedData->m_transformStyle3D
+ || rareNonInheritedData->m_backfaceVisibility != other.rareNonInheritedData->m_backfaceVisibility
+ || rareNonInheritedData->m_perspective != other.rareNonInheritedData->m_perspective
+ || rareNonInheritedData->m_perspectiveOriginX != other.rareNonInheritedData->m_perspectiveOriginX
+ || rareNonInheritedData->m_perspectiveOriginY != other.rareNonInheritedData->m_perspectiveOriginY
+ || hasWillChangeCompositingHint() != other.hasWillChangeCompositingHint())
+ return true;
}
- if (inherited->color != other->inherited->color
- || inherited_flags._text_decorations != other->inherited_flags._text_decorations
- || visual->textDecoration != other->visual->textDecoration
- || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
- || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
- || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
- || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
- || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
- || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
- return StyleDifferenceRepaintIfTextOrColorChange;
+ return false;
+}
- // Cursors are not checked, since they will be set appropriately in response to mouse events,
- // so they don't need to cause any repaint or layout.
+unsigned RenderStyle::computeChangedContextSensitiveProperties(const RenderStyle& other, StyleDifference diff) const
+{
+ unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
- // Animations don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off
- // the resulting transition properly.
- return StyleDifferenceEqual;
+ // StyleAdjuster has ensured that zIndex is non-auto only if it's applicable.
+ if (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != other.m_box->hasAutoZIndex())
+ changedContextSensitiveProperties |= ContextSensitivePropertyZIndex;
+
+ if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (!transformDataEquivalent(other))
+ changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
+
+ if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity)
+ changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
+
+ if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filter)
+ changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
+ }
+
+ if (!diff.needsRepaint()) {
+ if (inherited->color != other.inherited->color
+ || inherited_flags.m_textUnderline != other.inherited_flags.m_textUnderline
+ || visual->textDecoration != other.visual->textDecoration) {
+ changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
+ } else if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
+ if (rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle
+ || rareNonInheritedData->m_textDecorationColor != other.rareNonInheritedData->m_textDecorationColor)
+ changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
+ } else if (rareInheritedData.get() != other.rareInheritedData.get()) {
+ if (rareInheritedData->textFillColor() != other.rareInheritedData->textFillColor()
+ || rareInheritedData->textStrokeColor() != other.rareInheritedData->textStrokeColor()
+ || rareInheritedData->textEmphasisColor() != other.rareInheritedData->textEmphasisColor()
+ || rareInheritedData->textEmphasisFill != other.rareInheritedData->textEmphasisFill
+ || rareInheritedData->appliedTextDecorations != other.rareInheritedData->appliedTextDecorations)
+ changedContextSensitiveProperties |= ContextSensitivePropertyTextOrColor;
+ }
+ }
+
+ return changedContextSensitiveProperties;
}
-void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
+void RenderStyle::setClip(const Length& top, const Length& right, const Length& bottom, const Length& left)
{
StyleVisualData* data = visual.access();
data->clip.m_top = top;
@@ -707,15 +746,13 @@ void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
{
- if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
- return;
rareInheritedData.access()->quotes = q;
}
void RenderStyle::clearCursorList()
{
if (rareInheritedData->cursorData)
- rareInheritedData.access()->cursorData = 0;
+ rareInheritedData.access()->cursorData = nullptr;
}
void RenderStyle::addCallbackSelector(const String& selector)
@@ -842,6 +879,25 @@ bool RenderStyle::hasIsolation() const
return false;
}
+bool RenderStyle::hasWillChangeCompositingHint() const
+{
+ for (size_t i = 0; i < rareNonInheritedData->m_willChange->m_properties.size(); ++i) {
+ switch (rareNonInheritedData->m_willChange->m_properties[i]) {
+ case CSSPropertyOpacity:
+ case CSSPropertyTransform:
+ case CSSPropertyWebkitTransform:
+ case CSSPropertyTop:
+ case CSSPropertyLeft:
+ case CSSPropertyBottom:
+ case CSSPropertyRight:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
{
// transform-origin brackets the transform with translate operations.
@@ -878,8 +934,8 @@ void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRec
float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
if (applyTransformOrigin) {
- transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width(), 0) + offsetX,
- floatValueForLength(transformOriginY(), boundingBox.height(), 0) + offsetY,
+ transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
+ floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
transformOriginZ());
}
@@ -888,8 +944,8 @@ void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRec
transformOperations[i]->apply(transform, boundingBox.size());
if (applyTransformOrigin) {
- transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width(), 0) - offsetX,
- -floatValueForLength(transformOriginY(), boundingBox.height(), 0) - offsetY,
+ transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
+ -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
-transformOriginZ());
}
}
@@ -904,49 +960,17 @@ void RenderStyle::setBoxShadow(PassRefPtr<ShadowList> s)
rareNonInheritedData.access()->m_boxShadow = s;
}
-static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
+static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size)
{
return RoundedRect::Radii(
- 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)
-{
- // Constrain corner radii using CSS3 rules:
- // http://www.w3.org/TR/css3-background/#the-border-radius
-
- float factor = 1;
- unsigned radiiSum;
-
- // top
- radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
- if (radiiSum > static_cast<unsigned>(rect.width()))
- factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
-
- // bottom
- radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
- if (radiiSum > static_cast<unsigned>(rect.width()))
- factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
-
- // left
- radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
- if (radiiSum > static_cast<unsigned>(rect.height()))
- factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
-
- // right
- radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
- if (radiiSum > static_cast<unsigned>(rect.height()))
- factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
-
- ASSERT(factor <= 1);
- return factor;
+ IntSize(valueForLength(border.topLeft().width(), size.width()),
+ valueForLength(border.topLeft().height(), size.height())),
+ IntSize(valueForLength(border.topRight().width(), size.width()),
+ valueForLength(border.topRight().height(), size.height())),
+ IntSize(valueForLength(border.bottomLeft().width(), size.width()),
+ valueForLength(border.bottomLeft().height(), size.height())),
+ IntSize(valueForLength(border.bottomRight().width(), size.width()),
+ valueForLength(border.bottomRight().height(), size.height())));
}
StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
@@ -966,13 +990,13 @@ short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_bo
void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
-RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
RoundedRect roundedRect(snappedBorderRect);
if (hasBorderRadius()) {
- RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size(), renderView);
- radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
+ RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size());
+ radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
}
return roundedRect;
@@ -1096,111 +1120,67 @@ const AtomicString& RenderStyle::textEmphasisMarkString() const
return nullAtom;
}
-void RenderStyle::adjustAnimations()
+CSSAnimationData& RenderStyle::accessAnimations()
{
- CSSAnimationDataList* animationList = rareNonInheritedData->m_animations.get();
- if (!animationList)
- return;
-
- // Get rid of empty animations and anything beyond them
- for (size_t i = 0; i < animationList->size(); ++i) {
- if (animationList->animation(i)->isEmpty()) {
- animationList->resize(i);
- break;
- }
- }
-
- if (animationList->isEmpty()) {
- clearAnimations();
- return;
- }
-
- // Repeat patterns into layers that don't have some properties set.
- animationList->fillUnsetProperties();
+ if (!rareNonInheritedData.access()->m_animations)
+ rareNonInheritedData.access()->m_animations = CSSAnimationData::create();
+ return *rareNonInheritedData->m_animations;
}
-void RenderStyle::adjustTransitions()
+CSSTransitionData& RenderStyle::accessTransitions()
{
- CSSAnimationDataList* transitionList = rareNonInheritedData->m_transitions.get();
- if (!transitionList)
- return;
+ if (!rareNonInheritedData.access()->m_transitions)
+ rareNonInheritedData.access()->m_transitions = CSSTransitionData::create();
+ return *rareNonInheritedData->m_transitions;
+}
- // Get rid of empty transitions and anything beyond them
- for (size_t i = 0; i < transitionList->size(); ++i) {
- if (transitionList->animation(i)->isEmpty()) {
- transitionList->resize(i);
- break;
- }
- }
+const Font& RenderStyle::font() const { return inherited->font; }
+const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
+const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
+float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
+float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
+int RenderStyle::fontSize() const { return fontDescription().computedPixelSize(); }
+FontWeight RenderStyle::fontWeight() const { return fontDescription().weight(); }
- if (transitionList->isEmpty()) {
- clearTransitions();
- return;
- }
+TextDecoration RenderStyle::textDecorationsInEffect() const
+{
+ int decorations = 0;
- // Repeat patterns into layers that don't have some properties set.
- transitionList->fillUnsetProperties();
-
- // Make sure there are no duplicate properties. This is an O(n^2) algorithm
- // but the lists tend to be very short, so it is probably ok
- for (size_t i = 0; i < transitionList->size(); ++i) {
- for (size_t j = i+1; j < transitionList->size(); ++j) {
- if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
- // toss i
- transitionList->remove(i);
- j = i;
- }
- }
- }
-}
+ const Vector<AppliedTextDecoration>& applied = appliedTextDecorations();
-CSSAnimationDataList* RenderStyle::accessAnimations()
-{
- if (!rareNonInheritedData.access()->m_animations)
- rareNonInheritedData.access()->m_animations = adoptPtr(new CSSAnimationDataList());
- return rareNonInheritedData->m_animations.get();
-}
+ for (size_t i = 0; i < applied.size(); ++i)
+ decorations |= applied[i].line();
-CSSAnimationDataList* RenderStyle::accessTransitions()
-{
- if (!rareNonInheritedData.access()->m_transitions)
- rareNonInheritedData.access()->m_transitions = adoptPtr(new CSSAnimationDataList());
- return rareNonInheritedData->m_transitions.get();
+ return static_cast<TextDecoration>(decorations);
}
-const CSSAnimationData* RenderStyle::transitionForProperty(CSSPropertyID property) const
+const Vector<AppliedTextDecoration>& RenderStyle::appliedTextDecorations() const
{
- if (transitions()) {
- for (size_t i = 0; i < transitions()->size(); ++i) {
- const CSSAnimationData* p = transitions()->animation(i);
- if (p->animationMode() == CSSAnimationData::AnimateAll || p->property() == property) {
- return p;
- }
- }
+ if (!inherited_flags.m_textUnderline && !rareInheritedData->appliedTextDecorations) {
+ DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ());
+ return empty;
+ }
+ if (inherited_flags.m_textUnderline) {
+ DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, underline, (1, AppliedTextDecoration(TextDecorationUnderline)));
+ return underline;
}
- return 0;
-}
-const Font& RenderStyle::font() const { return inherited->font; }
-const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
-const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
-float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
-float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
-int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
+ return rareInheritedData->appliedTextDecorations->vector();
+}
-float RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
-float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
+float RenderStyle::wordSpacing() const { return fontDescription().wordSpacing(); }
+float RenderStyle::letterSpacing() const { return fontDescription().letterSpacing(); }
bool RenderStyle::setFontDescription(const FontDescription& v)
{
if (inherited->font.fontDescription() != v) {
- inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
+ inherited.access()->font = Font(v);
return true;
}
return false;
}
-Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
+const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
Length RenderStyle::lineHeight() const
{
const Length& lh = inherited->line_height;
@@ -1214,9 +1194,10 @@ Length RenderStyle::lineHeight() const
return lh;
}
-void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
-int RenderStyle::computedLineHeight(RenderView* renderView) const
+void RenderStyle::setLineHeight(const Length& specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
+
+int RenderStyle::computedLineHeight() const
{
const Length& lh = lineHeight();
@@ -1227,14 +1208,26 @@ int RenderStyle::computedLineHeight(RenderView* renderView) const
if (lh.isPercent())
return minimumValueForLength(lh, fontSize());
- if (lh.isViewportPercentage())
- return valueForLength(lh, 0, renderView);
-
return lh.value();
}
-void RenderStyle::setWordSpacing(float v) { inherited.access()->font.setWordSpacing(v); }
-void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
+void RenderStyle::setWordSpacing(float wordSpacing)
+{
+ FontSelector* currentFontSelector = font().fontSelector();
+ FontDescription desc(fontDescription());
+ desc.setWordSpacing(wordSpacing);
+ setFontDescription(desc);
+ font().update(currentFontSelector);
+}
+
+void RenderStyle::setLetterSpacing(float letterSpacing)
+{
+ FontSelector* currentFontSelector = font().fontSelector();
+ FontDescription desc(fontDescription());
+ desc.setLetterSpacing(letterSpacing);
+ setFontDescription(desc);
+ font().update(currentFontSelector);
+}
void RenderStyle::setFontSize(float size)
{
@@ -1262,6 +1255,66 @@ void RenderStyle::setFontSize(float size)
font().update(currentFontSelector);
}
+void RenderStyle::setFontWeight(FontWeight weight)
+{
+ FontSelector* currentFontSelector = font().fontSelector();
+ FontDescription desc(fontDescription());
+ desc.setWeight(weight);
+ setFontDescription(desc);
+ font().update(currentFontSelector);
+}
+
+void RenderStyle::addAppliedTextDecoration(const AppliedTextDecoration& decoration)
+{
+ RefPtr<AppliedTextDecorationList>& list = rareInheritedData.access()->appliedTextDecorations;
+
+ if (!list)
+ list = AppliedTextDecorationList::create();
+ else if (!list->hasOneRef())
+ list = list->copy();
+
+ if (inherited_flags.m_textUnderline) {
+ inherited_flags.m_textUnderline = false;
+ list->append(AppliedTextDecoration(TextDecorationUnderline));
+ }
+
+ list->append(decoration);
+}
+
+void RenderStyle::applyTextDecorations()
+{
+ if (textDecoration() == TextDecorationNone)
+ return;
+
+ TextDecorationStyle style = textDecorationStyle();
+ StyleColor styleColor = visitedDependentDecorationStyleColor();
+
+ int decorations = textDecoration();
+
+ if (decorations & TextDecorationUnderline) {
+ // To save memory, we don't use AppliedTextDecoration objects in the
+ // common case of a single simple underline.
+ AppliedTextDecoration underline(TextDecorationUnderline, style, styleColor);
+
+ if (!rareInheritedData->appliedTextDecorations && underline.isSimpleUnderline())
+ inherited_flags.m_textUnderline = true;
+ else
+ addAppliedTextDecoration(underline);
+ }
+ if (decorations & TextDecorationOverline)
+ addAppliedTextDecoration(AppliedTextDecoration(TextDecorationOverline, style, styleColor));
+ if (decorations & TextDecorationLineThrough)
+ addAppliedTextDecoration(AppliedTextDecoration(TextDecorationLineThrough, style, styleColor));
+}
+
+void RenderStyle::clearAppliedTextDecorations()
+{
+ inherited_flags.m_textUnderline = false;
+
+ if (rareInheritedData->appliedTextDecorations)
+ rareInheritedData.access()->appliedTextDecorations = nullptr;
+}
+
void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
{
top = 0;
@@ -1274,7 +1327,7 @@ void RenderStyle::getShadowExtent(const ShadowList* shadowList, LayoutUnit &top,
const ShadowData& shadow = shadowList->shadows()[i];
if (shadow.style() == Inset)
continue;
- int blurAndSpread = shadow.blur() + shadow.spread();
+ float blurAndSpread = shadow.blur() + shadow.spread();
top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
@@ -1295,7 +1348,7 @@ LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowList* shadowList)
const ShadowData& shadow = shadowList->shadows()[i];
if (shadow.style() == Normal)
continue;
- int blurAndSpread = shadow.blur() + shadow.spread();
+ float blurAndSpread = shadow.blur() + shadow.spread();
top = max<LayoutUnit>(top, shadow.y() + blurAndSpread);
right = min<LayoutUnit>(right, shadow.x() - blurAndSpread);
bottom = min<LayoutUnit>(bottom, shadow.y() - blurAndSpread);
@@ -1315,7 +1368,7 @@ void RenderStyle::getShadowHorizontalExtent(const ShadowList* shadowList, Layout
const ShadowData& shadow = shadowList->shadows()[i];
if (shadow.style() == Inset)
continue;
- int blurAndSpread = shadow.blur() + shadow.spread();
+ float blurAndSpread = shadow.blur() + shadow.spread();
left = min<LayoutUnit>(left, shadow.x() - blurAndSpread);
right = max<LayoutUnit>(right, shadow.x() + blurAndSpread);
@@ -1332,20 +1385,46 @@ void RenderStyle::getShadowVerticalExtent(const ShadowList* shadowList, LayoutUn
const ShadowData& shadow = shadowList->shadows()[i];
if (shadow.style() == Inset)
continue;
- int blurAndSpread = shadow.blur() + shadow.spread();
+ float blurAndSpread = shadow.blur() + shadow.spread();
top = min<LayoutUnit>(top, shadow.y() - blurAndSpread);
bottom = max<LayoutUnit>(bottom, shadow.y() + blurAndSpread);
}
}
+StyleColor RenderStyle::visitedDependentDecorationStyleColor() const
+{
+ bool isVisited = insideLink() == InsideVisitedLink;
+
+ StyleColor styleColor = isVisited ? visitedLinkTextDecorationColor() : textDecorationColor();
+
+ if (!styleColor.isCurrentColor())
+ return styleColor;
+
+ if (textStrokeWidth()) {
+ // Prefer stroke color if possible, but not if it's fully transparent.
+ StyleColor textStrokeStyleColor = isVisited ? visitedLinkTextStrokeColor() : textStrokeColor();
+ if (!textStrokeStyleColor.isCurrentColor() && textStrokeStyleColor.color().alpha())
+ return textStrokeStyleColor;
+ }
+
+ return isVisited ? visitedLinkTextFillColor() : textFillColor();
+}
+
+Color RenderStyle::visitedDependentDecorationColor() const
+{
+ bool isVisited = insideLink() == InsideVisitedLink;
+ return visitedDependentDecorationStyleColor().resolve(isVisited ? visitedLinkColor() : color());
+}
+
Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
{
- Color result;
+ StyleColor result(StyleColor::currentColor());
EBorderStyle borderStyle = BNONE;
switch (colorProperty) {
case CSSPropertyBackgroundColor:
- return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
+ result = visitedLink ? visitedLinkBackgroundColor() : backgroundColor();
+ break;
case CSSPropertyBorderLeftColor:
result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
borderStyle = borderLeftStyle();
@@ -1371,9 +1450,6 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
case CSSPropertyWebkitColumnRuleColor:
result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
break;
- case CSSPropertyTextDecorationColor:
- // Text decoration color fallback is handled in RenderObject::decorationColor.
- return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
case CSSPropertyWebkitTextEmphasisColor:
result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
break;
@@ -1400,13 +1476,14 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
break;
}
- if (!result.isValid()) {
- if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
- result.setRGB(238, 238, 238);
- else
- result = visitedLink ? visitedLinkColor() : color();
- }
- return result;
+ if (!result.isCurrentColor())
+ return result.color();
+
+ // FIXME: Treating styled borders with initial color differently causes problems
+ // See crbug.com/316559, crbug.com/276231
+ if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
+ return Color(238, 238, 238);
+ return visitedLink ? visitedLinkColor() : color();
}
Color RenderStyle::visitedDependentColor(int colorProperty) const
@@ -1417,10 +1494,6 @@ Color RenderStyle::visitedDependentColor(int colorProperty) const
Color visitedColor = colorIncludingFallback(colorProperty, true);
- // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
- if (colorProperty == CSSPropertyTextDecorationColor)
- return visitedColor;
-
// FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
// assume that if the background color is transparent that it wasn't set. Note that it's weird that
// we're returning unvisited info for a visited link, but given our restriction that the alpha values
@@ -1525,7 +1598,7 @@ unsigned short RenderStyle::borderEndWidth() const
return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
}
-void RenderStyle::setMarginStart(Length margin)
+void RenderStyle::setMarginStart(const Length& margin)
{
if (isHorizontalWritingMode()) {
if (isLeftToRightDirection())
@@ -1540,7 +1613,7 @@ void RenderStyle::setMarginStart(Length margin)
}
}
-void RenderStyle::setMarginEnd(Length margin)
+void RenderStyle::setMarginEnd(const Length& margin)
{
if (isHorizontalWritingMode()) {
if (isLeftToRightDirection())
@@ -1587,7 +1660,7 @@ void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
surround.access()->border.m_image.setImage(image);
}
-void RenderStyle::setBorderImageSlices(LengthBox slices)
+void RenderStyle::setBorderImageSlices(const LengthBox& slices)
{
if (surround->border.m_image.imageSlices() == slices)
return;
@@ -1608,4 +1681,36 @@ void RenderStyle::setBorderImageOutset(const BorderImageLengthBox& outset)
surround.access()->border.m_image.setOutset(outset);
}
+float calcBorderRadiiConstraintScaleFor(const FloatRect& rect, const FloatRoundedRect::Radii& radii)
+{
+ // Constrain corner radii using CSS3 rules:
+ // http://www.w3.org/TR/css3-background/#the-border-radius
+
+ float factor = 1;
+ float radiiSum;
+
+ // top
+ radiiSum = radii.topLeft().width() + radii.topRight().width(); // Casts to avoid integer overflow.
+ if (radiiSum > rect.width())
+ factor = std::min(rect.width() / radiiSum, factor);
+
+ // bottom
+ radiiSum = radii.bottomLeft().width() + radii.bottomRight().width();
+ if (radiiSum > rect.width())
+ factor = std::min(rect.width() / radiiSum, factor);
+
+ // left
+ radiiSum = radii.topLeft().height() + radii.bottomLeft().height();
+ if (radiiSum > rect.height())
+ factor = std::min(rect.height() / radiiSum, factor);
+
+ // right
+ radiiSum = radii.topRight().height() + radii.bottomRight().height();
+ if (radiiSum > rect.height())
+ factor = std::min(rect.height() / radiiSum, factor);
+
+ ASSERT(factor <= 1);
+ return factor;
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.h b/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.h
index f405b951fbe..543c815d06d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyle.h
@@ -25,11 +25,11 @@
#ifndef RenderStyle_h
#define RenderStyle_h
-#include "CSSPropertyNames.h"
-#include "core/css/CSSLengthFunctions.h"
+#include "core/CSSPropertyNames.h"
+#include "core/animation/css/CSSAnimationData.h"
+#include "core/animation/css/CSSTransitionData.h"
#include "core/css/CSSLineBoxContainValue.h"
#include "core/css/CSSPrimitiveValue.h"
-#include "core/platform/animation/CSSAnimationDataList.h"
#include "core/rendering/style/BorderValue.h"
#include "core/rendering/style/CounterDirectives.h"
#include "core/rendering/style/DataRef.h"
@@ -42,10 +42,12 @@
#include "core/rendering/style/StyleBackgroundData.h"
#include "core/rendering/style/StyleBoxData.h"
#include "core/rendering/style/StyleDeprecatedFlexibleBoxData.h"
+#include "core/rendering/style/StyleDifference.h"
#include "core/rendering/style/StyleFilterData.h"
#include "core/rendering/style/StyleFlexibleBoxData.h"
#include "core/rendering/style/StyleGridData.h"
#include "core/rendering/style/StyleGridItemData.h"
+#include "core/rendering/style/StyleInheritedData.h"
#include "core/rendering/style/StyleMarqueeData.h"
#include "core/rendering/style/StyleMultiColData.h"
#include "core/rendering/style/StyleRareInheritedData.h"
@@ -54,6 +56,7 @@
#include "core/rendering/style/StyleSurroundData.h"
#include "core/rendering/style/StyleTransformData.h"
#include "core/rendering/style/StyleVisualData.h"
+#include "core/rendering/style/StyleWillChangeData.h"
#include "core/svg/SVGPaint.h"
#include "platform/Length.h"
#include "platform/LengthBox.h"
@@ -61,10 +64,12 @@
#include "platform/ThemeTypes.h"
#include "platform/fonts/FontBaseline.h"
#include "platform/fonts/FontDescription.h"
+#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/LayoutBoxExtent.h"
#include "platform/geometry/RoundedRect.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsTypes.h"
+#include "platform/scroll/ScrollableArea.h"
#include "platform/text/TextDirection.h"
#include "platform/text/UnicodeBidi.h"
#include "platform/transforms/TransformOperations.h"
@@ -80,6 +85,10 @@ 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_VAR_WITH_SETTER(group, getter, setter, value) \
+ if (!compareEqual(group->getter(), value)) \
+ group.access()->setter(value)
+
#define SET_BORDERVALUE_COLOR(group, variable, value) \
if (!compareEqual(group->variable.color(), value)) \
group.access()->variable.setColor(value)
@@ -90,13 +99,11 @@ using std::max;
class FilterOperations;
+class AppliedTextDecoration;
class BorderData;
class CounterContent;
-class CursorList;
class Font;
class FontMetrics;
-class IntRect;
-class Pair;
class ShadowList;
class StyleImage;
class StyleInheritedData;
@@ -110,11 +117,11 @@ typedef Vector<RefPtr<RenderStyle>, 4> PseudoStyleCache;
class RenderStyle: public RefCounted<RenderStyle> {
friend class AnimatedStyleBuilder; // Used by Web Animations CSS. Sets the color styles
friend class CSSAnimatableValueFactory; // Used by Web Animations CSS. Gets visited and unvisited colors separately.
- friend class CSSPropertyAnimation; // Used by CSS animations. We can't allow them to animate based off visited colors.
+ friend class CSSPropertyEquality; // 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 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 PropertyWrapperMaybeInvalidStyleColor; // Used by CSS animations. We can't allow them to animate based off visited colors.
friend class StyleBuilderFunctions; // Sets color styles
friend class CachedUAStyle; // Saves Border/Background information for later comparison.
@@ -156,7 +163,7 @@ protected:
&& (_visibility == other._visibility)
&& (_text_align == other._text_align)
&& (_text_transform == other._text_transform)
- && (_text_decorations == other._text_decorations)
+ && (m_textUnderline == other.m_textUnderline)
&& (_cursor_style == other._cursor_style)
&& (_direction == other._direction)
&& (_white_space == other._white_space)
@@ -178,24 +185,23 @@ protected:
unsigned _visibility : 2; // EVisibility
unsigned _text_align : 4; // ETextAlign
unsigned _text_transform : 2; // ETextTransform
- unsigned _text_decorations : TextDecorationBits;
+ unsigned m_textUnderline : 1;
unsigned _cursor_style : 6; // ECursor
unsigned _direction : 1; // TextDirection
unsigned _white_space : 3; // EWhiteSpace
- // 32 bits
unsigned _border_collapse : 1; // EBorderCollapse
unsigned _box_direction : 1; // EBoxDirection (CSS3 box_direction property, flexible box layout module)
+ // 32 bits
// non CSS2 inherited
unsigned m_rtlOrdering : 1; // Order
unsigned m_printColorAdjust : PrintColorAdjustBits;
unsigned _pointerEvents : 4; // EPointerEvents
unsigned _insideLink : 2; // EInsideLink
- // 43 bits
// CSS Text Layout Module Level 3: Vertical writing support
unsigned m_writingMode : 2; // WritingMode
- // 45 bits
+ // 42 bits
} inherited_flags;
// don't inherit
@@ -243,7 +249,13 @@ protected:
unsigned _table_layout : 1; // ETableLayout
unsigned _unicodeBidi : 3; // EUnicodeBidi
- // 31 bits
+
+ // This is set if we used viewport units when resolving a length.
+ // It is mutable so we can pass around const RenderStyles to resolve lengths.
+ mutable unsigned hasViewportUnits : 1;
+
+ // 32 bits
+
unsigned _page_break_before : 2; // EPageBreak
unsigned _page_break_after : 2; // EPageBreak
unsigned _page_break_inside : 2; // EPageBreak
@@ -274,7 +286,7 @@ protected:
unsigned _affectedByDrag : 1;
unsigned _isLink : 1;
// If you add more style bits here, you will also need to update RenderStyle::copyNonInheritedFrom()
- // 60 bits
+ // 63 bits
} noninherited_flags;
// !END SYNC!
@@ -289,7 +301,7 @@ protected:
inherited_flags._visibility = initialVisibility();
inherited_flags._text_align = initialTextAlign();
inherited_flags._text_transform = initialTextTransform();
- inherited_flags._text_decorations = initialTextDecoration();
+ inherited_flags.m_textUnderline = false;
inherited_flags._cursor_style = initialCursor();
inherited_flags._direction = initialDirection();
inherited_flags._white_space = initialWhiteSpace();
@@ -321,6 +333,7 @@ protected:
noninherited_flags.emptyState = false;
noninherited_flags.firstChildState = false;
noninherited_flags.lastChildState = false;
+ noninherited_flags.hasViewportUnits = false;
noninherited_flags.setAffectedByFocus(false);
noninherited_flags.setAffectedByHover(false);
noninherited_flags.setAffectedByActive(false);
@@ -343,7 +356,11 @@ public:
static PassRefPtr<RenderStyle> createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay);
static PassRefPtr<RenderStyle> clone(const RenderStyle*);
- static StyleRecalcChange compare(const RenderStyle* oldStyle, const RenderStyle* newStyle);
+ // Computes how the style change should be propagated down the tree.
+ static StyleRecalcChange stylePropagationDiff(const RenderStyle* oldStyle, const RenderStyle* newStyle);
+
+ // Computes how much visual invalidation the style change causes: layout, repaint or recomposite.
+ StyleDifference visualInvalidationDiff(const RenderStyle&, unsigned& changedContextSensitiveProperties) const;
enum IsAtShadowBoundary {
AtShadowBoundary,
@@ -362,8 +379,8 @@ public:
const PseudoStyleCache* cachedPseudoStyles() const { return m_cachedPseudoStyles.get(); }
- void setVariable(const AtomicString& name, const String& value) { rareInheritedData.access()->m_variables.access()->setVariable(name, value); }
- const HashMap<AtomicString, String>* variables() { return &(rareInheritedData->m_variables->m_data); }
+ void setHasViewportUnits(bool hasViewportUnits = true) const { noninherited_flags.hasViewportUnits = hasViewportUnits; }
+ bool hasViewportUnits() const { return noninherited_flags.hasViewportUnits; }
bool affectedByFocus() const { return noninherited_flags.affectedByFocus(); }
bool affectedByHover() const { return noninherited_flags.affectedByHover(); }
@@ -395,7 +412,7 @@ public:
bool hasBackground() const
{
Color color = visitedDependentColor(CSSPropertyBackgroundColor);
- if (color.isValid() && color.alpha())
+ if (color.alpha())
return true;
return hasBackgroundImage();
}
@@ -427,22 +444,23 @@ public:
bool hasPseudoStyle(PseudoId pseudo) const;
void setHasPseudoStyle(PseudoId pseudo);
bool hasUniquePseudoStyle() const;
+ bool hasPseudoElementStyle() const;
// attribute getter methods
EDisplay display() const { return static_cast<EDisplay>(noninherited_flags._effectiveDisplay); }
EDisplay originalDisplay() const { return static_cast<EDisplay>(noninherited_flags._originalDisplay); }
- Length left() const { return surround->offset.left(); }
- Length right() const { return surround->offset.right(); }
- Length top() const { return surround->offset.top(); }
- Length bottom() const { return surround->offset.bottom(); }
+ const Length& left() const { return surround->offset.left(); }
+ const Length& right() const { return surround->offset.right(); }
+ const Length& top() const { return surround->offset.top(); }
+ const Length& bottom() const { return surround->offset.bottom(); }
// Accessors for positioned object edges that take into account writing mode.
- Length logicalLeft() const { return surround->offset.logicalLeft(writingMode()); }
- Length logicalRight() const { return surround->offset.logicalRight(writingMode()); }
- Length logicalTop() const { return surround->offset.before(writingMode()); }
- Length logicalBottom() const { return surround->offset.after(writingMode()); }
+ const Length& logicalLeft() const { return surround->offset.logicalLeft(writingMode()); }
+ const Length& logicalRight() const { return surround->offset.logicalRight(writingMode()); }
+ const Length& logicalTop() const { return surround->offset.before(writingMode()); }
+ const Length& logicalBottom() const { return surround->offset.after(writingMode()); }
// Whether or not a positioned element requires normal flow x/y to be computed
// to determine its position.
@@ -457,19 +475,19 @@ public:
bool hasViewportConstrainedPosition() const { return position() == FixedPosition || position() == StickyPosition; }
EFloat floating() const { return static_cast<EFloat>(noninherited_flags._floating); }
- Length width() const { return m_box->width(); }
- Length height() const { return m_box->height(); }
- Length minWidth() const { return m_box->minWidth(); }
- Length maxWidth() const { return m_box->maxWidth(); }
- Length minHeight() const { return m_box->minHeight(); }
- Length maxHeight() const { return m_box->maxHeight(); }
+ const Length& width() const { return m_box->width(); }
+ const Length& height() const { return m_box->height(); }
+ const Length& minWidth() const { return m_box->minWidth(); }
+ const Length& maxWidth() const { return m_box->maxWidth(); }
+ const Length& minHeight() const { return m_box->minHeight(); }
+ const Length& maxHeight() const { return m_box->maxHeight(); }
- Length logicalWidth() const { return isHorizontalWritingMode() ? width() : height(); }
- Length logicalHeight() const { return isHorizontalWritingMode() ? height() : width(); }
- Length logicalMinWidth() const { return isHorizontalWritingMode() ? minWidth() : minHeight(); }
- Length logicalMaxWidth() const { return isHorizontalWritingMode() ? maxWidth() : maxHeight(); }
- Length logicalMinHeight() const { return isHorizontalWritingMode() ? minHeight() : minWidth(); }
- Length logicalMaxHeight() const { return isHorizontalWritingMode() ? maxHeight() : maxWidth(); }
+ const Length& logicalWidth() const { return isHorizontalWritingMode() ? width() : height(); }
+ const Length& logicalHeight() const { return isHorizontalWritingMode() ? height() : width(); }
+ const Length& logicalMinWidth() const { return isHorizontalWritingMode() ? minWidth() : minHeight(); }
+ const Length& logicalMaxWidth() const { return isHorizontalWritingMode() ? maxWidth() : maxHeight(); }
+ const Length& logicalMinHeight() const { return isHorizontalWritingMode() ? minHeight() : minWidth(); }
+ const Length& logicalMaxHeight() const { return isHorizontalWritingMode() ? maxHeight() : maxWidth(); }
const BorderData& border() const { return surround->border; }
const BorderValue& borderLeft() const { return surround->border.left(); }
@@ -484,14 +502,14 @@ public:
const NinePieceImage& borderImage() const { return surround->border.image(); }
StyleImage* borderImageSource() const { return surround->border.image().image(); }
- LengthBox borderImageSlices() const { return surround->border.image().imageSlices(); }
+ const LengthBox& borderImageSlices() const { return surround->border.image().imageSlices(); }
const BorderImageLengthBox& borderImageWidth() const { return surround->border.image().borderSlices(); }
const BorderImageLengthBox& borderImageOutset() const { return surround->border.image().outset(); }
- LengthSize borderTopLeftRadius() const { return surround->border.topLeft(); }
- LengthSize borderTopRightRadius() const { return surround->border.topRight(); }
- LengthSize borderBottomLeftRadius() const { return surround->border.bottomLeft(); }
- LengthSize borderBottomRightRadius() const { return surround->border.bottomRight(); }
+ const LengthSize& borderTopLeftRadius() const { return surround->border.topLeft(); }
+ const LengthSize& borderTopRightRadius() const { return surround->border.topRight(); }
+ const LengthSize& borderBottomLeftRadius() const { return surround->border.bottomLeft(); }
+ const LengthSize& borderBottomRightRadius() const { return surround->border.bottomRight(); }
bool hasBorderRadius() const { return surround->border.hasBorderRadius(); }
unsigned borderLeftWidth() const { return surround->border.borderLeftWidth(); }
@@ -525,22 +543,26 @@ public:
EOverflow overflowX() const { return static_cast<EOverflow>(noninherited_flags._overflowX); }
EOverflow overflowY() const { return static_cast<EOverflow>(noninherited_flags._overflowY); }
+ // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value.
+ bool isOverflowVisible() const { ASSERT(overflowX() != OVISIBLE || overflowX() == overflowY()); return overflowX() == OVISIBLE; }
+ bool isOverflowPaged() const { return overflowY() == OPAGEDX || overflowY() == OPAGEDY; }
EVisibility visibility() const { return static_cast<EVisibility>(inherited_flags._visibility); }
EVerticalAlign verticalAlign() const { return static_cast<EVerticalAlign>(noninherited_flags._vertical_align); }
- Length verticalAlignLength() const { return m_box->verticalAlign(); }
+ const Length& verticalAlignLength() const { return m_box->verticalAlign(); }
- Length clipLeft() const { return visual->clip.left(); }
- Length clipRight() const { return visual->clip.right(); }
- Length clipTop() const { return visual->clip.top(); }
- Length clipBottom() const { return visual->clip.bottom(); }
- LengthBox clip() const { return visual->clip; }
+ const Length& clipLeft() const { return visual->clip.left(); }
+ const Length& clipRight() const { return visual->clip.right(); }
+ const Length& clipTop() const { return visual->clip.top(); }
+ const Length& clipBottom() const { return visual->clip.bottom(); }
+ const LengthBox& clip() const { return visual->clip; }
bool hasClip() const { return visual->hasClip; }
EUnicodeBidi unicodeBidi() const { return static_cast<EUnicodeBidi>(noninherited_flags._unicodeBidi); }
EClear clear() const { return static_cast<EClear>(noninherited_flags._clear); }
ETableLayout tableLayout() const { return static_cast<ETableLayout>(noninherited_flags._table_layout); }
+ bool isFixedTableLayout() const { return tableLayout() == TFIXED && !logicalWidth().isAuto(); }
const Font& font() const;
const FontMetrics& fontMetrics() const;
@@ -548,16 +570,19 @@ public:
float specifiedFontSize() const;
float computedFontSize() const;
int fontSize() const;
+ FontWeight fontWeight() const;
- float textAutosizingMultiplier() const { return visual->m_textAutosizingMultiplier; }
+ float textAutosizingMultiplier() const { return inherited->textAutosizingMultiplier; }
- Length textIndent() const { return rareInheritedData->indent; }
+ const Length& textIndent() const { return rareInheritedData->indent; }
TextIndentLine textIndentLine() const { return static_cast<TextIndentLine>(rareInheritedData->m_textIndentLine); }
+ TextIndentType textIndentType() const { return static_cast<TextIndentType>(rareInheritedData->m_textIndentType); }
ETextAlign textAlign() const { return static_cast<ETextAlign>(inherited_flags._text_align); }
TextAlignLast textAlignLast() const { return static_cast<TextAlignLast>(rareInheritedData->m_textAlignLast); }
TextJustify textJustify() const { return static_cast<TextJustify>(rareInheritedData->m_textJustify); }
ETextTransform textTransform() const { return static_cast<ETextTransform>(inherited_flags._text_transform); }
- TextDecoration textDecorationsInEffect() const { return static_cast<TextDecoration>(inherited_flags._text_decorations); }
+ TextDecoration textDecorationsInEffect() const;
+ const Vector<AppliedTextDecoration>& appliedTextDecorations() const;
TextDecoration textDecoration() const { return static_cast<TextDecoration>(visual->textDecoration); }
TextUnderlinePosition textUnderlinePosition() const { return static_cast<TextUnderlinePosition>(rareInheritedData->m_textUnderlinePosition); }
TextDecorationStyle textDecorationStyle() const { return static_cast<TextDecorationStyle>(rareNonInheritedData->m_textDecorationStyle); }
@@ -570,9 +595,9 @@ public:
TextDirection direction() const { return static_cast<TextDirection>(inherited_flags._direction); }
bool isLeftToRightDirection() const { return direction() == LTR; }
- Length specifiedLineHeight() const;
+ const Length& specifiedLineHeight() const;
Length lineHeight() const;
- int computedLineHeight(RenderView* = 0) const;
+ int computedLineHeight() const;
EWhiteSpace whiteSpace() const { return static_cast<EWhiteSpace>(inherited_flags._white_space); }
static bool autoWrap(EWhiteSpace ws)
@@ -636,10 +661,10 @@ public:
EFillAttachment backgroundAttachment() const { return static_cast<EFillAttachment>(m_background->background().attachment()); }
EFillBox backgroundClip() const { return static_cast<EFillBox>(m_background->background().clip()); }
EFillBox backgroundOrigin() const { return static_cast<EFillBox>(m_background->background().origin()); }
- Length backgroundXPosition() const { return m_background->background().xPosition(); }
- Length backgroundYPosition() const { return m_background->background().yPosition(); }
+ const Length& backgroundXPosition() const { return m_background->background().xPosition(); }
+ const Length& backgroundYPosition() const { return m_background->background().yPosition(); }
EFillSizeType backgroundSizeType() const { return m_background->background().sizeType(); }
- LengthSize backgroundSizeLength() const { return m_background->background().sizeLength(); }
+ const LengthSize& backgroundSizeLength() const { return m_background->background().sizeLength(); }
FillLayer* accessBackgroundLayers() { return &(m_background.access()->m_background); }
const FillLayer* backgroundLayers() const { return &(m_background->background()); }
@@ -649,16 +674,16 @@ public:
CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.composite()); }
EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.clip()); }
EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.origin()); }
- Length maskXPosition() const { return rareNonInheritedData->m_mask.xPosition(); }
- Length maskYPosition() const { return rareNonInheritedData->m_mask.yPosition(); }
+ const Length& maskXPosition() const { return rareNonInheritedData->m_mask.xPosition(); }
+ const Length& maskYPosition() const { return rareNonInheritedData->m_mask.yPosition(); }
EFillSizeType maskSizeType() const { return rareNonInheritedData->m_mask.sizeType(); }
- LengthSize maskSizeLength() const { return rareNonInheritedData->m_mask.sizeLength(); }
+ const LengthSize& maskSizeLength() const { return rareNonInheritedData->m_mask.sizeLength(); }
FillLayer* accessMaskLayers() { return &(rareNonInheritedData.access()->m_mask); }
const FillLayer* maskLayers() const { return &(rareNonInheritedData->m_mask); }
const NinePieceImage& maskBoxImage() const { return rareNonInheritedData->m_maskBoxImage; }
StyleImage* maskBoxImageSource() const { return rareNonInheritedData->m_maskBoxImage.image(); }
- LengthBox maskBoxImageSlices() const { return rareNonInheritedData->m_maskBoxImage.imageSlices(); }
+ const LengthBox& maskBoxImageSlices() const { return rareNonInheritedData->m_maskBoxImage.imageSlices(); }
bool maskBoxImageSlicesFill() const { return rareNonInheritedData->m_maskBoxImage.fill(); }
const BorderImageLengthBox& maskBoxImageWidth() const { return rareNonInheritedData->m_maskBoxImage.borderSlices(); }
const BorderImageLengthBox& maskBoxImageOutset() const { return rareNonInheritedData->m_maskBoxImage.outset(); }
@@ -673,28 +698,28 @@ public:
StyleImage* listStyleImage() const;
EListStylePosition listStylePosition() const { return static_cast<EListStylePosition>(inherited_flags._list_style_position); }
- Length marginTop() const { return surround->margin.top(); }
- Length marginBottom() const { return surround->margin.bottom(); }
- Length marginLeft() const { return surround->margin.left(); }
- Length marginRight() const { return surround->margin.right(); }
- Length marginBefore() const { return surround->margin.before(writingMode()); }
- Length marginAfter() const { return surround->margin.after(writingMode()); }
- Length marginStart() const { return surround->margin.start(writingMode(), direction()); }
- Length marginEnd() const { return surround->margin.end(writingMode(), direction()); }
- Length marginStartUsing(const RenderStyle* otherStyle) const { return surround->margin.start(otherStyle->writingMode(), otherStyle->direction()); }
- Length marginEndUsing(const RenderStyle* otherStyle) const { return surround->margin.end(otherStyle->writingMode(), otherStyle->direction()); }
- Length marginBeforeUsing(const RenderStyle* otherStyle) const { return surround->margin.before(otherStyle->writingMode()); }
- Length marginAfterUsing(const RenderStyle* otherStyle) const { return surround->margin.after(otherStyle->writingMode()); }
-
- LengthBox paddingBox() const { return surround->padding; }
- Length paddingTop() const { return surround->padding.top(); }
- Length paddingBottom() const { return surround->padding.bottom(); }
- Length paddingLeft() const { return surround->padding.left(); }
- Length paddingRight() const { return surround->padding.right(); }
- Length paddingBefore() const { return surround->padding.before(writingMode()); }
- Length paddingAfter() const { return surround->padding.after(writingMode()); }
- Length paddingStart() const { return surround->padding.start(writingMode(), direction()); }
- Length paddingEnd() const { return surround->padding.end(writingMode(), direction()); }
+ const Length& marginTop() const { return surround->margin.top(); }
+ const Length& marginBottom() const { return surround->margin.bottom(); }
+ const Length& marginLeft() const { return surround->margin.left(); }
+ const Length& marginRight() const { return surround->margin.right(); }
+ const Length& marginBefore() const { return surround->margin.before(writingMode()); }
+ const Length& marginAfter() const { return surround->margin.after(writingMode()); }
+ const Length& marginStart() const { return surround->margin.start(writingMode(), direction()); }
+ const Length& marginEnd() const { return surround->margin.end(writingMode(), direction()); }
+ const Length& marginStartUsing(const RenderStyle* otherStyle) const { return surround->margin.start(otherStyle->writingMode(), otherStyle->direction()); }
+ const Length& marginEndUsing(const RenderStyle* otherStyle) const { return surround->margin.end(otherStyle->writingMode(), otherStyle->direction()); }
+ const Length& marginBeforeUsing(const RenderStyle* otherStyle) const { return surround->margin.before(otherStyle->writingMode()); }
+ const Length& marginAfterUsing(const RenderStyle* otherStyle) const { return surround->margin.after(otherStyle->writingMode()); }
+
+ const LengthBox& paddingBox() const { return surround->padding; }
+ const Length& paddingTop() const { return surround->padding.top(); }
+ const Length& paddingBottom() const { return surround->padding.bottom(); }
+ const Length& paddingLeft() const { return surround->padding.left(); }
+ const Length& paddingRight() const { return surround->padding.right(); }
+ const Length& paddingBefore() const { return surround->padding.before(writingMode()); }
+ const Length& paddingAfter() const { return surround->padding.after(writingMode()); }
+ const Length& paddingStart() const { return surround->padding.start(writingMode(), direction()); }
+ const Length& paddingEnd() const { return surround->padding.end(writingMode(), direction()); }
ECursor cursor() const { return static_cast<ECursor>(inherited_flags._cursor_style); }
CursorList* cursors() const { return rareInheritedData->cursorData.get(); }
@@ -737,9 +762,9 @@ public:
EBoxAlignment boxAlign() const { return static_cast<EBoxAlignment>(rareNonInheritedData->m_deprecatedFlexibleBox->align); }
EBoxDirection boxDirection() const { return static_cast<EBoxDirection>(inherited_flags._box_direction); }
float boxFlex() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flex; }
- unsigned int boxFlexGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flex_group; }
+ unsigned boxFlexGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flexGroup; }
EBoxLines boxLines() const { return static_cast<EBoxLines>(rareNonInheritedData->m_deprecatedFlexibleBox->lines); }
- unsigned int boxOrdinalGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->ordinal_group; }
+ unsigned boxOrdinalGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->ordinalGroup; }
EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->m_deprecatedFlexibleBox->orient); }
EBoxPack boxPack() const { return static_cast<EBoxPack>(rareNonInheritedData->m_deprecatedFlexibleBox->pack); }
@@ -747,18 +772,22 @@ public:
const Vector<String>& callbackSelectors() const { return rareNonInheritedData->m_callbackSelectors; }
float flexGrow() const { return rareNonInheritedData->m_flexibleBox->m_flexGrow; }
float flexShrink() const { return rareNonInheritedData->m_flexibleBox->m_flexShrink; }
- Length flexBasis() const { return rareNonInheritedData->m_flexibleBox->m_flexBasis; }
+ const Length& flexBasis() const { return rareNonInheritedData->m_flexibleBox->m_flexBasis; }
EAlignContent alignContent() const { return static_cast<EAlignContent>(rareNonInheritedData->m_alignContent); }
- EAlignItems alignItems() const { return static_cast<EAlignItems>(rareNonInheritedData->m_alignItems); }
- EAlignItems alignSelf() const { return static_cast<EAlignItems>(rareNonInheritedData->m_alignSelf); }
+ ItemPosition alignItems() const { return static_cast<ItemPosition>(rareNonInheritedData->m_alignItems); }
+ OverflowAlignment alignItemsOverflowAlignment() const { return static_cast<OverflowAlignment>(rareNonInheritedData->m_alignItemsOverflowAlignment); }
+ ItemPosition alignSelf() const { return static_cast<ItemPosition>(rareNonInheritedData->m_alignSelf); }
+ OverflowAlignment alignSelfOverflowAlignment() const { return static_cast<OverflowAlignment>(rareNonInheritedData->m_alignSelfOverflowAlignment); }
EFlexDirection flexDirection() const { return static_cast<EFlexDirection>(rareNonInheritedData->m_flexibleBox->m_flexDirection); }
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); }
EJustifyContent justifyContent() const { return static_cast<EJustifyContent>(rareNonInheritedData->m_justifyContent); }
+ ItemPosition justifySelf() const { return static_cast<ItemPosition>(rareNonInheritedData->m_justifySelf); }
+ OverflowAlignment justifySelfOverflowAlignment() const { return static_cast<OverflowAlignment>(rareNonInheritedData->m_justifySelfOverflowAlignment); }
- const Vector<GridTrackSize>& gridDefinitionColumns() const { return rareNonInheritedData->m_grid->m_gridDefinitionColumns; }
- const Vector<GridTrackSize>& gridDefinitionRows() const { return rareNonInheritedData->m_grid->m_gridDefinitionRows; }
+ const Vector<GridTrackSize>& gridTemplateColumns() const { return rareNonInheritedData->m_grid->m_gridTemplateColumns; }
+ const Vector<GridTrackSize>& gridTemplateRows() const { return rareNonInheritedData->m_grid->m_gridTemplateRows; }
const NamedGridLinesMap& namedGridColumnLines() const { return rareNonInheritedData->m_grid->m_namedGridColumnLines; }
const NamedGridLinesMap& namedGridRowLines() const { return rareNonInheritedData->m_grid->m_namedGridRowLines; }
const OrderedNamedGridLines& orderedNamedGridColumnLines() const { return rareNonInheritedData->m_grid->m_orderedNamedGridColumnLines; }
@@ -785,8 +814,10 @@ public:
EBoxDecorationBreak boxDecorationBreak() const { return m_box->boxDecorationBreak(); }
StyleReflection* boxReflect() const { return rareNonInheritedData->m_boxReflect.get(); }
+ bool reflectionDataEquivalent(const RenderStyle* otherStyle) const { return rareNonInheritedData->reflectionDataEquivalent(*otherStyle->rareNonInheritedData); }
+
EBoxSizing boxSizing() const { return m_box->boxSizing(); }
- Length marqueeIncrement() const { return rareNonInheritedData->m_marquee->increment; }
+ const Length& marqueeIncrement() const { return rareNonInheritedData->m_marquee->increment; }
int marqueeSpeed() const { return rareNonInheritedData->m_marquee->speed; }
int marqueeLoopCount() const { return rareNonInheritedData->m_marquee->loops; }
EMarqueeBehavior marqueeBehavior() const { return static_cast<EMarqueeBehavior>(rareNonInheritedData->m_marquee->behavior); }
@@ -805,18 +836,20 @@ public:
const AtomicString& locale() const { return rareInheritedData->locale; }
EBorderFit borderFit() const { return static_cast<EBorderFit>(rareNonInheritedData->m_borderFit); }
EResize resize() const { return static_cast<EResize>(rareInheritedData->resize); }
- ColumnAxis columnAxis() const { return static_cast<ColumnAxis>(rareNonInheritedData->m_multiCol->m_axis); }
- bool hasInlineColumnAxis() const {
- ColumnAxis axis = columnAxis();
- return axis == AutoColumnAxis || isHorizontalWritingMode() == (axis == HorizontalColumnAxis);
+ bool hasInlinePaginationAxis() const
+ {
+ // If the pagination axis is parallel with the writing mode inline axis, columns may be laid
+ // out along the inline axis, just like for regular multicol. Otherwise, we need to lay out
+ // along the block axis.
+ if (isOverflowPaged())
+ return (overflowY() == OPAGEDX) == isHorizontalWritingMode();
+ return false;
}
- ColumnProgression columnProgression() const { return static_cast<ColumnProgression>(rareNonInheritedData->m_multiCol->m_progression); }
float columnWidth() const { return rareNonInheritedData->m_multiCol->m_width; }
bool hasAutoColumnWidth() const { return rareNonInheritedData->m_multiCol->m_autoWidth; }
unsigned short columnCount() const { return rareNonInheritedData->m_multiCol->m_count; }
bool hasAutoColumnCount() const { return rareNonInheritedData->m_multiCol->m_autoCount; }
- bool specifiesAutoColumns() const { return hasAutoColumnCount() && hasAutoColumnWidth(); }
- bool specifiesColumns() const { return !hasAutoColumnCount() || !hasAutoColumnWidth() || !hasInlineColumnAxis(); }
+ bool specifiesColumns() const { return !hasAutoColumnCount() || !hasAutoColumnWidth(); }
ColumnFill columnFill() const { return static_cast<ColumnFill>(rareNonInheritedData->m_multiCol->m_fill); }
float columnGap() const { return rareNonInheritedData->m_multiCol->m_gap; }
bool hasNormalColumnGap() const { return rareNonInheritedData->m_multiCol->m_normalGap; }
@@ -827,14 +860,12 @@ public:
EPageBreak columnBreakBefore() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakBefore); }
EPageBreak columnBreakInside() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakInside); }
EPageBreak columnBreakAfter() const { return static_cast<EPageBreak>(rareNonInheritedData->m_multiCol->m_breakAfter); }
- EPageBreak regionBreakBefore() const { return static_cast<EPageBreak>(rareNonInheritedData->m_regionBreakBefore); }
- EPageBreak regionBreakInside() const { return static_cast<EPageBreak>(rareNonInheritedData->m_regionBreakInside); }
- EPageBreak regionBreakAfter() const { return static_cast<EPageBreak>(rareNonInheritedData->m_regionBreakAfter); }
const TransformOperations& transform() const { return rareNonInheritedData->m_transform->m_operations; }
- Length transformOriginX() const { return rareNonInheritedData->m_transform->m_x; }
- Length transformOriginY() const { return rareNonInheritedData->m_transform->m_y; }
+ const Length& transformOriginX() const { return rareNonInheritedData->m_transform->m_x; }
+ const Length& transformOriginY() const { return rareNonInheritedData->m_transform->m_y; }
float transformOriginZ() const { return rareNonInheritedData->m_transform->m_z; }
bool hasTransform() const { return !rareNonInheritedData->m_transform->m_operations.operations().isEmpty(); }
+ bool transformDataEquivalent(const RenderStyle& otherStyle) const { return rareNonInheritedData->m_transform == otherStyle.rareNonInheritedData->m_transform; }
TextEmphasisFill textEmphasisFill() const { return static_cast<TextEmphasisFill>(rareInheritedData->textEmphasisFill); }
TextEmphasisMark textEmphasisMark() const;
@@ -866,30 +897,16 @@ public:
// End CSS3 Getters
- const AtomicString& flowThread() const { return rareNonInheritedData->m_flowThread; }
- bool hasFlowFrom() const { return !rareNonInheritedData->m_regionThread.isNull(); }
- const AtomicString& regionThread() const { return rareNonInheritedData->m_regionThread; }
- RegionFragment regionFragment() const { return static_cast<RegionFragment>(rareNonInheritedData->m_regionFragment); }
-
- const AtomicString& lineGrid() const { return rareInheritedData->m_lineGrid; }
- LineSnap lineSnap() const { return static_cast<LineSnap>(rareInheritedData->m_lineSnap); }
- LineAlign lineAlign() const { return static_cast<LineAlign>(rareInheritedData->m_lineAlign); }
-
WrapFlow wrapFlow() const { return static_cast<WrapFlow>(rareNonInheritedData->m_wrapFlow); }
WrapThrough wrapThrough() const { return static_cast<WrapThrough>(rareNonInheritedData->m_wrapThrough); }
// Apple-specific property getter methods
EPointerEvents pointerEvents() const { return static_cast<EPointerEvents>(inherited_flags._pointerEvents); }
- const CSSAnimationDataList* animations() const { return rareNonInheritedData->m_animations.get(); }
- const CSSAnimationDataList* transitions() const { return rareNonInheritedData->m_transitions.get(); }
+ const CSSAnimationData* animations() const { return rareNonInheritedData->m_animations.get(); }
+ const CSSTransitionData* transitions() const { return rareNonInheritedData->m_transitions.get(); }
- CSSAnimationDataList* accessAnimations();
- CSSAnimationDataList* accessTransitions();
-
- bool hasAnimations() const { return rareNonInheritedData->m_animations && rareNonInheritedData->m_animations->size() > 0; }
-
- // return the first found Animation (including 'all' transitions)
- const CSSAnimationData* transitionForProperty(CSSPropertyID) const;
+ CSSAnimationData& accessAnimations();
+ CSSTransitionData& accessTransitions();
ETransformStyle3D transformStyle3D() const { return static_cast<ETransformStyle3D>(rareNonInheritedData->m_transformStyle3D); }
bool preserves3D() const { return rareNonInheritedData->m_transformStyle3D == TransformStyle3DPreserve3D; }
@@ -897,13 +914,20 @@ public:
EBackfaceVisibility backfaceVisibility() const { return static_cast<EBackfaceVisibility>(rareNonInheritedData->m_backfaceVisibility); }
float perspective() const { return rareNonInheritedData->m_perspective; }
bool hasPerspective() const { return rareNonInheritedData->m_perspective > 0; }
- Length perspectiveOriginX() const { return rareNonInheritedData->m_perspectiveOriginX; }
- Length perspectiveOriginY() const { return rareNonInheritedData->m_perspectiveOriginY; }
- LengthSize pageSize() const { return rareNonInheritedData->m_pageSize; }
+ const Length& perspectiveOriginX() const { return rareNonInheritedData->m_perspectiveOriginX; }
+ const Length& perspectiveOriginY() const { return rareNonInheritedData->m_perspectiveOriginY; }
+ const LengthSize& pageSize() const { return rareNonInheritedData->m_pageSize; }
PageSizeType pageSizeType() const { return static_cast<PageSizeType>(rareNonInheritedData->m_pageSizeType); }
- // When set, this ensures that styles compare as different. Used during accelerated animations.
- bool isRunningAcceleratedAnimation() const { return rareNonInheritedData->m_runningAcceleratedAnimation; }
+ bool hasCurrentOpacityAnimation() const { return rareNonInheritedData->m_hasCurrentOpacityAnimation; }
+ bool hasCurrentTransformAnimation() const { return rareNonInheritedData->m_hasCurrentTransformAnimation; }
+ bool hasCurrentFilterAnimation() const { return rareNonInheritedData->m_hasCurrentFilterAnimation; }
+ bool shouldCompositeForCurrentAnimations() { return hasCurrentOpacityAnimation() || hasCurrentTransformAnimation() || hasCurrentFilterAnimation(); }
+
+ bool isRunningOpacityAnimationOnCompositor() const { return rareNonInheritedData->m_runningOpacityAnimationOnCompositor; }
+ bool isRunningTransformAnimationOnCompositor() const { return rareNonInheritedData->m_runningTransformAnimationOnCompositor; }
+ bool isRunningFilterAnimationOnCompositor() const { return rareNonInheritedData->m_runningFilterAnimationOnCompositor; }
+ bool isRunningAnimationOnCompositor() { return isRunningOpacityAnimationOnCompositor() || isRunningTransformAnimationOnCompositor() || isRunningFilterAnimationOnCompositor(); }
LineBoxContain lineBoxContain() const { return rareInheritedData->m_lineBoxContain; }
const LineClampValue& lineClamp() const { return rareNonInheritedData->lineClamp; }
@@ -936,6 +960,14 @@ public:
TouchAction touchAction() const { return static_cast<TouchAction>(rareNonInheritedData->m_touchAction); }
TouchActionDelay touchActionDelay() const { return static_cast<TouchActionDelay>(rareInheritedData->m_touchActionDelay); }
+ ScrollBehavior scrollBehavior() const { return static_cast<ScrollBehavior>(rareNonInheritedData->m_scrollBehavior); }
+
+ const Vector<CSSPropertyID>& willChangeProperties() const { return rareNonInheritedData->m_willChange->m_properties; }
+ bool willChangeContents() const { return rareNonInheritedData->m_willChange->m_contents; }
+ bool willChangeScrollPosition() const { return rareNonInheritedData->m_willChange->m_scrollPosition; }
+ bool hasWillChangeCompositingHint() const;
+ bool subtreeWillChangeContents() const { return rareInheritedData->m_subtreeWillChangeContents; }
+
// attribute setter methods
void setDisplay(EDisplay v) { noninherited_flags._effectiveDisplay = v; }
@@ -943,15 +975,15 @@ public:
void setPosition(EPosition v) { noninherited_flags._position = v; }
void setFloating(EFloat v) { noninherited_flags._floating = v; }
- void setLeft(Length v) { SET_VAR(surround, offset.m_left, v); }
- void setRight(Length v) { SET_VAR(surround, offset.m_right, v); }
- void setTop(Length v) { SET_VAR(surround, offset.m_top, v); }
- void setBottom(Length v) { SET_VAR(surround, offset.m_bottom, v); }
+ void setLeft(const Length& v) { SET_VAR(surround, offset.m_left, v); }
+ void setRight(const Length& v) { SET_VAR(surround, offset.m_right, v); }
+ void setTop(const Length& v) { SET_VAR(surround, offset.m_top, v); }
+ void setBottom(const Length& v) { SET_VAR(surround, offset.m_bottom, v); }
- void setWidth(Length v) { SET_VAR(m_box, m_width, v); }
- void setHeight(Length v) { SET_VAR(m_box, m_height, v); }
+ void setWidth(const Length& v) { SET_VAR(m_box, m_width, v); }
+ void setHeight(const Length& v) { SET_VAR(m_box, m_height, v); }
- void setLogicalWidth(Length v)
+ void setLogicalWidth(const Length& v)
{
if (isHorizontalWritingMode()) {
SET_VAR(m_box, m_width, v);
@@ -960,7 +992,7 @@ public:
}
}
- void setLogicalHeight(Length v)
+ void setLogicalHeight(const Length& v)
{
if (isHorizontalWritingMode()) {
SET_VAR(m_box, m_height, v);
@@ -969,45 +1001,55 @@ public:
}
}
- void setMinWidth(Length v) { SET_VAR(m_box, m_minWidth, v); }
- void setMaxWidth(Length v) { SET_VAR(m_box, m_maxWidth, v); }
- void setMinHeight(Length v) { SET_VAR(m_box, m_minHeight, v); }
- void setMaxHeight(Length v) { SET_VAR(m_box, m_maxHeight, v); }
+ void setMinWidth(const Length& v) { SET_VAR(m_box, m_minWidth, v); }
+ void setMaxWidth(const Length& v) { SET_VAR(m_box, m_maxWidth, v); }
+ void setMinHeight(const Length& v) { SET_VAR(m_box, m_minHeight, v); }
+ void setMaxHeight(const Length& v) { SET_VAR(m_box, m_maxHeight, v); }
DraggableRegionMode getDraggableRegionMode() const { return rareNonInheritedData->m_draggableRegionMode; }
void setDraggableRegionMode(DraggableRegionMode v) { SET_VAR(rareNonInheritedData, m_draggableRegionMode, v); }
- void resetBorder() { resetBorderImage(); resetBorderTop(); resetBorderRight(); resetBorderBottom(); resetBorderLeft(); resetBorderRadius(); }
+ void resetBorder()
+ {
+ resetBorderImage();
+ resetBorderTop();
+ resetBorderRight();
+ resetBorderBottom();
+ resetBorderLeft();
+ resetBorderTopLeftRadius();
+ resetBorderTopRightRadius();
+ resetBorderBottomLeftRadius();
+ resetBorderBottomRightRadius();
+ }
void resetBorderTop() { SET_VAR(surround, border.m_top, BorderValue()); }
void resetBorderRight() { SET_VAR(surround, border.m_right, BorderValue()); }
void resetBorderBottom() { SET_VAR(surround, border.m_bottom, BorderValue()); }
void resetBorderLeft() { SET_VAR(surround, border.m_left, BorderValue()); }
void resetBorderImage() { SET_VAR(surround, border.m_image, NinePieceImage()); }
- void resetBorderRadius() { resetBorderTopLeftRadius(); resetBorderTopRightRadius(); resetBorderBottomLeftRadius(); resetBorderBottomRightRadius(); }
void resetBorderTopLeftRadius() { SET_VAR(surround, border.m_topLeft, initialBorderRadius()); }
void resetBorderTopRightRadius() { SET_VAR(surround, border.m_topRight, initialBorderRadius()); }
void resetBorderBottomLeftRadius() { SET_VAR(surround, border.m_bottomLeft, initialBorderRadius()); }
void resetBorderBottomRightRadius() { SET_VAR(surround, border.m_bottomRight, initialBorderRadius()); }
- void setBackgroundColor(const Color& v) { SET_VAR(m_background, m_color, v); }
+ void setBackgroundColor(const StyleColor& v) { SET_VAR(m_background, m_color, v); }
- void setBackgroundXPosition(Length length) { SET_VAR(m_background, m_background.m_xPosition, length); }
- void setBackgroundYPosition(Length length) { SET_VAR(m_background, m_background.m_yPosition, length); }
+ void setBackgroundXPosition(const Length& length) { SET_VAR(m_background, m_background.m_xPosition, length); }
+ void setBackgroundYPosition(const Length& length) { SET_VAR(m_background, m_background.m_yPosition, length); }
void setBackgroundSize(EFillSizeType b) { SET_VAR(m_background, m_background.m_sizeType, b); }
- void setBackgroundSizeLength(LengthSize s) { SET_VAR(m_background, m_background.m_sizeLength, s); }
+ void setBackgroundSizeLength(const LengthSize& s) { SET_VAR(m_background, m_background.m_sizeLength, s); }
void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.m_image, b); }
void setBorderImageSource(PassRefPtr<StyleImage>);
- void setBorderImageSlices(LengthBox);
+ void setBorderImageSlices(const LengthBox&);
void setBorderImageWidth(const BorderImageLengthBox&);
void setBorderImageOutset(const BorderImageLengthBox&);
- void setBorderTopLeftRadius(LengthSize s) { SET_VAR(surround, border.m_topLeft, s); }
- void setBorderTopRightRadius(LengthSize s) { SET_VAR(surround, border.m_topRight, s); }
- void setBorderBottomLeftRadius(LengthSize s) { SET_VAR(surround, border.m_bottomLeft, s); }
- void setBorderBottomRightRadius(LengthSize s) { SET_VAR(surround, border.m_bottomRight, s); }
+ void setBorderTopLeftRadius(const LengthSize& s) { SET_VAR(surround, border.m_topLeft, s); }
+ void setBorderTopRightRadius(const LengthSize& s) { SET_VAR(surround, border.m_topRight, s); }
+ void setBorderBottomLeftRadius(const LengthSize& s) { SET_VAR(surround, border.m_bottomLeft, s); }
+ void setBorderBottomRightRadius(const LengthSize& s) { SET_VAR(surround, border.m_bottomRight, s); }
- void setBorderRadius(LengthSize s)
+ void setBorderRadius(const LengthSize& s)
{
setBorderTopLeftRadius(s);
setBorderTopRightRadius(s);
@@ -1019,7 +1061,7 @@ public:
setBorderRadius(LengthSize(Length(s.width(), Fixed), Length(s.height(), Fixed)));
}
- RoundedRect getRoundedBorderFor(const LayoutRect& borderRect, RenderView* = 0, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+ RoundedRect getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
RoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
RoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect,
@@ -1027,35 +1069,35 @@ 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_BORDERVALUE_COLOR(surround, border.m_left, v); }
+ void setBorderLeftColor(const StyleColor& 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_BORDERVALUE_COLOR(surround, border.m_right, v); }
+ void setBorderRightColor(const StyleColor& 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_BORDERVALUE_COLOR(surround, border.m_top, v); }
+ void setBorderTopColor(const StyleColor& 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_BORDERVALUE_COLOR(surround, border.m_bottom, v); }
+ void setBorderBottomColor(const StyleColor& 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_BORDERVALUE_COLOR(m_background, m_outline, v); }
+ void setOutlineColor(const StyleColor& 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; }
void setVisibility(EVisibility v) { inherited_flags._visibility = v; }
void setVerticalAlign(EVerticalAlign v) { noninherited_flags._vertical_align = v; }
- void setVerticalAlignLength(Length length) { setVerticalAlign(LENGTH); SET_VAR(m_box, m_verticalAlign, length); }
+ void setVerticalAlignLength(const Length& length) { setVerticalAlign(LENGTH); SET_VAR(m_box, m_verticalAlign, length); }
void setHasClip(bool b = true) { SET_VAR(visual, hasClip, b); }
- void setClipLeft(Length v) { SET_VAR(visual, clip.m_left, v); }
- void setClipRight(Length v) { SET_VAR(visual, clip.m_right, v); }
- void setClipTop(Length v) { SET_VAR(visual, clip.m_top, v); }
- void setClipBottom(Length v) { SET_VAR(visual, clip.m_bottom, v); }
- void setClip(Length top, Length right, Length bottom, Length left);
- void setClip(LengthBox box) { SET_VAR(visual, clip, box); }
+ void setClipLeft(const Length& v) { SET_VAR(visual, clip.m_left, v); }
+ void setClipRight(const Length& v) { SET_VAR(visual, clip.m_right, v); }
+ void setClipTop(const Length& v) { SET_VAR(visual, clip.m_top, v); }
+ void setClipBottom(const Length& v) { SET_VAR(visual, clip.m_bottom, v); }
+ void setClip(const Length& top, const Length& right, const Length& bottom, const Length& left);
+ void setClip(const LengthBox& box) { SET_VAR(visual, clip, box); }
void setUnicodeBidi(EUnicodeBidi b) { noninherited_flags._unicodeBidi = b; }
@@ -1065,41 +1107,40 @@ public:
bool setFontDescription(const FontDescription&);
// Only used for blending font sizes when animating and for text autosizing.
void setFontSize(float);
+ void setFontWeight(FontWeight);
void setTextAutosizingMultiplier(float v)
{
- SET_VAR(visual, m_textAutosizingMultiplier, v);
+ SET_VAR(inherited, textAutosizingMultiplier, v);
setFontSize(fontDescription().specifiedSize());
}
void setColor(const Color&);
- void setTextIndent(Length v) { SET_VAR(rareInheritedData, indent, v); }
+ void setTextIndent(const Length& v) { SET_VAR(rareInheritedData, indent, v); }
void setTextIndentLine(TextIndentLine v) { SET_VAR(rareInheritedData, m_textIndentLine, v); }
+ void setTextIndentType(TextIndentType v) { SET_VAR(rareInheritedData, m_textIndentType, v); }
void setTextAlign(ETextAlign v) { inherited_flags._text_align = v; }
void setTextAlignLast(TextAlignLast v) { SET_VAR(rareInheritedData, m_textAlignLast, v); }
void setTextJustify(TextJustify v) { SET_VAR(rareInheritedData, m_textJustify, v); }
void setTextTransform(ETextTransform v) { inherited_flags._text_transform = v; }
- void addToTextDecorationsInEffect(TextDecoration v) { inherited_flags._text_decorations |= v; }
- void setTextDecorationsInEffect(TextDecoration v) { inherited_flags._text_decorations = v; }
+ void applyTextDecorations();
+ void clearAppliedTextDecorations();
void setTextDecoration(TextDecoration v) { SET_VAR(visual, textDecoration, v); }
void setTextUnderlinePosition(TextUnderlinePosition v) { SET_VAR(rareInheritedData, m_textUnderlinePosition, v); }
void setTextDecorationStyle(TextDecorationStyle v) { SET_VAR(rareNonInheritedData, m_textDecorationStyle, v); }
void setDirection(TextDirection v) { inherited_flags._direction = v; }
- void setLineHeight(Length specifiedLineHeight);
+ void setLineHeight(const Length& specifiedLineHeight);
bool setZoom(float);
- void setZoomWithoutReturnValue(float f) { setZoom(f); }
bool setEffectiveZoom(float);
void setImageRendering(EImageRendering v) { SET_VAR(rareInheritedData, m_imageRendering, v); }
void setWhiteSpace(EWhiteSpace v) { inherited_flags._white_space = v; }
+ // FIXME: Remove these two and replace them with respective FontBuilder calls.
void setWordSpacing(float);
void setLetterSpacing(float);
- void clearBackgroundLayers() { m_background.access()->m_background = FillLayer(BackgroundFillLayer); }
- void inheritBackgroundLayers(const FillLayer& parent) { m_background.access()->m_background = parent; }
-
void adjustBackgroundLayers()
{
if (backgroundLayers()->next()) {
@@ -1108,9 +1149,6 @@ public:
}
}
- void clearMaskLayers() { rareNonInheritedData.access()->m_mask = FillLayer(MaskFillLayer); }
- void inheritMaskLayers(const FillLayer& parent) { rareNonInheritedData.access()->m_mask = parent; }
-
void adjustMaskLayers()
{
if (maskLayers()->next()) {
@@ -1123,7 +1161,7 @@ public:
void setMaskBoxImage(const NinePieceImage& b) { SET_VAR(rareNonInheritedData, m_maskBoxImage, b); }
void setMaskBoxImageSource(PassRefPtr<StyleImage> v) { rareNonInheritedData.access()->m_maskBoxImage.setImage(v); }
- void setMaskBoxImageSlices(LengthBox slices)
+ void setMaskBoxImageSlices(const LengthBox& slices)
{
rareNonInheritedData.access()->m_maskBoxImage.setImageSlices(slices);
}
@@ -1139,9 +1177,9 @@ public:
{
rareNonInheritedData.access()->m_maskBoxImage.setOutset(outset);
}
- void setMaskXPosition(Length length) { SET_VAR(rareNonInheritedData, m_mask.m_xPosition, length); }
- void setMaskYPosition(Length length) { SET_VAR(rareNonInheritedData, m_mask.m_yPosition, length); }
- void setMaskSize(LengthSize s) { SET_VAR(rareNonInheritedData, m_mask.m_sizeLength, s); }
+ void setMaskXPosition(const Length& length) { SET_VAR(rareNonInheritedData, m_mask.m_xPosition, length); }
+ void setMaskYPosition(const Length& length) { SET_VAR(rareNonInheritedData, m_mask.m_yPosition, length); }
+ void setMaskSize(const LengthSize& s) { SET_VAR(rareNonInheritedData, m_mask.m_sizeLength, s); }
void setBorderCollapse(EBorderCollapse collapse) { inherited_flags._border_collapse = collapse; }
void setHorizontalBorderSpacing(short);
@@ -1157,20 +1195,19 @@ public:
void setListStyleImage(PassRefPtr<StyleImage>);
void setListStylePosition(EListStylePosition v) { inherited_flags._list_style_position = v; }
- void resetMargin() { SET_VAR(surround, margin, LengthBox(Fixed)); }
- void setMarginTop(Length v) { SET_VAR(surround, margin.m_top, v); }
- void setMarginBottom(Length v) { SET_VAR(surround, margin.m_bottom, v); }
- void setMarginLeft(Length v) { SET_VAR(surround, margin.m_left, v); }
- void setMarginRight(Length v) { SET_VAR(surround, margin.m_right, v); }
- void setMarginStart(Length);
- void setMarginEnd(Length);
+ void setMarginTop(const Length& v) { SET_VAR(surround, margin.m_top, v); }
+ void setMarginBottom(const Length& v) { SET_VAR(surround, margin.m_bottom, v); }
+ void setMarginLeft(const Length& v) { SET_VAR(surround, margin.m_left, v); }
+ void setMarginRight(const Length& v) { SET_VAR(surround, margin.m_right, v); }
+ void setMarginStart(const Length&);
+ void setMarginEnd(const Length&);
void resetPadding() { SET_VAR(surround, padding, LengthBox(Auto)); }
void setPaddingBox(const LengthBox& b) { SET_VAR(surround, padding, b); }
- void setPaddingTop(Length v) { SET_VAR(surround, padding.m_top, v); }
- void setPaddingBottom(Length v) { SET_VAR(surround, padding.m_bottom, v); }
- void setPaddingLeft(Length v) { SET_VAR(surround, padding.m_left, v); }
- void setPaddingRight(Length v) { SET_VAR(surround, padding.m_right, v); }
+ void setPaddingTop(const Length& v) { SET_VAR(surround, padding.m_top, v); }
+ void setPaddingBottom(const Length& v) { SET_VAR(surround, padding.m_bottom, v); }
+ void setPaddingLeft(const Length& v) { SET_VAR(surround, padding.m_left, v); }
+ void setPaddingRight(const Length& v) { SET_VAR(surround, padding.m_right, v); }
void setCursor(ECursor c) { inherited_flags._cursor_style = c; }
void addCursor(PassRefPtr<StyleImage>, const IntPoint& hotSpot = IntPoint());
@@ -1202,9 +1239,9 @@ public:
// CSS3 Setters
void setOutlineOffset(int v) { SET_VAR(m_background, m_outline.m_offset, v); }
void setTextShadow(PassRefPtr<ShadowList>);
- void setTextStrokeColor(const Color& c) { SET_VAR(rareInheritedData, textStrokeColor, c); }
+ void setTextStrokeColor(const StyleColor& c) { SET_VAR_WITH_SETTER(rareInheritedData, textStrokeColor, setTextStrokeColor, c); }
void setTextStrokeWidth(float w) { SET_VAR(rareInheritedData, textStrokeWidth, w); }
- void setTextFillColor(const Color& c) { SET_VAR(rareInheritedData, textFillColor, c); }
+ void setTextFillColor(const StyleColor& c) { SET_VAR_WITH_SETTER(rareInheritedData, textFillColor, setTextFillColor, c); }
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
@@ -1212,9 +1249,9 @@ public:
void setBoxDecorationBreak(EBoxDecorationBreak b) { SET_VAR(m_box, m_boxDecorationBreak, b); }
void setBoxDirection(EBoxDirection d) { inherited_flags._box_direction = d; }
void setBoxFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flex, f); }
- void setBoxFlexGroup(unsigned int fg) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flex_group, fg); }
+ void setBoxFlexGroup(unsigned fg) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flexGroup, fg); }
void setBoxLines(EBoxLines l) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, lines, l); }
- void setBoxOrdinalGroup(unsigned int og) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, ordinal_group, og); }
+ void setBoxOrdinalGroup(unsigned og) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, ordinalGroup, og); }
void setBoxOrient(EBoxOrient o) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, orient, o); }
void setBoxPack(EBoxPack p) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, pack, p); }
void setBoxShadow(PassRefPtr<ShadowList>);
@@ -1222,19 +1259,24 @@ public:
void setBoxSizing(EBoxSizing s) { SET_VAR(m_box, m_boxSizing, s); }
void setFlexGrow(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexGrow, f); }
void setFlexShrink(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexShrink, f); }
- void setFlexBasis(Length length) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexBasis, length); }
- void setOrder(int o) { SET_VAR(rareNonInheritedData, m_order, o); }
+ void setFlexBasis(const Length& length) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexBasis, length); }
+ // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set.
+ void setOrder(int o) { SET_VAR(rareNonInheritedData, m_order, max(std::numeric_limits<int>::min() + 2, o)); }
void addCallbackSelector(const String& selector);
void setAlignContent(EAlignContent p) { SET_VAR(rareNonInheritedData, m_alignContent, p); }
- void setAlignItems(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignItems, a); }
- void setAlignSelf(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignSelf, a); }
+ void setAlignItems(ItemPosition a) { SET_VAR(rareNonInheritedData, m_alignItems, a); }
+ void setAlignItemsOverflowAlignment(OverflowAlignment overflowAlignment) { SET_VAR(rareNonInheritedData, m_alignItemsOverflowAlignment, overflowAlignment); }
+ void setAlignSelf(ItemPosition a) { SET_VAR(rareNonInheritedData, m_alignSelf, a); }
+ void setAlignSelfOverflowAlignment(OverflowAlignment overflowAlignment) { SET_VAR(rareNonInheritedData, m_alignSelfOverflowAlignment, overflowAlignment); }
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 setJustifyContent(EJustifyContent p) { SET_VAR(rareNonInheritedData, m_justifyContent, p); }
+ void setJustifySelf(ItemPosition justifySelf) { SET_VAR(rareNonInheritedData, m_justifySelf, justifySelf); }
+ void setJustifySelfOverflowAlignment(OverflowAlignment overflowAlignment) { SET_VAR(rareNonInheritedData, m_justifySelfOverflowAlignment, overflowAlignment); }
void setGridAutoColumns(const GridTrackSize& length) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridAutoColumns, length); }
void setGridAutoRows(const GridTrackSize& length) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridAutoRows, length); }
- void setGridDefinitionColumns(const Vector<GridTrackSize>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridDefinitionColumns, lengths); }
- void setGridDefinitionRows(const Vector<GridTrackSize>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridDefinitionRows, lengths); }
+ void setGridTemplateColumns(const Vector<GridTrackSize>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridTemplateColumns, lengths); }
+ void setGridTemplateRows(const Vector<GridTrackSize>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridTemplateRows, lengths); }
void setNamedGridColumnLines(const NamedGridLinesMap& namedGridColumnLines) { SET_VAR(rareNonInheritedData.access()->m_grid, m_namedGridColumnLines, namedGridColumnLines); }
void setNamedGridRowLines(const NamedGridLinesMap& namedGridRowLines) { SET_VAR(rareNonInheritedData.access()->m_grid, m_namedGridRowLines, namedGridRowLines); }
void setOrderedNamedGridColumnLines(const OrderedNamedGridLines& orderedNamedGridColumnLines) { SET_VAR(rareNonInheritedData.access()->m_grid, m_orderedNamedGridColumnLines, orderedNamedGridColumnLines); }
@@ -1249,7 +1291,7 @@ public:
void setGridRowStart(const GridPosition& rowStartPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridRowStart, rowStartPosition); }
void setGridRowEnd(const GridPosition& rowEndPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridRowEnd, rowEndPosition); }
- void setMarqueeIncrement(Length f) { SET_VAR(rareNonInheritedData.access()->m_marquee, increment, f); }
+ void setMarqueeIncrement(const Length& f) { SET_VAR(rareNonInheritedData.access()->m_marquee, increment, f); }
void setMarqueeSpeed(int f) { SET_VAR(rareNonInheritedData.access()->m_marquee, speed, f); }
void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(rareNonInheritedData.access()->m_marquee, direction, d); }
void setMarqueeBehavior(EMarqueeBehavior b) { SET_VAR(rareNonInheritedData.access()->m_marquee, behavior, b); }
@@ -1269,8 +1311,6 @@ public:
void setLocale(const AtomicString& locale) { SET_VAR(rareInheritedData, locale, locale); }
void setBorderFit(EBorderFit b) { SET_VAR(rareNonInheritedData, m_borderFit, b); }
void setResize(EResize r) { SET_VAR(rareInheritedData, resize, r); }
- void setColumnAxis(ColumnAxis axis) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_axis, axis); }
- void setColumnProgression(ColumnProgression progression) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_progression, progression); }
void setColumnWidth(float f) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoWidth, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_width, f); }
void setHasAutoColumnWidth() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoWidth, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_width, 0); }
void setColumnCount(unsigned short c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoCount, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_count, c); }
@@ -1278,7 +1318,7 @@ public:
void setColumnFill(ColumnFill columnFill) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_fill, columnFill); }
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_BORDERVALUE_COLOR(rareNonInheritedData.access()->m_multiCol, m_rule, c); }
+ void setColumnRuleColor(const StyleColor& 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()); }
@@ -1287,18 +1327,15 @@ public:
// For valid values of column-break-inside see http://www.w3.org/TR/css3-multicol/#break-before-break-after-break-inside
void setColumnBreakInside(EPageBreak p) { ASSERT(p == PBAUTO || p == PBAVOID); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakInside, p); }
void setColumnBreakAfter(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakAfter, p); }
- void setRegionBreakBefore(EPageBreak p) { SET_VAR(rareNonInheritedData, m_regionBreakBefore, p); }
- void setRegionBreakInside(EPageBreak p) { ASSERT(p == PBAUTO || p == PBAVOID); SET_VAR(rareNonInheritedData, m_regionBreakInside, p); }
- void setRegionBreakAfter(EPageBreak p) { SET_VAR(rareNonInheritedData, m_regionBreakAfter, p); }
void inheritColumnPropertiesFrom(RenderStyle* parent) { rareNonInheritedData.access()->m_multiCol = parent->rareNonInheritedData->m_multiCol; }
void setTransform(const TransformOperations& ops) { SET_VAR(rareNonInheritedData.access()->m_transform, m_operations, ops); }
- void setTransformOriginX(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_x, l); }
- void setTransformOriginY(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_y, l); }
+ void setTransformOriginX(const Length& l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_x, l); }
+ void setTransformOriginY(const Length& l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_y, l); }
void setTransformOriginZ(float f) { SET_VAR(rareNonInheritedData.access()->m_transform, m_z, f); }
void setSpeak(ESpeak s) { SET_VAR(rareInheritedData, speak, s); }
void setTextCombine(TextCombine v) { SET_VAR(rareNonInheritedData, m_textCombine, v); }
- void setTextDecorationColor(const Color& c) { SET_VAR(rareNonInheritedData, m_textDecorationColor, c); }
- void setTextEmphasisColor(const Color& c) { SET_VAR(rareInheritedData, textEmphasisColor, c); }
+ void setTextDecorationColor(const StyleColor& c) { SET_VAR(rareNonInheritedData, m_textDecorationColor, c); }
+ void setTextEmphasisColor(const StyleColor& c) { SET_VAR_WITH_SETTER(rareInheritedData, textEmphasisColor, setTextEmphasisColor, c); }
void setTextEmphasisFill(TextEmphasisFill fill) { SET_VAR(rareInheritedData, textEmphasisFill, fill); }
void setTextEmphasisMark(TextEmphasisMark mark) { SET_VAR(rareInheritedData, textEmphasisMark, mark); }
void setTextEmphasisCustomMark(const AtomicString& mark) { SET_VAR(rareInheritedData, textEmphasisCustomMark, mark); }
@@ -1316,14 +1353,6 @@ public:
// End CSS3 Setters
- void setLineGrid(const AtomicString& lineGrid) { SET_VAR(rareInheritedData, m_lineGrid, lineGrid); }
- void setLineSnap(LineSnap lineSnap) { SET_VAR(rareInheritedData, m_lineSnap, lineSnap); }
- void setLineAlign(LineAlign lineAlign) { SET_VAR(rareInheritedData, m_lineAlign, lineAlign); }
-
- void setFlowThread(const AtomicString& flowThread) { SET_VAR(rareNonInheritedData, m_flowThread, flowThread); }
- void setRegionThread(const AtomicString& regionThread) { SET_VAR(rareNonInheritedData, m_regionThread, regionThread); }
- void setRegionFragment(RegionFragment regionFragment) { SET_VAR(rareNonInheritedData, m_regionFragment, regionFragment); }
-
void setWrapFlow(WrapFlow wrapFlow) { SET_VAR(rareNonInheritedData, m_wrapFlow, wrapFlow); }
void setWrapThrough(WrapThrough wrapThrough) { SET_VAR(rareNonInheritedData, m_wrapThrough, wrapThrough); }
@@ -1340,19 +1369,22 @@ public:
rareNonInheritedData.access()->m_transitions.clear();
}
- void adjustAnimations();
- void adjustTransitions();
-
void setTransformStyle3D(ETransformStyle3D b) { SET_VAR(rareNonInheritedData, m_transformStyle3D, b); }
void setBackfaceVisibility(EBackfaceVisibility b) { SET_VAR(rareNonInheritedData, m_backfaceVisibility, b); }
void setPerspective(float p) { SET_VAR(rareNonInheritedData, m_perspective, p); }
- void setPerspectiveOriginX(Length l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginX, l); }
- void setPerspectiveOriginY(Length l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginY, l); }
- void setPageSize(LengthSize s) { SET_VAR(rareNonInheritedData, m_pageSize, s); }
+ void setPerspectiveOriginX(const Length& l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginX, l); }
+ void setPerspectiveOriginY(const Length& l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginY, l); }
+ void setPageSize(const LengthSize& s) { SET_VAR(rareNonInheritedData, m_pageSize, s); }
void setPageSizeType(PageSizeType t) { SET_VAR(rareNonInheritedData, m_pageSizeType, t); }
void resetPageSizeType() { SET_VAR(rareNonInheritedData, m_pageSizeType, PAGE_SIZE_AUTO); }
- void setIsRunningAcceleratedAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_runningAcceleratedAnimation, b); }
+ void setHasCurrentOpacityAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_hasCurrentOpacityAnimation, b); }
+ void setHasCurrentTransformAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_hasCurrentTransformAnimation, b); }
+ void setHasCurrentFilterAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_hasCurrentFilterAnimation, b); }
+
+ void setIsRunningOpacityAnimationOnCompositor(bool b = true) { SET_VAR(rareNonInheritedData, m_runningOpacityAnimationOnCompositor, b); }
+ void setIsRunningTransformAnimationOnCompositor(bool b = true) { SET_VAR(rareNonInheritedData, m_runningTransformAnimationOnCompositor, b); }
+ void setIsRunningFilterAnimationOnCompositor(bool b = true) { SET_VAR(rareNonInheritedData, m_runningFilterAnimationOnCompositor, b); }
void setLineBoxContain(LineBoxContain c) { SET_VAR(rareInheritedData, m_lineBoxContain, c); }
void setLineClamp(LineClampValue c) { SET_VAR(rareNonInheritedData, lineClamp, c); }
@@ -1361,6 +1393,16 @@ public:
void setTouchAction(TouchAction t) { SET_VAR(rareNonInheritedData, m_touchAction, t); }
void setTouchActionDelay(TouchActionDelay t) { SET_VAR(rareInheritedData, m_touchActionDelay, t); }
+ void setScrollBehavior(ScrollBehavior b) { SET_VAR(rareNonInheritedData, m_scrollBehavior, b); }
+
+ void setWillChangeProperties(const Vector<CSSPropertyID>& properties) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_properties, properties); }
+ void setWillChangeContents(bool b) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_contents, b); }
+ void setWillChangeScrollPosition(bool b) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_scrollPosition, b); }
+ void setSubtreeWillChangeContents(bool b) { SET_VAR(rareInheritedData, m_subtreeWillChangeContents, b); }
+
+ bool requiresAcceleratedCompositingForExternalReasons(bool b) { return rareNonInheritedData->m_requiresAcceleratedCompositingForExternalReasons; }
+ void setRequiresAcceleratedCompositingForExternalReasons(bool b) { SET_VAR(rareNonInheritedData, m_requiresAcceleratedCompositingForExternalReasons, b); }
+
const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); }
SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); }
@@ -1375,12 +1417,12 @@ public:
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); }
- SVGLength strokeWidth() const { return svgStyle()->strokeWidth(); }
- void setStrokeWidth(SVGLength w) { accessSVGStyle()->setStrokeWidth(w); }
- Vector<SVGLength> strokeDashArray() const { return svgStyle()->strokeDashArray(); }
- void setStrokeDashArray(Vector<SVGLength> array) { accessSVGStyle()->setStrokeDashArray(array); }
- SVGLength strokeDashOffset() const { return svgStyle()->strokeDashOffset(); }
- void setStrokeDashOffset(SVGLength d) { accessSVGStyle()->setStrokeDashOffset(d); }
+ SVGLength* strokeWidth() const { return svgStyle()->strokeWidth(); }
+ void setStrokeWidth(PassRefPtr<SVGLength> w) { accessSVGStyle()->setStrokeWidth(w); }
+ SVGLengthList* strokeDashArray() const { return svgStyle()->strokeDashArray(); }
+ void setStrokeDashArray(PassRefPtr<SVGLengthList> array) { accessSVGStyle()->setStrokeDashArray(array); }
+ SVGLength* strokeDashOffset() const { return svgStyle()->strokeDashOffset(); }
+ void setStrokeDashOffset(PassRefPtr<SVGLength> d) { accessSVGStyle()->setStrokeDashOffset(d); }
float strokeMiterLimit() const { return svgStyle()->strokeMiterLimit(); }
void setStrokeMiterLimit(float f) { accessSVGStyle()->setStrokeMiterLimit(f); }
@@ -1394,25 +1436,8 @@ public:
void setFloodColor(const Color& c) { accessSVGStyle()->setFloodColor(c); }
void setLightingColor(const Color& c) { accessSVGStyle()->setLightingColor(c); }
- SVGLength baselineShiftValue() const { return svgStyle()->baselineShiftValue(); }
- void setBaselineShiftValue(SVGLength s) { accessSVGStyle()->setBaselineShiftValue(s); }
- SVGLength kerning() const { return svgStyle()->kerning(); }
- void setKerning(SVGLength k) { accessSVGStyle()->setKerning(k); }
-
- void setShapeInside(PassRefPtr<ShapeValue> value)
- {
- if (rareNonInheritedData->m_shapeInside == value)
- return;
- rareNonInheritedData.access()->m_shapeInside = value;
- }
- ShapeValue* shapeInside() const { return rareNonInheritedData->m_shapeInside.get(); }
- ShapeValue* resolvedShapeInside() const
- {
- ShapeValue* shapeInside = this->shapeInside();
- if (shapeInside && shapeInside->type() == ShapeValue::Outside)
- return shapeOutside();
- return shapeInside;
- }
+ SVGLength* baselineShiftValue() const { return svgStyle()->baselineShiftValue(); }
+ void setBaselineShiftValue(PassRefPtr<SVGLength> s) { accessSVGStyle()->setBaselineShiftValue(s); }
void setShapeOutside(PassRefPtr<ShapeValue> value)
{
@@ -1422,7 +1447,6 @@ public:
}
ShapeValue* shapeOutside() const { return rareNonInheritedData->m_shapeOutside.get(); }
- static ShapeValue* initialShapeInside() { return 0; }
static ShapeValue* initialShapeOutside() { return 0; }
void setClipPath(PassRefPtr<ClipPathOperation> operation)
@@ -1434,12 +1458,8 @@ public:
static ClipPathOperation* initialClipPath() { return 0; }
- Length shapePadding() const { return rareNonInheritedData->m_shapePadding; }
- void setShapePadding(Length shapePadding) { SET_VAR(rareNonInheritedData, m_shapePadding, shapePadding); }
- static Length initialShapePadding() { return Length(0, Fixed); }
-
- Length shapeMargin() const { return rareNonInheritedData->m_shapeMargin; }
- void setShapeMargin(Length shapeMargin) { SET_VAR(rareNonInheritedData, m_shapeMargin, shapeMargin); }
+ const Length& shapeMargin() const { return rareNonInheritedData->m_shapeMargin; }
+ void setShapeMargin(const Length& shapeMargin) { SET_VAR(rareNonInheritedData, m_shapeMargin, shapeMargin); }
static Length initialShapeMargin() { return Length(0, Fixed); }
float shapeImageThreshold() const { return rareNonInheritedData->m_shapeImageThreshold; }
@@ -1471,17 +1491,9 @@ public:
bool inheritedNotEqual(const RenderStyle*) const;
bool inheritedDataShared(const RenderStyle*) const;
- 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 isDisplayRegionType() const
- {
- return display() == BLOCK || display() == INLINE_BLOCK
- || display() == TABLE_CELL || display() == TABLE_CAPTION
- || display() == LIST_ITEM;
- }
bool setWritingMode(WritingMode v)
{
@@ -1505,6 +1517,8 @@ public:
bool lastChildState() const { return noninherited_flags.lastChildState; }
void setLastChildState() { setUnique(); noninherited_flags.lastChildState = true; }
+ StyleColor visitedDependentDecorationStyleColor() const;
+ Color visitedDependentDecorationColor() const;
Color visitedDependentColor(int colorProperty) const;
void setHasExplicitlyInheritedProperties() { noninherited_flags.explicitInheritance = true; }
@@ -1521,8 +1535,6 @@ public:
static LengthSize initialBorderRadius() { return LengthSize(Length(0, Fixed), Length(0, Fixed)); }
static ECaptionSide initialCaptionSide() { return CAPTOP; }
static EClear initialClear() { return CNONE; }
- static ColumnAxis initialColumnAxis() { return AutoColumnAxis; }
- static ColumnProgression initialColumnProgression() { return NormalColumnProgression; }
static TextDirection initialDirection() { return LTR; }
static WritingMode initialWritingMode() { return TopToBottomWritingMode; }
static TextCombine initialTextCombine() { return TextCombineNone; }
@@ -1560,6 +1572,7 @@ public:
static Length initialPadding() { return Length(Fixed); }
static Length initialTextIndent() { return Length(Fixed); }
static TextIndentLine initialTextIndentLine() { return TextIndentFirstLine; }
+ static TextIndentType initialTextIndentType() { return TextIndentNormal; }
static EVerticalAlign initialVerticalAlign() { return BASELINE; }
static short initialWidows() { return 2; }
static short initialOrphans() { return 2; }
@@ -1580,8 +1593,8 @@ public:
static EBoxOrient initialBoxOrient() { return HORIZONTAL; }
static EBoxPack initialBoxPack() { return Start; }
static float initialBoxFlex() { return 0.0f; }
- static unsigned int initialBoxFlexGroup() { return 1; }
- static unsigned int initialBoxOrdinalGroup() { return 1; }
+ static unsigned initialBoxFlexGroup() { return 1; }
+ static unsigned initialBoxOrdinalGroup() { return 1; }
static EBoxSizing initialBoxSizing() { return CONTENT_BOX; }
static StyleReflection* initialBoxReflect() { return 0; }
static float initialFlexGrow() { return 0; }
@@ -1589,11 +1602,15 @@ public:
static Length initialFlexBasis() { return Length(Auto); }
static int initialOrder() { return 0; }
static EAlignContent initialAlignContent() { return AlignContentStretch; }
- static EAlignItems initialAlignItems() { return AlignStretch; }
- static EAlignItems initialAlignSelf() { return AlignAuto; }
+ static ItemPosition initialAlignItems() { return ItemPositionStretch; }
+ static OverflowAlignment initialAlignItemsOverflowAlignment() { return OverflowAlignmentDefault; }
+ static ItemPosition initialAlignSelf() { return ItemPositionAuto; }
+ static OverflowAlignment initialAlignSelfOverflowAlignment() { return OverflowAlignmentDefault; }
static EFlexDirection initialFlexDirection() { return FlowRow; }
static EFlexWrap initialFlexWrap() { return FlexNoWrap; }
static EJustifyContent initialJustifyContent() { return JustifyFlexStart; }
+ static ItemPosition initialJustifySelf() { return ItemPositionAuto; }
+ static OverflowAlignment initialJustifySelfOverflowAlignment() { return OverflowAlignmentDefault; }
static int initialMarqueeLoopCount() { return -1; }
static int initialMarqueeSpeed() { return 85; }
static Length initialMarqueeIncrement() { return Length(6, Fixed); }
@@ -1653,15 +1670,16 @@ public:
static TouchActionDelay initialTouchActionDelay() { return TouchActionDelayScript; }
static ShadowList* initialBoxShadow() { return 0; }
static ShadowList* initialTextShadow() { return 0; }
+ static ScrollBehavior initialScrollBehavior() { return ScrollBehaviorInstant; }
// The initial value is 'none' for grid tracks.
- static Vector<GridTrackSize> initialGridDefinitionColumns() { return Vector<GridTrackSize>(); }
- static Vector<GridTrackSize> initialGridDefinitionRows() { return Vector<GridTrackSize>(); }
+ static Vector<GridTrackSize> initialGridTemplateColumns() { return Vector<GridTrackSize>(); }
+ static Vector<GridTrackSize> initialGridTemplateRows() { return Vector<GridTrackSize>(); }
static GridAutoFlow initialGridAutoFlow() { return AutoFlowNone; }
- static GridTrackSize initialGridAutoColumns() { return GridTrackSize(Auto); }
- static GridTrackSize initialGridAutoRows() { return GridTrackSize(Auto); }
+ static GridTrackSize initialGridAutoColumns() { return GridTrackSize(Length(Auto)); }
+ static GridTrackSize initialGridAutoRows() { return GridTrackSize(Length(Auto)); }
static NamedGridLinesMap initialNamedGridColumnLines() { return NamedGridLinesMap(); }
static NamedGridLinesMap initialNamedGridRowLines() { return NamedGridLinesMap(); }
@@ -1680,14 +1698,6 @@ public:
static unsigned initialTabSize() { return 8; }
- static const AtomicString& initialLineGrid() { return nullAtom; }
- static LineSnap initialLineSnap() { return LineSnapNone; }
- static LineAlign initialLineAlign() { return LineAlignNone; }
-
- static const AtomicString& initialFlowThread() { return nullAtom; }
- static const AtomicString& initialRegionThread() { return nullAtom; }
- static RegionFragment initialRegionFragment() { return AutoRegionFragment; }
-
static WrapFlow initialWrapFlow() { return WrapFlowAuto; }
static WrapThrough initialWrapThrough() { return WrapThroughWrap; }
@@ -1703,17 +1713,17 @@ public:
static EIsolation initialIsolation() { return IsolationAuto; }
private:
void setVisitedLinkColor(const Color&);
- void setVisitedLinkBackgroundColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBackgroundColor, v); }
- void setVisitedLinkBorderLeftColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderLeftColor, v); }
- void setVisitedLinkBorderRightColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderRightColor, v); }
- void setVisitedLinkBorderBottomColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderBottomColor, v); }
- void setVisitedLinkBorderTopColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderTopColor, v); }
- void setVisitedLinkOutlineColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkOutlineColor, v); }
- void setVisitedLinkColumnRuleColor(const Color& v) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_visitedLinkColumnRuleColor, v); }
- void setVisitedLinkTextDecorationColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkTextDecorationColor, v); }
- void setVisitedLinkTextEmphasisColor(const Color& v) { SET_VAR(rareInheritedData, visitedLinkTextEmphasisColor, v); }
- void setVisitedLinkTextFillColor(const Color& v) { SET_VAR(rareInheritedData, visitedLinkTextFillColor, v); }
- void setVisitedLinkTextStrokeColor(const Color& v) { SET_VAR(rareInheritedData, visitedLinkTextStrokeColor, v); }
+ void setVisitedLinkBackgroundColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBackgroundColor, v); }
+ void setVisitedLinkBorderLeftColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderLeftColor, v); }
+ void setVisitedLinkBorderRightColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderRightColor, v); }
+ void setVisitedLinkBorderBottomColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderBottomColor, v); }
+ void setVisitedLinkBorderTopColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderTopColor, v); }
+ void setVisitedLinkOutlineColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkOutlineColor, v); }
+ void setVisitedLinkColumnRuleColor(const StyleColor& v) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_visitedLinkColumnRuleColor, v); }
+ void setVisitedLinkTextDecorationColor(const StyleColor& v) { SET_VAR(rareNonInheritedData, m_visitedLinkTextDecorationColor, v); }
+ void setVisitedLinkTextEmphasisColor(const StyleColor& v) { SET_VAR_WITH_SETTER(rareInheritedData, visitedLinkTextEmphasisColor, setVisitedLinkTextEmphasisColor, v); }
+ void setVisitedLinkTextFillColor(const StyleColor& v) { SET_VAR_WITH_SETTER(rareInheritedData, visitedLinkTextFillColor, setVisitedLinkTextFillColor, v); }
+ void setVisitedLinkTextStrokeColor(const StyleColor& v) { SET_VAR_WITH_SETTER(rareInheritedData, visitedLinkTextStrokeColor, setVisitedLinkTextStrokeColor, v); }
void inheritUnicodeBidiFrom(const RenderStyle* parent) { noninherited_flags._unicodeBidi = parent->noninherited_flags._unicodeBidi; }
void getShadowExtent(const ShadowList*, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const;
@@ -1741,31 +1751,30 @@ private:
}
// Color accessors are all private to make sure callers use visitedDependentColor instead to access them.
- Color invalidColor() const { static Color invalid; return invalid; }
- Color borderLeftColor() const { return surround->border.left().color(); }
- 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(); }
+ StyleColor borderLeftColor() const { return surround->border.left().color(); }
+ StyleColor borderRightColor() const { return surround->border.right().color(); }
+ StyleColor borderTopColor() const { return surround->border.top().color(); }
+ StyleColor borderBottomColor() const { return surround->border.bottom().color(); }
+ StyleColor backgroundColor() const { return m_background->color(); }
Color color() const;
- 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; }
+ StyleColor columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); }
+ StyleColor outlineColor() const { return m_background->outline().color(); }
+ StyleColor textEmphasisColor() const { return rareInheritedData->textEmphasisColor(); }
+ StyleColor textFillColor() const { return rareInheritedData->textFillColor(); }
+ StyleColor textStrokeColor() const { return rareInheritedData->textStrokeColor(); }
Color visitedLinkColor() const;
- 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 textDecorationColor() const { return rareNonInheritedData->m_textDecorationColor; }
- Color visitedLinkTextDecorationColor() const { return rareNonInheritedData->m_visitedLinkTextDecorationColor; }
- Color visitedLinkTextEmphasisColor() const { return rareInheritedData->visitedLinkTextEmphasisColor; }
- Color visitedLinkTextFillColor() const { return rareInheritedData->visitedLinkTextFillColor; }
- Color visitedLinkTextStrokeColor() const { return rareInheritedData->visitedLinkTextStrokeColor; }
+ StyleColor visitedLinkBackgroundColor() const { return rareNonInheritedData->m_visitedLinkBackgroundColor; }
+ StyleColor visitedLinkBorderLeftColor() const { return rareNonInheritedData->m_visitedLinkBorderLeftColor; }
+ StyleColor visitedLinkBorderRightColor() const { return rareNonInheritedData->m_visitedLinkBorderRightColor; }
+ StyleColor visitedLinkBorderBottomColor() const { return rareNonInheritedData->m_visitedLinkBorderBottomColor; }
+ StyleColor visitedLinkBorderTopColor() const { return rareNonInheritedData->m_visitedLinkBorderTopColor; }
+ StyleColor visitedLinkOutlineColor() const { return rareNonInheritedData->m_visitedLinkOutlineColor; }
+ StyleColor visitedLinkColumnRuleColor() const { return rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor; }
+ StyleColor textDecorationColor() const { return rareNonInheritedData->m_textDecorationColor; }
+ StyleColor visitedLinkTextDecorationColor() const { return rareNonInheritedData->m_visitedLinkTextDecorationColor; }
+ StyleColor visitedLinkTextEmphasisColor() const { return rareInheritedData->visitedLinkTextEmphasisColor(); }
+ StyleColor visitedLinkTextFillColor() const { return rareInheritedData->visitedLinkTextFillColor(); }
+ StyleColor visitedLinkTextStrokeColor() const { return rareInheritedData->visitedLinkTextStrokeColor(); }
Color colorIncludingFallback(int colorProperty, bool visitedLink) const;
@@ -1774,22 +1783,32 @@ private:
Color lightingColor() const { return svgStyle()->lightingColor(); }
void appendContent(PassOwnPtr<ContentData>);
- StyleDifference repaintOnlyDiff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const;
+ void addAppliedTextDecoration(const AppliedTextDecoration&);
+
+ bool diffNeedsFullLayoutAndRepaint(const RenderStyle& other) const;
+ bool diffNeedsFullLayout(const RenderStyle& other) const;
+ bool diffNeedsRepaintLayer(const RenderStyle& other) const;
+ bool diffNeedsRepaintObject(const RenderStyle& other) const;
+ bool diffNeedsRecompositeLayer(const RenderStyle& other) const;
+ unsigned computeChangedContextSensitiveProperties(const RenderStyle& other, StyleDifference) const;
};
+// FIXME: Reduce/remove the dependency on zoom adjusted int values.
+// The float or LayoutUnit versions of layout values should be used.
inline int adjustForAbsoluteZoom(int value, float zoomFactor)
{
if (zoomFactor == 1)
return value;
// Needed because computeLengthInt truncates (rather than rounds) when scaling up.
+ float fvalue = value;
if (zoomFactor > 1) {
if (value < 0)
- value--;
+ fvalue -= 0.5f;
else
- value++;
+ fvalue += 0.5f;
}
- return roundForImpreciseConversion<int>(value / zoomFactor);
+ return roundForImpreciseConversion<int>(fvalue / zoomFactor);
}
inline int adjustForAbsoluteZoom(int value, const RenderStyle* style)
@@ -1802,6 +1821,11 @@ inline float adjustFloatForAbsoluteZoom(float value, const RenderStyle& style)
return value / style.effectiveZoom();
}
+inline double adjustDoubleForAbsoluteZoom(double value, const RenderStyle& style)
+{
+ return value / style.effectiveZoom();
+}
+
inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, const RenderStyle& style)
{
return value / style.effectiveZoom();
@@ -1830,8 +1854,6 @@ inline bool RenderStyle::isSharable() const
return false;
if (hasUniquePseudoStyle())
return false;
- if (transitions() || animations())
- return false;
return true;
}
@@ -1863,6 +1885,13 @@ inline void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
noninherited_flags._pseudoBits |= 1 << (pseudo - 1);
}
+inline bool RenderStyle::hasPseudoElementStyle() const
+{
+ return noninherited_flags._pseudoBits & PSEUDO_ELEMENT_MASK;
+}
+
+float calcBorderRadiiConstraintScaleFor(const FloatRect&, const FloatRoundedRect::Radii&);
+
} // namespace WebCore
#endif // RenderStyle_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyleConstants.h b/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyleConstants.h
index 45531d20231..f2a3d006af0 100755..100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyleConstants.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/RenderStyleConstants.h
@@ -31,9 +31,11 @@ namespace WebCore {
enum StyleRecalcChange {
NoChange,
NoInherit,
+ UpdatePseudoElements,
Inherit,
Force,
Reattach,
+ ReattachNoRenderer
};
static const size_t PrintColorAdjustBits = 1;
@@ -42,37 +44,18 @@ enum PrintColorAdjust {
PrintColorAdjustExact
};
-// The difference between two styles. The following values are used:
-// (1) StyleDifferenceEqual - The two styles are identical.
-// (2) StyleDifferenceRecompositeLayer - The layer needs its position and transform updated, but no repaint.
-// (3) StyleDifferenceRepaint - The object just needs to be repainted.
-// (4) StyleDifferenceRepaintIfTextOrColorChange - The object needs to be repainted if it contains text or properties dependent on color (e.g., border or outline).
-// (5) StyleDifferenceRepaintLayer - The layer and its descendant layers needs to be repainted.
-// (6) StyleDifferenceLayoutPositionedMovementOnly - Only the position of this positioned object has been updated.
-// (7) StyleDifferenceSimplifiedLayout - Only overflow needs to be recomputed.
-// (8) StyleDifferenceSimplifiedLayoutAndPositionedMovement - Both positioned movement and simplified layout updates are required.
-// (9) StyleDifferenceLayout - A full layout is required.
-enum StyleDifference {
- StyleDifferenceEqual,
- StyleDifferenceRecompositeLayer,
- StyleDifferenceRepaint,
- StyleDifferenceRepaintIfTextOrColorChange,
- StyleDifferenceRepaintLayer,
- StyleDifferenceLayoutPositionedMovementOnly,
- StyleDifferenceSimplifiedLayout,
- StyleDifferenceSimplifiedLayoutAndPositionedMovement,
- StyleDifferenceLayout
-};
-
// When some style properties change, different amounts of work have to be done depending on
// context (e.g. whether the property is changing on an element which has a compositing layer).
// A simple StyleDifference does not provide enough information so we return a bit mask of
-// StyleDifferenceContextSensitiveProperties from RenderStyle::diff() too.
+// StyleDifferenceContextSensitiveProperties from RenderStyle::visualInvalidationDiff() too.
enum StyleDifferenceContextSensitiveProperty {
ContextSensitivePropertyNone = 0,
ContextSensitivePropertyTransform = (1 << 0),
ContextSensitivePropertyOpacity = (1 << 1),
- ContextSensitivePropertyFilter = (1 << 2)
+ ContextSensitivePropertyZIndex = (1 << 2),
+ ContextSensitivePropertyFilter = (1 << 3),
+ // The object needs to be repainted if it contains text or properties dependent on color (e.g., border or outline).
+ ContextSensitivePropertyTextOrColor = (1 << 4)
};
// Static pseudo styles. Dynamic ones are produced on the fly.
@@ -81,13 +64,13 @@ enum PseudoId {
// If you add or remove a public ID, you must update _pseudoBits in RenderStyle.
NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, BACKDROP, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR,
// Internal IDs follow:
- SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
- INPUT_LIST_BUTTON,
+ SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, INPUT_LIST_BUTTON,
+ // Special values follow:
AFTER_LAST_INTERNAL_PSEUDOID,
- FULL_SCREEN, FULL_SCREEN_DOCUMENT, FULL_SCREEN_ANCESTOR,
FIRST_PUBLIC_PSEUDOID = FIRST_LINE,
FIRST_INTERNAL_PSEUDOID = SCROLLBAR_THUMB,
- PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1)
+ PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1),
+ PSEUDO_ELEMENT_MASK = (1 << (BEFORE - 1)) | (1 << (AFTER - 1)) | (1 << (BACKDROP - 1))
};
enum ColumnFill { ColumnFillBalance, ColumnFillAuto };
@@ -191,7 +174,6 @@ enum EBoxDirection { BNORMAL, BREVERSE };
// CSS3 Flexbox Properties
enum EAlignContent { AlignContentFlexStart, AlignContentFlexEnd, AlignContentCenter, AlignContentSpaceBetween, AlignContentSpaceAround, AlignContentStretch };
-enum EAlignItems { AlignAuto, AlignFlexStart, AlignFlexEnd, AlignCenter, AlignStretch, AlignBaseline };
enum EFlexDirection { FlowRow, FlowRowReverse, FlowColumn, FlowColumnReverse };
enum EFlexWrap { FlexNoWrap, FlexWrap, FlexWrapReverse };
enum EJustifyContent { JustifyFlexStart, JustifyFlexEnd, JustifyCenter, JustifySpaceBetween, JustifySpaceAround };
@@ -330,11 +312,9 @@ enum QuoteType {
enum EBorderFit { BorderFitBorder, BorderFitLines };
-enum EAnimationFillMode { AnimationFillModeNone, AnimationFillModeForwards, AnimationFillModeBackwards, AnimationFillModeBoth };
-
enum EAnimPlayState {
- AnimPlayStatePlaying = 0x0,
- AnimPlayStatePaused = 0x1
+ AnimPlayStatePlaying,
+ AnimPlayStatePaused
};
enum EWhiteSpace {
@@ -413,8 +393,8 @@ enum ECursor {
CURSOR_PROGRESS,
CURSOR_NO_DROP,
CURSOR_NOT_ALLOWED,
- CURSOR_WEBKIT_ZOOM_IN,
- CURSOR_WEBKIT_ZOOM_OUT,
+ CURSOR_ZOOM_IN,
+ CURSOR_ZOOM_OUT,
CURSOR_E_RESIZE,
CURSOR_NE_RESIZE,
CURSOR_NW_RESIZE,
@@ -450,7 +430,9 @@ enum EDisplay {
TABLE_CAPTION, BOX, INLINE_BOX,
FLEX, INLINE_FLEX,
GRID, INLINE_GRID,
- NONE
+ NONE,
+ FIRST_TABLE_DISPLAY = TABLE,
+ LAST_TABLE_DISPLAY = TABLE_CAPTION
};
enum EInsideLink {
@@ -495,16 +477,6 @@ enum ImageResolutionSnap { ImageResolutionNoSnap = 0, ImageResolutionSnapPixels
enum Order { LogicalOrder = 0, VisualOrder };
-enum RegionFragment { AutoRegionFragment, BreakRegionFragment };
-
-enum ColumnAxis { HorizontalColumnAxis, VerticalColumnAxis, AutoColumnAxis };
-
-enum ColumnProgression { NormalColumnProgression, ReverseColumnProgression };
-
-enum LineSnap { LineSnapNone, LineSnapBaseline, LineSnapContain };
-
-enum LineAlign { LineAlignNone, LineAlignEdges };
-
enum WrapFlow { WrapFlowAuto, WrapFlowBoth, WrapFlowStart, WrapFlowEnd, WrapFlowMaximum, WrapFlowClear };
enum WrapThrough { WrapThroughWrap, WrapThroughNone };
@@ -515,12 +487,13 @@ enum GridAutoFlow { AutoFlowNone, AutoFlowColumn, AutoFlowRow };
enum DraggableRegionMode { DraggableRegionNone, DraggableRegionDrag, DraggableRegionNoDrag };
-static const size_t TouchActionBits = 3;
+static const size_t TouchActionBits = 4;
enum TouchAction {
TouchActionAuto = 0x0,
TouchActionNone = 0x1,
TouchActionPanX = 0x2,
- TouchActionPanY = 0x4
+ TouchActionPanY = 0x4,
+ TouchActionPinchZoom = 0x8,
};
inline TouchAction operator| (TouchAction a, TouchAction b) { return TouchAction(int(a) | int(b)); }
inline TouchAction& operator|= (TouchAction& a, TouchAction b) { return a = a | b; }
@@ -531,12 +504,34 @@ enum EIsolation { IsolationAuto, IsolationIsolate };
enum TouchActionDelay { TouchActionDelayNone, TouchActionDelayScript };
+enum ItemPosition {
+ ItemPositionAuto,
+ ItemPositionStretch,
+ ItemPositionBaseline,
+ ItemPositionCenter,
+ ItemPositionStart,
+ ItemPositionEnd,
+ ItemPositionSelfStart,
+ ItemPositionSelfEnd,
+ ItemPositionFlexStart,
+ ItemPositionFlexEnd,
+ ItemPositionLeft,
+ ItemPositionRight
+};
+
+enum OverflowAlignment {
+ OverflowAlignmentDefault,
+ OverflowAlignmentTrue,
+ OverflowAlignmentSafe
+};
+
// Reasonable maximum to prevent insane font sizes from causing crashes on some platforms (such as Windows).
static const float maximumAllowedFontSize = 1000000.0f;
enum TextIndentLine { TextIndentFirstLine, TextIndentEachLine };
+enum TextIndentType { TextIndentNormal, TextIndentHanging };
-enum LayoutBox { MarginBox, BorderBox, PaddingBox, ContentBox };
+enum CSSBoxType { BoxMissing = 0, MarginBox, BorderBox, PaddingBox, ContentBox };
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.cpp
index 947c39db641..2e0646ed587 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.cpp
@@ -40,7 +40,6 @@ SVGRenderStyle::SVGRenderStyle()
fill = defaultStyle->fill;
stroke = defaultStyle->stroke;
- text = defaultStyle->text;
stops = defaultStyle->stops;
misc = defaultStyle->misc;
inheritedResources = defaultStyle->inheritedResources;
@@ -55,7 +54,6 @@ SVGRenderStyle::SVGRenderStyle(CreateDefaultType)
fill.init();
stroke.init();
- text.init();
stops.init();
misc.init();
inheritedResources.init();
@@ -67,7 +65,6 @@ SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other)
{
fill = other.fill;
stroke = other.stroke;
- text = other.text;
stops = other.stops;
misc = other.misc;
inheritedResources = other.inheritedResources;
@@ -85,7 +82,6 @@ bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const
{
return fill == other.fill
&& stroke == other.stroke
- && text == other.text
&& stops == other.stops
&& misc == other.misc
&& inheritedResources == other.inheritedResources
@@ -98,7 +94,6 @@ bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle* other) const
{
return fill != other->fill
|| stroke != other->stroke
- || text != other->text
|| inheritedResources != other->inheritedResources
|| svg_inherited_flags != other->svg_inherited_flags;
}
@@ -110,7 +105,6 @@ void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent)
fill = svgInheritParent->fill;
stroke = svgInheritParent->stroke;
- text = svgInheritParent->text;
inheritedResources = svgInheritParent->inheritedResources;
svg_inherited_flags = svgInheritParent->svg_inherited_flags;
@@ -126,19 +120,27 @@ void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle* other)
StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
{
- // NOTE: All comparisions that may return StyleDifferenceLayout have to go before those who return StyleDifferenceRepaint
+ StyleDifference styleDifference;
- // If kerning changes, we need a relayout, to force SVGCharacterData to be recalculated in the SVGRootInlineBox.
- if (text != other->text)
- return StyleDifferenceLayout;
+ if (diffNeedsLayoutAndRepaint(other)) {
+ styleDifference.setNeedsFullLayout();
+ styleDifference.setNeedsRepaintObject();
+ } else if (diffNeedsRepaint(other)) {
+ styleDifference.setNeedsRepaintObject();
+ }
+
+ return styleDifference;
+}
+bool SVGRenderStyle::diffNeedsLayoutAndRepaint(const SVGRenderStyle* other) const
+{
// If resources change, we need a relayout, as the presence of resources influences the repaint rect.
if (resources != other->resources)
- return StyleDifferenceLayout;
+ return true;
// If markers change, we need a relayout, as marker boundaries are cached in RenderSVGPath.
if (inheritedResources != other->inheritedResources)
- return StyleDifferenceLayout;
+ return true;
// All text related properties influence layout.
if (svg_inherited_flags._textAnchor != other->svg_inherited_flags._textAnchor
@@ -148,20 +150,23 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
|| svg_noninherited_flags.f._alignmentBaseline != other->svg_noninherited_flags.f._alignmentBaseline
|| svg_noninherited_flags.f._dominantBaseline != other->svg_noninherited_flags.f._dominantBaseline
|| svg_noninherited_flags.f._baselineShift != other->svg_noninherited_flags.f._baselineShift)
- return StyleDifferenceLayout;
+ return true;
// Text related properties influence layout.
- bool miscNotEqual = misc != other->misc;
- if (miscNotEqual && misc->baselineShiftValue != other->misc->baselineShiftValue)
- return StyleDifferenceLayout;
+ if (misc->baselineShiftValue != other->misc->baselineShiftValue)
+ return true;
// These properties affect the cached stroke bounding box rects.
if (svg_inherited_flags._capStyle != other->svg_inherited_flags._capStyle
|| svg_inherited_flags._joinStyle != other->svg_inherited_flags._joinStyle)
- return StyleDifferenceLayout;
+ return true;
+
+ // vector-effect changes require a re-layout.
+ if (svg_noninherited_flags.f._vectorEffect != other->svg_noninherited_flags.f._vectorEffect)
+ return true;
// Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated.
- if (stroke != other->stroke) {
+ if (stroke.get() != other->stroke.get()) {
if (stroke->width != other->stroke->width
|| stroke->paintType != other->stroke->paintType
|| stroke->paintColor != other->stroke->paintColor
@@ -172,35 +177,37 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
|| stroke->visitedLinkPaintColor != other->stroke->visitedLinkPaintColor
|| stroke->visitedLinkPaintUri != other->stroke->visitedLinkPaintUri
|| stroke->visitedLinkPaintType != other->stroke->visitedLinkPaintType)
- return StyleDifferenceLayout;
-
- // Only the stroke-opacity case remains, where we only need a repaint.
- ASSERT(stroke->opacity != other->stroke->opacity);
- return StyleDifferenceRepaint;
+ return true;
}
- // vector-effect changes require a re-layout.
- if (svg_noninherited_flags.f._vectorEffect != other->svg_noninherited_flags.f._vectorEffect)
- return StyleDifferenceLayout;
+ return false;
+}
- // NOTE: All comparisions below may only return StyleDifferenceRepaint
+bool SVGRenderStyle::diffNeedsRepaint(const SVGRenderStyle* other) const
+{
+ if (stroke->opacity != other->stroke->opacity)
+ return true;
// Painting related properties only need repaints.
- if (miscNotEqual) {
+ if (misc.get() != other->misc.get()) {
if (misc->floodColor != other->misc->floodColor
|| misc->floodOpacity != other->misc->floodOpacity
|| misc->lightingColor != other->misc->lightingColor)
- return StyleDifferenceRepaint;
+ return true;
}
// If fill changes, we just need to repaint. Fill boundaries are not influenced by this, only by the Path, that RenderSVGPath contains.
- if (fill->paintType != other->fill->paintType || fill->paintColor != other->fill->paintColor
- || fill->paintUri != other->fill->paintUri || fill->opacity != other->fill->opacity)
- return StyleDifferenceRepaint;
+ if (fill.get() != other->fill.get()) {
+ if (fill->paintType != other->fill->paintType
+ || fill->paintColor != other->fill->paintColor
+ || fill->paintUri != other->fill->paintUri
+ || fill->opacity != other->fill->opacity)
+ return true;
+ }
// If gradient stops change, we just need to repaint. Style updates are already handled through RenderSVGGradientSTop.
if (stops != other->stops)
- return StyleDifferenceRepaint;
+ return true;
// Changes of these flags only cause repaints.
if (svg_inherited_flags._colorRendering != other->svg_inherited_flags._colorRendering
@@ -210,15 +217,15 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
|| svg_inherited_flags._colorInterpolation != other->svg_inherited_flags._colorInterpolation
|| svg_inherited_flags._colorInterpolationFilters != other->svg_inherited_flags._colorInterpolationFilters
|| svg_inherited_flags._paintOrder != other->svg_inherited_flags._paintOrder)
- return StyleDifferenceRepaint;
+ return true;
if (svg_noninherited_flags.f.bufferedRendering != other->svg_noninherited_flags.f.bufferedRendering)
- return StyleDifferenceRepaint;
+ return true;
if (svg_noninherited_flags.f.maskType != other->svg_noninherited_flags.f.maskType)
- return StyleDifferenceRepaint;
+ return true;
- return StyleDifferenceEqual;
+ return false;
}
EPaintOrderType SVGRenderStyle::paintOrderType(unsigned index) const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.h b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.h
index dba333e1ddf..128ed626aa7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyle.h
@@ -28,16 +28,13 @@
#include "core/rendering/style/DataRef.h"
#include "core/rendering/style/RenderStyleConstants.h"
#include "core/rendering/style/SVGRenderStyleDefs.h"
+#include "core/rendering/style/StyleDifference.h"
#include "core/svg/SVGPaint.h"
#include "platform/graphics/GraphicsTypes.h"
#include "platform/graphics/Path.h"
namespace WebCore {
-class FloatRect;
-class IntRect;
-class RenderObject;
-
class SVGRenderStyle : public RefCounted<SVGRenderStyle> {
public:
static PassRefPtr<SVGRenderStyle> create() { return adoptRef(new SVGRenderStyle); }
@@ -79,48 +76,41 @@ public:
static SVGPaint::SVGPaintType initialStrokePaintType() { return SVGPaint::SVG_PAINTTYPE_NONE; }
static Color initialStrokePaintColor() { return Color(); }
static String initialStrokePaintUri() { return String(); }
- static Vector<SVGLength> initialStrokeDashArray() { return Vector<SVGLength>(); }
+ static PassRefPtr<SVGLengthList> initialStrokeDashArray() { return SVGLengthList::create(); }
static float initialStrokeMiterLimit() { return 4; }
static float initialStopOpacity() { return 1; }
static Color initialStopColor() { return Color(0, 0, 0); }
static float initialFloodOpacity() { return 1; }
static Color initialFloodColor() { return Color(0, 0, 0); }
static Color initialLightingColor() { return Color(255, 255, 255); }
- static String initialClipperResource() { return String(); }
- static String initialFilterResource() { return String(); }
- static String initialMaskerResource() { return String(); }
- static String initialMarkerStartResource() { return String(); }
- static String initialMarkerMidResource() { return String(); }
- static String initialMarkerEndResource() { return String(); }
+ static const AtomicString& initialClipperResource() { return nullAtom; }
+ static const AtomicString& initialFilterResource() { return nullAtom; }
+ static const AtomicString& initialMaskerResource() { return nullAtom; }
+ static const AtomicString& initialMarkerStartResource() { return nullAtom; }
+ static const AtomicString& initialMarkerMidResource() { return nullAtom; }
+ static const AtomicString& initialMarkerEndResource() { return nullAtom; }
static EMaskType initialMaskType() { return MT_LUMINANCE; }
static EPaintOrder initialPaintOrder() { return PO_NORMAL; }
- static SVGLength initialBaselineShiftValue()
- {
- SVGLength length;
- length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
- return length;
- }
-
- static SVGLength initialKerning()
+ static PassRefPtr<SVGLength> initialBaselineShiftValue()
{
- SVGLength length;
- length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
- return length;
+ RefPtr<SVGLength> length = SVGLength::create();
+ length->newValueSpecifiedUnits(LengthTypeNumber, 0);
+ return length.release();
}
- static SVGLength initialStrokeDashOffset()
+ static PassRefPtr<SVGLength> initialStrokeDashOffset()
{
- SVGLength length;
- length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
- return length;
+ RefPtr<SVGLength> length = SVGLength::create();
+ length->newValueSpecifiedUnits(LengthTypeNumber, 0);
+ return length.release();
}
- static SVGLength initialStrokeWidth()
+ static PassRefPtr<SVGLength> initialStrokeWidth()
{
- SVGLength length;
- length.newValueSpecifiedUnits(LengthTypeNumber, 1, ASSERT_NO_EXCEPTION);
- return length;
+ RefPtr<SVGLength> length = SVGLength::create();
+ length->newValueSpecifiedUnits(LengthTypeNumber, 1);
+ return length.release();
}
// SVG CSS Property setters
@@ -196,7 +186,7 @@ public:
}
}
- void setStrokeDashArray(const Vector<SVGLength>& obj)
+ void setStrokeDashArray(PassRefPtr<SVGLengthList> obj)
{
if (!(stroke->dashArray == obj))
stroke.access()->dashArray = obj;
@@ -208,24 +198,18 @@ public:
stroke.access()->miterLimit = obj;
}
- void setStrokeWidth(const SVGLength& obj)
+ void setStrokeWidth(PassRefPtr<SVGLength> obj)
{
if (!(stroke->width == obj))
stroke.access()->width = obj;
}
- void setStrokeDashOffset(const SVGLength& obj)
+ void setStrokeDashOffset(PassRefPtr<SVGLength> obj)
{
if (!(stroke->dashOffset == obj))
stroke.access()->dashOffset = obj;
}
- void setKerning(const SVGLength& obj)
- {
- if (!(text->kerning == obj))
- text.access()->kerning = obj;
- }
-
void setStopOpacity(float obj)
{
if (!(stops->opacity == obj))
@@ -256,45 +240,45 @@ public:
misc.access()->lightingColor = obj;
}
- void setBaselineShiftValue(const SVGLength& obj)
+ void setBaselineShiftValue(PassRefPtr<SVGLength> obj)
{
if (!(misc->baselineShiftValue == obj))
misc.access()->baselineShiftValue = obj;
}
// Setters for non-inherited resources
- void setClipperResource(const String& obj)
+ void setClipperResource(const AtomicString& obj)
{
if (!(resources->clipper == obj))
resources.access()->clipper = obj;
}
- void setFilterResource(const String& obj)
+ void setFilterResource(const AtomicString& obj)
{
if (!(resources->filter == obj))
resources.access()->filter = obj;
}
- void setMaskerResource(const String& obj)
+ void setMaskerResource(const AtomicString& obj)
{
if (!(resources->masker == obj))
resources.access()->masker = obj;
}
// Setters for inherited resources
- void setMarkerStartResource(const String& obj)
+ void setMarkerStartResource(const AtomicString& obj)
{
if (!(inheritedResources->markerStart == obj))
inheritedResources.access()->markerStart = obj;
}
- void setMarkerMidResource(const String& obj)
+ void setMarkerMidResource(const AtomicString& obj)
{
if (!(inheritedResources->markerMid == obj))
inheritedResources.access()->markerMid = obj;
}
- void setMarkerEndResource(const String& obj)
+ void setMarkerEndResource(const AtomicString& obj)
{
if (!(inheritedResources->markerEnd == obj))
inheritedResources.access()->markerEnd = obj;
@@ -326,23 +310,22 @@ public:
const SVGPaint::SVGPaintType& strokePaintType() const { return stroke->paintType; }
const Color& strokePaintColor() const { return stroke->paintColor; }
const String& strokePaintUri() const { return stroke->paintUri; }
- Vector<SVGLength> strokeDashArray() const { return stroke->dashArray; }
+ SVGLengthList* strokeDashArray() const { return stroke->dashArray.get(); }
float strokeMiterLimit() const { return stroke->miterLimit; }
- SVGLength strokeWidth() const { return stroke->width; }
- SVGLength strokeDashOffset() const { return stroke->dashOffset; }
- SVGLength kerning() const { return text->kerning; }
+ SVGLength* strokeWidth() const { return stroke->width.get(); }
+ SVGLength* strokeDashOffset() const { return stroke->dashOffset.get(); }
float stopOpacity() const { return stops->opacity; }
const Color& stopColor() const { return stops->color; }
float floodOpacity() const { return misc->floodOpacity; }
const Color& floodColor() const { return misc->floodColor; }
const Color& lightingColor() const { return misc->lightingColor; }
- SVGLength baselineShiftValue() const { return misc->baselineShiftValue; }
- String clipperResource() const { return resources->clipper; }
- String filterResource() const { return resources->filter; }
- String maskerResource() const { return resources->masker; }
- String markerStartResource() const { return inheritedResources->markerStart; }
- String markerMidResource() const { return inheritedResources->markerMid; }
- String markerEndResource() const { return inheritedResources->markerEnd; }
+ SVGLength* baselineShiftValue() const { return misc->baselineShiftValue.get(); }
+ const AtomicString& clipperResource() const { return resources->clipper; }
+ const AtomicString& filterResource() const { return resources->filter; }
+ const AtomicString& maskerResource() const { return resources->masker; }
+ const AtomicString& markerStartResource() const { return inheritedResources->markerStart; }
+ const AtomicString& markerMidResource() const { return inheritedResources->markerMid; }
+ const AtomicString& markerEndResource() const { return inheritedResources->markerEnd; }
EMaskType maskType() const { return (EMaskType) svg_noninherited_flags.f.maskType; }
EPaintOrder paintOrder() const { return (EPaintOrder) svg_inherited_flags._paintOrder; }
EPaintOrderType paintOrderType(unsigned index) const;
@@ -360,7 +343,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 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; }
@@ -427,7 +410,6 @@ protected:
// inherited attributes
DataRef<StyleFillData> fill;
DataRef<StyleStrokeData> stroke;
- DataRef<StyleTextData> text;
DataRef<StyleInheritedResourceData> inheritedResources;
// non-inherited attributes
@@ -442,6 +424,9 @@ private:
SVGRenderStyle(const SVGRenderStyle&);
SVGRenderStyle(CreateDefaultType); // Used to create the default style.
+ bool diffNeedsLayoutAndRepaint(const SVGRenderStyle* other) const;
+ bool diffNeedsRepaint(const SVGRenderStyle* other) const;
+
void setBitDefaults()
{
svg_inherited_flags._clipRule = initialClipRule();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.cpp
index 56e4a06ed5f..7a7f562b4d3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.cpp
@@ -86,9 +86,9 @@ StyleStrokeData::StyleStrokeData(const StyleStrokeData& other)
: RefCounted<StyleStrokeData>()
, opacity(other.opacity)
, miterLimit(other.miterLimit)
- , width(other.width)
- , dashOffset(other.dashOffset)
- , dashArray(other.dashArray)
+ , width(other.width->clone())
+ , dashOffset(other.dashOffset->clone())
+ , dashArray(other.dashArray->clone())
, paintType(other.paintType)
, paintColor(other.paintColor)
, paintUri(other.paintUri)
@@ -100,11 +100,11 @@ StyleStrokeData::StyleStrokeData(const StyleStrokeData& other)
bool StyleStrokeData::operator==(const StyleStrokeData& other) const
{
- return width == other.width
+ return *width == *other.width
&& opacity == other.opacity
&& miterLimit == other.miterLimit
- && dashOffset == other.dashOffset
- && dashArray == other.dashArray
+ && *dashOffset == *other.dashOffset
+ && *dashArray == *other.dashArray
&& paintType == other.paintType
&& paintColor == other.paintColor
&& paintUri == other.paintUri
@@ -132,22 +132,6 @@ bool StyleStopData::operator==(const StyleStopData& other) const
&& opacity == other.opacity;
}
-StyleTextData::StyleTextData()
- : kerning(SVGRenderStyle::initialKerning())
-{
-}
-
-StyleTextData::StyleTextData(const StyleTextData& other)
- : RefCounted<StyleTextData>()
- , kerning(other.kerning)
-{
-}
-
-bool StyleTextData::operator==(const StyleTextData& other) const
-{
- return kerning == other.kerning;
-}
-
StyleMiscData::StyleMiscData()
: floodColor(SVGRenderStyle::initialFloodColor())
, floodOpacity(SVGRenderStyle::initialFloodOpacity())
@@ -161,7 +145,7 @@ StyleMiscData::StyleMiscData(const StyleMiscData& other)
, floodColor(other.floodColor)
, floodOpacity(other.floodOpacity)
, lightingColor(other.lightingColor)
- , baselineShiftValue(other.baselineShiftValue)
+ , baselineShiftValue(other.baselineShiftValue->clone())
{
}
@@ -170,7 +154,7 @@ bool StyleMiscData::operator==(const StyleMiscData& other) const
return floodOpacity == other.floodOpacity
&& floodColor == other.floodColor
&& lightingColor == other.lightingColor
- && baselineShiftValue == other.baselineShiftValue;
+ && *baselineShiftValue == *other.baselineShiftValue;
}
StyleResourceData::StyleResourceData()
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.h b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.h
index 9b32f78a578..abd12379dd6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/SVGRenderStyleDefs.h
@@ -29,6 +29,7 @@
#define SVGRenderStyleDefs_h
#include "core/svg/SVGLength.h"
+#include "core/svg/SVGLengthList.h"
#include "core/svg/SVGPaint.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
@@ -103,10 +104,6 @@ namespace WebCore {
typedef unsigned EPaintOrder;
const unsigned PO_NORMAL = PT_FILL | PT_STROKE << 2 | PT_MARKERS << 4;
- class CSSValue;
- class CSSValueList;
- class SVGPaint;
-
// Inherited/Non-Inherited Style Datastructures
class StyleFillData : public RefCounted<StyleFillData> {
public:
@@ -146,9 +143,9 @@ namespace WebCore {
float opacity;
float miterLimit;
- SVGLength width;
- SVGLength dashOffset;
- Vector<SVGLength> dashArray;
+ RefPtr<SVGLength> width;
+ RefPtr<SVGLength> dashOffset;
+ RefPtr<SVGLengthList> dashArray;
SVGPaint::SVGPaintType paintType;
Color paintColor;
@@ -181,24 +178,6 @@ namespace WebCore {
StyleStopData(const StyleStopData&);
};
- class StyleTextData : public RefCounted<StyleTextData> {
- public:
- static PassRefPtr<StyleTextData> create() { return adoptRef(new StyleTextData); }
- PassRefPtr<StyleTextData> copy() const { return adoptRef(new StyleTextData(*this)); }
-
- bool operator==(const StyleTextData& other) const;
- bool operator!=(const StyleTextData& other) const
- {
- return !(*this == other);
- }
-
- SVGLength kerning;
-
- private:
- StyleTextData();
- StyleTextData(const StyleTextData&);
- };
-
// Note: the rule for this class is, *no inheritance* of these props
class StyleMiscData : public RefCounted<StyleMiscData> {
public:
@@ -215,8 +194,7 @@ namespace WebCore {
float floodOpacity;
Color lightingColor;
- // non-inherited text stuff lives here not in StyleTextData.
- SVGLength baselineShiftValue;
+ RefPtr<SVGLength> baselineShiftValue;
private:
StyleMiscData();
@@ -235,9 +213,9 @@ namespace WebCore {
return !(*this == other);
}
- String clipper;
- String filter;
- String masker;
+ AtomicString clipper;
+ AtomicString filter;
+ AtomicString masker;
private:
StyleResourceData();
@@ -256,9 +234,9 @@ namespace WebCore {
return !(*this == other);
}
- String markerStart;
- String markerMid;
- String markerEnd;
+ AtomicString markerStart;
+ AtomicString markerMid;
+ AtomicString markerEnd;
private:
StyleInheritedResourceData();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.cpp
index 7f81d909f6b..d89b03e74e8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.cpp
@@ -41,7 +41,7 @@ ShadowData ShadowData::blend(const ShadowData& from, double progress) const
return *this;
return ShadowData(WebCore::blend(from.location(), location(), progress),
- clampTo<int>(WebCore::blend(from.blur(), blur(), progress), 0),
+ clampTo(WebCore::blend(from.blur(), blur(), progress), 0.0f),
WebCore::blend(from.spread(), spread(), progress),
style(),
WebCore::blend(from.color(), color(), progress));
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.h b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.h
index 574b3f8214e..fa5a063cf34 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowData.h
@@ -25,7 +25,7 @@
#ifndef ShadowData_h
#define ShadowData_h
-#include "platform/geometry/IntPoint.h"
+#include "platform/geometry/FloatPoint.h"
#include "platform/graphics/Color.h"
namespace WebCore {
@@ -36,7 +36,7 @@ enum ShadowStyle { Normal, Inset };
class ShadowData {
WTF_MAKE_FAST_ALLOCATED;
public:
- ShadowData(const IntPoint& location, int blur, int spread, ShadowStyle style, const Color& color)
+ ShadowData(const FloatPoint& location, float blur, float spread, ShadowStyle style, const Color& color)
: m_location(location)
, m_blur(blur)
, m_spread(spread)
@@ -50,18 +50,19 @@ public:
ShadowData blend(const ShadowData& from, double progress) const;
- 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; }
+ float x() const { return m_location.x(); }
+ float y() const { return m_location.y(); }
+ FloatPoint location() const { return m_location; }
+ float blur() const { return m_blur; }
+ float spread() const { return m_spread; }
ShadowStyle style() const { return m_style; }
const Color& color() const { return m_color; }
private:
- IntPoint m_location;
- int m_blur;
- int m_spread;
+ FloatPoint m_location;
+ float m_blur;
+ float m_spread;
+ // FIXME: We should use StyleColor here to allow currentColor to work correctly with visited links
Color m_color;
ShadowStyle m_style;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.cpp
index 675effec90b..b0f414a1162 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.cpp
@@ -32,11 +32,10 @@
#include "core/rendering/style/ShadowList.h"
#include "platform/geometry/FloatRect.h"
-#include "platform/geometry/LayoutRect.h"
namespace WebCore {
-static inline void calculateShadowExtent(const ShadowList* shadowList, int additionalOutlineSize, int& shadowLeft, int& shadowRight, int& shadowTop, int& shadowBottom)
+static inline void calculateShadowExtent(const ShadowList* shadowList, float additionalOutlineSize, float& shadowLeft, float& shadowRight, float& shadowTop, float& shadowBottom)
{
ASSERT(shadowList);
size_t shadowCount = shadowList->shadows().size();
@@ -44,7 +43,7 @@ static inline void calculateShadowExtent(const ShadowList* shadowList, int addit
const ShadowData& shadow = shadowList->shadows()[i];
if (shadow.style() == Inset)
continue;
- int blurAndSpread = shadow.blur() + shadow.spread() + additionalOutlineSize;
+ float blurAndSpread = shadow.blur() + shadow.spread() + additionalOutlineSize;
shadowLeft = std::min(shadow.x() - blurAndSpread, shadowLeft);
shadowRight = std::max(shadow.x() + blurAndSpread, shadowRight);
shadowTop = std::min(shadow.y() - blurAndSpread, shadowTop);
@@ -52,25 +51,19 @@ static inline void calculateShadowExtent(const ShadowList* shadowList, int addit
}
}
-void ShadowList::adjustRectForShadow(LayoutRect& rect, int additionalOutlineSize) const
+void ShadowList::adjustRectForShadow(LayoutRect& rect, float additionalOutlineSize) const
{
- int shadowLeft = 0;
- int shadowRight = 0;
- int shadowTop = 0;
- int shadowBottom = 0;
- calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
-
- rect.move(shadowLeft, shadowTop);
- rect.setWidth(rect.width() - shadowLeft + shadowRight);
- rect.setHeight(rect.height() - shadowTop + shadowBottom);
+ FloatRect floatRect(rect);
+ adjustRectForShadow(floatRect);
+ rect = LayoutRect(floatRect);
}
-void ShadowList::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const
+void ShadowList::adjustRectForShadow(FloatRect& rect, float additionalOutlineSize) const
{
- int shadowLeft = 0;
- int shadowRight = 0;
- int shadowTop = 0;
- int shadowBottom = 0;
+ float shadowLeft = 0;
+ float shadowRight = 0;
+ float shadowTop = 0;
+ float shadowBottom = 0;
calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
rect.move(shadowLeft, shadowTop);
@@ -83,12 +76,12 @@ PassRefPtr<ShadowList> ShadowList::blend(const ShadowList* from, const ShadowLis
size_t fromLength = from ? from->shadows().size() : 0;
size_t toLength = to ? to->shadows().size() : 0;
if (!fromLength && !toLength)
- return 0;
+ return nullptr;
ShadowDataVector shadows;
- DEFINE_STATIC_LOCAL(ShadowData, defaultShadowData, (IntPoint(), 0, 0, Normal, Color::transparent));
- DEFINE_STATIC_LOCAL(ShadowData, defaultInsetShadowData, (IntPoint(), 0, 0, Inset, Color::transparent));
+ DEFINE_STATIC_LOCAL(ShadowData, defaultShadowData, (FloatPoint(), 0, 0, Normal, Color::transparent));
+ DEFINE_STATIC_LOCAL(ShadowData, defaultInsetShadowData, (FloatPoint(), 0, 0, Inset, Color::transparent));
size_t maxLength = std::max(fromLength, toLength);
for (size_t i = 0; i < maxLength; ++i) {
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.h b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.h
index 12acedf4801..6a1a4c1c9ad 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/ShadowList.h
@@ -32,6 +32,7 @@
#define ShadowList_h
#include "core/rendering/style/ShadowData.h"
+#include "platform/geometry/LayoutRect.h"
#include "wtf/RefCounted.h"
#include "wtf/Vector.h"
@@ -57,8 +58,8 @@ public:
static PassRefPtr<ShadowList> blend(const ShadowList* from, const ShadowList* to, double progress);
- void adjustRectForShadow(LayoutRect&, int additionalOutlineSize = 0) const;
- void adjustRectForShadow(FloatRect&, int additionalOutlineSize = 0) const;
+ void adjustRectForShadow(LayoutRect&, float additionalOutlineSize = 0) const;
+ void adjustRectForShadow(FloatRect&, float additionalOutlineSize = 0) const;
private:
ShadowList(ShadowDataVector& shadows)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/ShapeValue.h b/chromium/third_party/WebKit/Source/core/rendering/style/ShapeValue.h
index 6b872807dce..dc12b4f1ff8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/ShapeValue.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/ShapeValue.h
@@ -44,23 +44,17 @@ public:
// The Auto value is defined by a null ShapeValue*
Shape,
Box,
- Outside,
Image
};
- static PassRefPtr<ShapeValue> createShapeValue(PassRefPtr<BasicShape> shape)
+ static PassRefPtr<ShapeValue> createShapeValue(PassRefPtr<BasicShape> shape, CSSBoxType cssBox)
{
- return adoptRef(new ShapeValue(shape));
+ return adoptRef(new ShapeValue(shape, cssBox));
}
- static PassRefPtr<ShapeValue> createOutsideValue()
+ static PassRefPtr<ShapeValue> createBoxShapeValue(CSSBoxType cssBox)
{
- return adoptRef(new ShapeValue(Outside));
- }
-
- static PassRefPtr<ShapeValue> createLayoutBoxValue(LayoutBox layoutBox)
- {
- return adoptRef(new ShapeValue(layoutBox));
+ return adoptRef(new ShapeValue(cssBox));
}
static PassRefPtr<ShapeValue> createImageValue(PassRefPtr<StyleImage> image)
@@ -72,39 +66,45 @@ public:
BasicShape* shape() const { return m_shape.get(); }
StyleImage* image() const { return m_image.get(); }
- bool isImageValid() const { return image() && image()->cachedImage() && image()->cachedImage()->hasImage(); }
+ bool isImageValid() const
+ {
+ if (!image())
+ return false;
+ if (image()->isImageResource() || image()->isImageResourceSet())
+ return image()->cachedImage() && image()->cachedImage()->hasImage();
+ return image()->isGeneratedImage();
+ }
void setImage(PassRefPtr<StyleImage> image)
{
ASSERT(type() == Image);
if (m_image != image)
m_image = image;
}
- LayoutBox layoutBox() const { return m_layoutBox; }
- void setLayoutBox(LayoutBox layoutBox) { m_layoutBox = layoutBox; }
+ CSSBoxType cssBox() const { return m_cssBox; }
- bool operator==(const ShapeValue& other) const { return type() == other.type(); }
+ bool operator==(const ShapeValue& other) const;
private:
- ShapeValue(PassRefPtr<BasicShape> shape)
+ ShapeValue(PassRefPtr<BasicShape> shape, CSSBoxType cssBox)
: m_type(Shape)
, m_shape(shape)
- , m_layoutBox(ContentBox)
+ , m_cssBox(cssBox)
{
}
ShapeValue(ShapeValueType type)
: m_type(type)
- , m_layoutBox(ContentBox)
+ , m_cssBox(BoxMissing)
{
}
ShapeValue(PassRefPtr<StyleImage> image)
: m_type(Image)
, m_image(image)
- , m_layoutBox(ContentBox)
+ , m_cssBox(ContentBox)
{
}
- ShapeValue(LayoutBox layoutBox)
+ ShapeValue(CSSBoxType cssBox)
: m_type(Box)
- , m_layoutBox(layoutBox)
+ , m_cssBox(cssBox)
{
}
@@ -112,9 +112,27 @@ private:
ShapeValueType m_type;
RefPtr<BasicShape> m_shape;
RefPtr<StyleImage> m_image;
- LayoutBox m_layoutBox;
+ CSSBoxType m_cssBox;
};
+inline bool ShapeValue::operator==(const ShapeValue& other) const
+{
+ if (type() != other.type())
+ return false;
+
+ switch (type()) {
+ case Shape:
+ return shape() == other.shape() && cssBox() == other.cssBox();
+ case Box:
+ return cssBox() == other.cssBox();
+ case Image:
+ return image() == other.image();
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
}
#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.cpp
index d0b7ba4ff27..1dcfc53fb58 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.cpp
@@ -46,4 +46,9 @@ bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
}
+bool StyleBackgroundData::visuallyEqual(const StyleBackgroundData& o) const
+{
+ return m_background == o.m_background && m_color == o.m_color && m_outline.visuallyEqual(o.m_outline);
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.h
index fda242f38f2..f25efbd9f05 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleBackgroundData.h
@@ -45,8 +45,10 @@ public:
return !(*this == o);
}
+ bool visuallyEqual(const StyleBackgroundData&) const;
+
const FillLayer& background() const { return m_background; }
- const Color& color() const { return m_color; }
+ const StyleColor& color() const { return m_color; }
const OutlineValue& outline() const { return m_outline; }
private:
@@ -56,7 +58,7 @@ private:
StyleBackgroundData(const StyleBackgroundData&);
FillLayer m_background;
- Color m_color;
+ StyleColor m_color;
OutlineValue m_outline;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleBoxData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleBoxData.h
index 9b2296641df..6814b3a92e7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleBoxData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleBoxData.h
@@ -43,16 +43,16 @@ public:
return !(*this == o);
}
- Length width() const { return m_width; }
- Length height() const { return m_height; }
+ const Length& width() const { return m_width; }
+ const Length& height() const { return m_height; }
- Length minWidth() const { return m_minWidth; }
- Length minHeight() const { return m_minHeight; }
+ const Length& minWidth() const { return m_minWidth; }
+ const Length& minHeight() const { return m_minHeight; }
- Length maxWidth() const { return m_maxWidth; }
- Length maxHeight() const { return m_maxHeight; }
+ const Length& maxWidth() const { return m_maxWidth; }
+ const Length& maxHeight() const { return m_maxHeight; }
- Length verticalAlign() const { return m_verticalAlign; }
+ const Length& verticalAlign() const { return m_verticalAlign; }
int zIndex() const { return m_zIndex; }
bool hasAutoZIndex() const { return m_hasAutoZIndex; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.cpp
deleted file mode 100644
index 31c3d64d662..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013 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 "core/rendering/style/StyleCustomFilterProgram.h"
-
-#include "core/rendering/style/StyleCustomFilterProgramCache.h"
-
-namespace WebCore {
-
-StyleCustomFilterProgram::~StyleCustomFilterProgram()
-{
- if (m_cache)
- m_cache->remove(this);
-}
-
-} // namespace WebCore
-
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.h
deleted file mode 100644
index d79cf6368f5..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgram.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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 StyleCustomFilterProgram_h
-#define StyleCustomFilterProgram_h
-
-#include "core/fetch/ResourceClient.h"
-#include "core/fetch/ResourcePtr.h"
-#include "core/fetch/ShaderResource.h"
-#include "core/rendering/style/StyleShader.h"
-#include "platform/graphics/filters/custom/CustomFilterProgram.h"
-#include "platform/weborigin/KURL.h"
-#include "wtf/FastAllocBase.h"
-
-namespace WebCore {
-
-// CSS Shaders
-
-class StyleCustomFilterProgramCache;
-
-class StyleCustomFilterProgram : public CustomFilterProgram, public ResourceClient {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- static PassRefPtr<StyleCustomFilterProgram> create(KURL vertexShaderURL, PassRefPtr<StyleShader> vertexShader,
- KURL fragmentShaderURL, PassRefPtr<StyleShader> fragmentShader, CustomFilterProgramType programType,
- const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
- {
- return adoptRef(new StyleCustomFilterProgram(vertexShaderURL, vertexShader, fragmentShaderURL, fragmentShader, programType, mixSettings, meshType));
- }
-
- void setVertexShader(PassRefPtr<StyleShader> shader)
- {
- // The shader is immutable while in the cache.
- ASSERT(!m_cache);
- m_vertexShader = shader;
- }
- StyleShader* vertexShader() const { return m_vertexShader.get(); }
-
- void setFragmentShader(PassRefPtr<StyleShader> shader)
- {
- // The shader is immutable while in the cache.
- ASSERT(!m_cache);
- m_fragmentShader = shader;
- }
- StyleShader* fragmentShader() const { return m_fragmentShader.get(); }
-
- virtual String vertexShaderString() const
- {
- ASSERT(isLoaded());
- return m_cachedVertexShader.get() ? m_cachedVertexShader->shaderString() : String();
- }
-
- virtual String fragmentShaderString() const
- {
- ASSERT(isLoaded());
- return m_cachedFragmentShader.get() ? m_cachedFragmentShader->shaderString() : String();
- }
-
- virtual bool isLoaded() const
- {
- // Do not use the Resource:isLoaded method here, because it actually means !isLoading(),
- // so missing and canceled resources will have isLoaded set to true, even if they are not loaded yet.
- ASSERT(!m_vertexShader || m_vertexShader->isShaderResource());
- ASSERT(!m_fragmentShader || m_fragmentShader->isShaderResource());
-
- // If we failed to create resources for the vertex shader or the
- // fragment shader, they won't be set here.
- // This can happen if the ResourceFetcher is no longer accepting fetch
- // requests because the page is being torn down.
- if (!m_vertexShader && !m_fragmentShader)
- return false;
-
- ASSERT(m_cachedVertexShader.get() || m_cachedFragmentShader.get());
- return (!m_cachedVertexShader.get() || m_isVertexShaderLoaded)
- && (!m_cachedFragmentShader.get() || m_isFragmentShaderLoaded);
- }
-
- virtual void willHaveClients()
- {
- if (m_vertexShader) {
- m_cachedVertexShader = m_vertexShader->resource();
- m_cachedVertexShader->addClient(this);
- }
- if (m_fragmentShader) {
- m_cachedFragmentShader = m_fragmentShader->resource();
- m_cachedFragmentShader->addClient(this);
- }
- }
-
- virtual void didRemoveLastClient()
- {
- if (m_cachedVertexShader.get()) {
- m_cachedVertexShader->removeClient(this);
- m_cachedVertexShader = 0;
- m_isVertexShaderLoaded = false;
- }
- if (m_cachedFragmentShader.get()) {
- m_cachedFragmentShader->removeClient(this);
- m_cachedFragmentShader = 0;
- m_isFragmentShaderLoaded = false;
- }
- }
-
- virtual void notifyFinished(Resource* resource)
- {
- if (resource->errorOccurred())
- return;
- // Note that m_cachedVertexShader might be equal to m_cachedFragmentShader and it would only get one event in that case.
- if (resource == m_cachedVertexShader.get())
- m_isVertexShaderLoaded = true;
- if (resource == m_cachedFragmentShader.get())
- m_isFragmentShaderLoaded = true;
- if (isLoaded())
- notifyClients();
- }
-
- bool hasPendingShaders() const
- {
- return (m_vertexShader && m_vertexShader->isPendingShader())
- || (m_fragmentShader && m_fragmentShader->isPendingShader());
- }
-
- // StyleCustomFilterProgramCache is responsible with updating the reference to the cache.
- void setCache(StyleCustomFilterProgramCache* cache) { m_cache = cache; }
- bool inCache() const { return m_cache; }
-
- KURL vertexShaderURL() const { return m_vertexShaderURL; }
- KURL fragmentShaderURL() const { return m_fragmentShaderURL; }
-
-private:
- StyleCustomFilterProgram(KURL vertexShaderURL, PassRefPtr<StyleShader> vertexShader, KURL fragmentShaderURL, PassRefPtr<StyleShader> fragmentShader,
- CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
- : CustomFilterProgram(programType, mixSettings, meshType)
- , m_vertexShader(vertexShader)
- , m_fragmentShader(fragmentShader)
- , m_vertexShaderURL(vertexShaderURL)
- , m_fragmentShaderURL(fragmentShaderURL)
- , m_cache(0)
- , m_isVertexShaderLoaded(false)
- , m_isFragmentShaderLoaded(false)
- {
- }
-
- ~StyleCustomFilterProgram();
-
- RefPtr<StyleShader> m_vertexShader;
- RefPtr<StyleShader> m_fragmentShader;
-
- ResourcePtr<ShaderResource> m_cachedVertexShader;
- ResourcePtr<ShaderResource> m_cachedFragmentShader;
-
- // The URLs form the key of the StyleCustomFilterProgram in the cache and are used
- // to lookup the StyleCustomFilterProgram when it's removed from the cache.
- KURL m_vertexShaderURL;
- KURL m_fragmentShaderURL;
-
- // The Cache is responsible of invalidating this reference.
- StyleCustomFilterProgramCache* m_cache;
-
- bool m_isVertexShaderLoaded;
- bool m_isFragmentShaderLoaded;
-};
-
-} // namespace WebCore
-
-
-#endif // StyleCustomFilterProgram_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp
deleted file mode 100644
index 87d3aba9b66..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2013 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 "core/rendering/style/StyleCustomFilterProgramCache.h"
-
-#include "core/rendering/style/StyleCustomFilterProgram.h"
-
-namespace WebCore {
-
-static CustomFilterProgramInfo programCacheKey(StyleCustomFilterProgram* program)
-{
- ASSERT(program->vertexShaderURL().isValid() || program->fragmentShaderURL().isValid());
- return CustomFilterProgramInfo(program->vertexShaderURL().string(), program->fragmentShaderURL().string(),
- program->programType(), program->mixSettings(), program->meshType());
-}
-
-PassOwnPtr<StyleCustomFilterProgramCache> StyleCustomFilterProgramCache::create()
-{
- return adoptPtr(new StyleCustomFilterProgramCache());
-}
-
-StyleCustomFilterProgramCache::~StyleCustomFilterProgramCache()
-{
- // Make sure the programs are not calling back into this object.
- for (CacheMap::iterator iter = m_cache.begin(), end = m_cache.end(); iter != end; ++iter)
- iter->value->setCache(0);
-}
-
-StyleCustomFilterProgram* StyleCustomFilterProgramCache::lookup(const CustomFilterProgramInfo& programInfo) const
-{
- CacheMap::const_iterator iter = m_cache.find(programInfo);
- return iter != m_cache.end() ? iter->value : 0;
-}
-
-StyleCustomFilterProgram* StyleCustomFilterProgramCache::lookup(StyleCustomFilterProgram* program) const
-{
- return lookup(programCacheKey(program));
-}
-
-void StyleCustomFilterProgramCache::add(StyleCustomFilterProgram* program)
-{
- CustomFilterProgramInfo key = programCacheKey(program);
- ASSERT(m_cache.find(key) == m_cache.end());
- m_cache.set(key, program);
- program->setCache(this);
-}
-
-void StyleCustomFilterProgramCache::remove(StyleCustomFilterProgram* program)
-{
- CacheMap::iterator iter = m_cache.find(programCacheKey(program));
- ASSERT_WITH_SECURITY_IMPLICATION(iter != m_cache.end());
- m_cache.remove(iter);
-}
-
-
-} // namespace WebCore
-
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.h
deleted file mode 100644
index 2bc1652d0e6..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleCustomFilterProgramCache.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2013 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 StyleCustomFilterProgramCache_h
-#define StyleCustomFilterProgramCache_h
-
-#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h"
-#include "wtf/FastAllocBase.h"
-#include "wtf/HashMap.h"
-
-namespace WebCore {
-
-class StyleCustomFilterProgram;
-class CustomFilterProgramInfo;
-
-class StyleCustomFilterProgramCache {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- static PassOwnPtr<StyleCustomFilterProgramCache> create();
- ~StyleCustomFilterProgramCache();
-
- // Lookups a StyleCustomFilterProgram that has similar parameters with the specified program.
- StyleCustomFilterProgram* lookup(StyleCustomFilterProgram*) const;
- StyleCustomFilterProgram* lookup(const CustomFilterProgramInfo&) const;
-
- void add(StyleCustomFilterProgram*);
- void remove(StyleCustomFilterProgram*);
-
-private:
- StyleCustomFilterProgramCache() { }
-
- typedef HashMap<CustomFilterProgramInfo, StyleCustomFilterProgram*> CacheMap;
- CacheMap m_cache;
-};
-
-} // namespace WebCore
-
-
-#endif // StyleCustomFilterProgramCache_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp
index 4b3ff280e23..2c030fcc86a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp
@@ -28,8 +28,8 @@ namespace WebCore {
StyleDeprecatedFlexibleBoxData::StyleDeprecatedFlexibleBoxData()
: flex(RenderStyle::initialBoxFlex())
- , flex_group(RenderStyle::initialBoxFlexGroup())
- , ordinal_group(RenderStyle::initialBoxOrdinalGroup())
+ , flexGroup(RenderStyle::initialBoxFlexGroup())
+ , ordinalGroup(RenderStyle::initialBoxOrdinalGroup())
, align(RenderStyle::initialBoxAlign())
, pack(RenderStyle::initialBoxPack())
, orient(RenderStyle::initialBoxOrient())
@@ -40,8 +40,8 @@ StyleDeprecatedFlexibleBoxData::StyleDeprecatedFlexibleBoxData()
StyleDeprecatedFlexibleBoxData::StyleDeprecatedFlexibleBoxData(const StyleDeprecatedFlexibleBoxData& o)
: RefCounted<StyleDeprecatedFlexibleBoxData>()
, flex(o.flex)
- , flex_group(o.flex_group)
- , ordinal_group(o.ordinal_group)
+ , flexGroup(o.flexGroup)
+ , ordinalGroup(o.ordinalGroup)
, align(o.align)
, pack(o.pack)
, orient(o.orient)
@@ -51,9 +51,7 @@ StyleDeprecatedFlexibleBoxData::StyleDeprecatedFlexibleBoxData(const StyleDeprec
bool StyleDeprecatedFlexibleBoxData::operator==(const StyleDeprecatedFlexibleBoxData& o) const
{
- return flex == o.flex && flex_group == o.flex_group &&
- ordinal_group == o.ordinal_group && align == o.align &&
- pack == o.pack && orient == o.orient && lines == o.lines;
+ return flex == o.flex && flexGroup == o.flexGroup && ordinalGroup == o.ordinalGroup && align == o.align && pack == o.pack && orient == o.orient && lines == o.lines;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h
index 501157cc15d..adfee1f1717 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h
@@ -42,8 +42,8 @@ public:
}
float flex;
- unsigned int flex_group;
- unsigned int ordinal_group;
+ unsigned flexGroup;
+ unsigned ordinalGroup;
unsigned align : 3; // EBoxAlignment
unsigned pack: 2; // EBoxPack
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleDifference.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleDifference.h
new file mode 100644
index 00000000000..d8418217b83
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleDifference.h
@@ -0,0 +1,80 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef StyleDifference_h
+#define StyleDifference_h
+
+#include "wtf/Assertions.h"
+
+namespace WebCore {
+
+// This class represents the difference between two computed styles (RenderStyle).
+// The difference can be combination of 3 types according to the actions needed:
+// - Difference needing layout
+// - Difference needing repaint
+// - Difference needing recompositing layers
+class StyleDifference {
+public:
+ StyleDifference()
+ : m_needsRecompositeLayer(false)
+ , m_repaintType(NoRepaint)
+ , m_layoutType(NoLayout) { }
+
+ // The two styles are identical.
+ bool hasNoChange() const { return !m_needsRecompositeLayer && !m_repaintType && !m_layoutType; }
+
+ // The layer needs its position and transform updated. Implied by other repaint and layout flags.
+ bool needsRecompositeLayer() const { return m_needsRecompositeLayer || needsRepaint() || needsLayout(); }
+ void setNeedsRecompositeLayer() { m_needsRecompositeLayer = true; }
+
+ bool needsRepaint() const { return m_repaintType != NoRepaint; }
+ void clearNeedsRepaint() { m_repaintType = NoRepaint; }
+
+ // The object just needs to be repainted.
+ bool needsRepaintObject() const { return m_repaintType == RepaintObject; }
+ void setNeedsRepaintObject()
+ {
+ ASSERT(!needsRepaintLayer());
+ m_repaintType = RepaintObject;
+ }
+
+ // The layer and its descendant layers need to be repainted.
+ bool needsRepaintLayer() const { return m_repaintType == RepaintLayer; }
+ void setNeedsRepaintLayer() { m_repaintType = RepaintLayer; }
+
+ bool needsLayout() const { return m_layoutType != NoLayout; }
+ void clearNeedsLayout() { m_layoutType = NoLayout; }
+
+ // The offset of this positioned object has been updated.
+ bool needsPositionedMovementLayout() const { return m_layoutType == PositionedMovement; }
+ void setNeedsPositionedMovementLayout()
+ {
+ ASSERT(!needsFullLayout());
+ m_layoutType = PositionedMovement;
+ }
+
+ bool needsFullLayout() const { return m_layoutType == FullLayout; }
+ void setNeedsFullLayout() { m_layoutType = FullLayout; }
+
+private:
+ unsigned m_needsRecompositeLayer : 1;
+
+ enum RepaintType {
+ NoRepaint = 0,
+ RepaintObject,
+ RepaintLayer
+ };
+ unsigned m_repaintType : 2;
+
+ enum LayoutType {
+ NoLayout = 0,
+ PositionedMovement,
+ FullLayout
+ };
+ unsigned m_layoutType : 2;
+};
+
+} // namespace WebCore
+
+#endif // StyleDifference_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.cpp
index 31dc65a0452..e53dc04ada8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.cpp
@@ -24,6 +24,7 @@
#include "config.h"
#include "core/rendering/style/StyleFetchedImage.h"
+#include "core/css/CSSImageValue.h"
#include "core/fetch/ImageResource.h"
#include "core/rendering/RenderObject.h"
@@ -41,12 +42,12 @@ StyleFetchedImage::~StyleFetchedImage()
m_image->removeClient(this);
}
-PassRefPtr<CSSValue> StyleFetchedImage::cssValue() const
+PassRefPtrWillBeRawPtr<CSSValue> StyleFetchedImage::cssValue() const
{
- return CSSPrimitiveValue::create(m_image->url().string(), CSSPrimitiveValue::CSS_URI);
+ return CSSImageValue::create(m_image->url(), const_cast<StyleFetchedImage*>(this));
}
-bool StyleFetchedImage::canRender(const RenderObject* renderer, float multiplier) const
+bool StyleFetchedImage::canRender(const RenderObject& renderer, float multiplier) const
{
return m_image->canRender(renderer, multiplier);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.h
index e783439b195..e74c26c9168 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImage.h
@@ -32,28 +32,28 @@ namespace WebCore {
class ImageResource;
-class StyleFetchedImage : public StyleImage, private ImageResourceClient {
+class StyleFetchedImage FINAL : public StyleImage, private ImageResourceClient {
WTF_MAKE_FAST_ALLOCATED;
public:
static PassRefPtr<StyleFetchedImage> create(ImageResource* image) { return adoptRef(new StyleFetchedImage(image)); }
virtual ~StyleFetchedImage();
- virtual WrappedImagePtr data() const { return m_image.get(); }
+ virtual WrappedImagePtr data() const OVERRIDE { return m_image.get(); }
- virtual PassRefPtr<CSSValue> cssValue() const;
+ virtual PassRefPtrWillBeRawPtr<CSSValue> cssValue() const OVERRIDE;
- virtual bool canRender(const RenderObject*, float multiplier) const;
- virtual bool isLoaded() const;
- virtual bool errorOccurred() const;
+ virtual bool canRender(const RenderObject&, float multiplier) const OVERRIDE;
+ virtual bool isLoaded() const OVERRIDE;
+ virtual bool errorOccurred() const OVERRIDE;
virtual LayoutSize imageSize(const RenderObject*, float multiplier) const OVERRIDE;
- 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 bool imageHasRelativeWidth() const OVERRIDE;
+ virtual bool imageHasRelativeHeight() const OVERRIDE;
+ virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) OVERRIDE;
+ virtual bool usesImageContainerSize() const OVERRIDE;
+ virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float) OVERRIDE;
+ virtual void addClient(RenderObject*) OVERRIDE;
+ virtual void removeClient(RenderObject*) OVERRIDE;
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const OVERRIDE;
virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE;
virtual ImageResource* cachedImage() const OVERRIDE { return m_image.get(); }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.cpp
index 04a8d9d5961..2aacd2fedd9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.cpp
@@ -47,12 +47,12 @@ StyleFetchedImageSet::~StyleFetchedImageSet()
m_bestFitImage->removeClient(this);
}
-PassRefPtr<CSSValue> StyleFetchedImageSet::cssValue() const
+PassRefPtrWillBeRawPtr<CSSValue> StyleFetchedImageSet::cssValue() const
{
return m_imageSetValue;
}
-bool StyleFetchedImageSet::canRender(const RenderObject* renderer, float multiplier) const
+bool StyleFetchedImageSet::canRender(const RenderObject& renderer, float multiplier) const
{
return m_bestFitImage->canRender(renderer, multiplier);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.h
index 873c14299ef..cee20a65846 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedImageSet.h
@@ -38,7 +38,7 @@ class CSSImageSetValue;
// This class keeps one cached image and has access to a set of alternatives.
-class StyleFetchedImageSet : public StyleImage, private ImageResourceClient {
+class StyleFetchedImageSet FINAL : public StyleImage, private ImageResourceClient {
WTF_MAKE_FAST_ALLOCATED;
public:
static PassRefPtr<StyleFetchedImageSet> create(ImageResource* image, float imageScaleFactor, CSSImageSetValue* value)
@@ -47,28 +47,28 @@ public:
}
virtual ~StyleFetchedImageSet();
- virtual PassRefPtr<CSSValue> cssValue() const;
+ virtual PassRefPtrWillBeRawPtr<CSSValue> cssValue() const OVERRIDE;
// 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(); }
+ virtual WrappedImagePtr data() const OVERRIDE { return m_bestFitImage.get(); }
void clearImageSetValue() { m_imageSetValue = 0; }
- virtual bool canRender(const RenderObject*, float multiplier) const;
- virtual bool isLoaded() const;
- virtual bool errorOccurred() const;
- virtual LayoutSize 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; }
+ virtual bool canRender(const RenderObject&, float multiplier) const OVERRIDE;
+ virtual bool isLoaded() const OVERRIDE;
+ virtual bool errorOccurred() const OVERRIDE;
+ virtual LayoutSize imageSize(const RenderObject*, float multiplier) const OVERRIDE;
+ virtual bool imageHasRelativeWidth() const OVERRIDE;
+ virtual bool imageHasRelativeHeight() const OVERRIDE;
+ virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) OVERRIDE;
+ virtual bool usesImageContainerSize() const OVERRIDE;
+ virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float) OVERRIDE;
+ virtual void addClient(RenderObject*) OVERRIDE;
+ virtual void removeClient(RenderObject*) OVERRIDE;
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const OVERRIDE;
+ virtual float imageScaleFactor() const OVERRIDE { return m_imageScaleFactor; }
virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE;
virtual ImageResource* cachedImage() const OVERRIDE { return m_bestFitImage.get(); }
@@ -77,6 +77,11 @@ private:
ResourcePtr<ImageResource> m_bestFitImage;
float m_imageScaleFactor;
+
+ // FIXME: oilpan: Change to RawPtrWillBeMember when moving this class onto oilpan heap.
+ // Also add "if !ENABLE(OILPAN)" around clearImageSetValue above as well as around its
+ // caller since it should not be needed once both of the objects are on the heap and
+ // oilpan is enabled.
CSSImageSetValue* m_imageSetValue; // Not retained; it owns us.
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.cpp
deleted file mode 100644
index 13a8b98c36a..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.cpp
+++ /dev/null
@@ -1,53 +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.
- */
-
-#include "config.h"
-
-#include "core/rendering/style/StyleFetchedShader.h"
-
-#include "core/css/CSSPrimitiveValue.h"
-#include "core/fetch/ShaderResource.h"
-
-namespace WebCore {
-
-
-StyleFetchedShader::StyleFetchedShader(ShaderResource* shader)
- : m_shader(shader)
-{
- m_isShaderResource = true;
-}
-
-PassRefPtr<CSSValue> StyleFetchedShader::cssValue() const
-{
- return CSSPrimitiveValue::create(m_shader->url().string(), CSSPrimitiveValue::CSS_URI);
-}
-
-} // namespace WebCore
-
-
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.h
deleted file mode 100644
index 104a90cc871..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleFetchedShader.h
+++ /dev/null
@@ -1,57 +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 StyleFetchedShader_h
-#define StyleFetchedShader_h
-
-#include "core/fetch/ResourcePtr.h"
-#include "core/rendering/style/StyleShader.h"
-
-namespace WebCore {
-
-class ShaderResource;
-
-class StyleFetchedShader : public StyleShader {
-public:
- // FIXME: Keep a reference to the actual ShaderResource in this class.
- static PassRefPtr<StyleFetchedShader> create(ShaderResource* shader) { return adoptRef(new StyleFetchedShader(shader)); }
-
- virtual PassRefPtr<CSSValue> cssValue() const;
-
- virtual ShaderResource* resource() const { return m_shader.get(); }
-
-private:
- StyleFetchedShader(ShaderResource*);
-
- ResourcePtr<ShaderResource> m_shader;
-};
-
-}
-
-#endif // StyleFetchedShader_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.cpp
index 2ec1c87de4e..f675fa5b0b5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.cpp
@@ -30,16 +30,16 @@
namespace WebCore {
-StyleGeneratedImage::StyleGeneratedImage(PassRefPtr<CSSImageGeneratorValue> value)
+StyleGeneratedImage::StyleGeneratedImage(PassRefPtrWillBeRawPtr<CSSImageGeneratorValue> value)
: m_imageGeneratorValue(value)
, m_fixedSize(m_imageGeneratorValue->isFixedSize())
{
m_isGeneratedImage = true;
}
-PassRefPtr<CSSValue> StyleGeneratedImage::cssValue() const
+PassRefPtrWillBeRawPtr<CSSValue> StyleGeneratedImage::cssValue() const
{
- return m_imageGeneratorValue;
+ return m_imageGeneratorValue.get();
}
LayoutSize StyleGeneratedImage::imageSize(const RenderObject* renderer, float multiplier) const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.h
index bf93af475da..219f47e241d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGeneratedImage.h
@@ -31,32 +31,33 @@ namespace WebCore {
class CSSValue;
class CSSImageGeneratorValue;
-class StyleGeneratedImage : public StyleImage {
+class StyleGeneratedImage FINAL : public StyleImage {
public:
static PassRefPtr<StyleGeneratedImage> create(CSSImageGeneratorValue* value)
{
return adoptRef(new StyleGeneratedImage(value));
}
- virtual WrappedImagePtr data() const { return m_imageGeneratorValue.get(); }
+ virtual WrappedImagePtr data() const OVERRIDE { return m_imageGeneratorValue.get(); }
- virtual PassRefPtr<CSSValue> cssValue() const;
+ virtual PassRefPtrWillBeRawPtr<CSSValue> cssValue() const OVERRIDE;
virtual LayoutSize imageSize(const RenderObject*, float multiplier) const OVERRIDE;
- virtual bool imageHasRelativeWidth() const { return !m_fixedSize; }
- virtual bool imageHasRelativeHeight() const { return !m_fixedSize; }
- virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
- virtual bool usesImageContainerSize() const { return !m_fixedSize; }
- virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize& containerSize, float) { m_containerSize = containerSize; }
- virtual void addClient(RenderObject*);
- virtual void removeClient(RenderObject*);
- virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
+ virtual bool imageHasRelativeWidth() const OVERRIDE { return !m_fixedSize; }
+ virtual bool imageHasRelativeHeight() const OVERRIDE { return !m_fixedSize; }
+ virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) OVERRIDE;
+ virtual bool usesImageContainerSize() const OVERRIDE { return !m_fixedSize; }
+ virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize& containerSize, float) OVERRIDE { m_containerSize = containerSize; }
+ virtual void addClient(RenderObject*) OVERRIDE;
+ virtual void removeClient(RenderObject*) OVERRIDE;
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const OVERRIDE;
virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE;
private:
- StyleGeneratedImage(PassRefPtr<CSSImageGeneratorValue>);
+ StyleGeneratedImage(PassRefPtrWillBeRawPtr<CSSImageGeneratorValue>);
- RefPtr<CSSImageGeneratorValue> m_imageGeneratorValue;
+ // FIXME: oilpan: change to member once StyleImage is moved to the oilpan heap
+ RefPtrWillBePersistent<CSSImageGeneratorValue> m_imageGeneratorValue;
IntSize m_containerSize;
bool m_fixedSize;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.cpp
index a3f8a348017..d323864b32b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.cpp
@@ -31,8 +31,8 @@
namespace WebCore {
StyleGridData::StyleGridData()
- : m_gridDefinitionColumns(RenderStyle::initialGridDefinitionColumns())
- , m_gridDefinitionRows(RenderStyle::initialGridDefinitionRows())
+ : m_gridTemplateColumns(RenderStyle::initialGridTemplateColumns())
+ , m_gridTemplateRows(RenderStyle::initialGridTemplateRows())
, m_namedGridColumnLines(RenderStyle::initialNamedGridColumnLines())
, m_namedGridRowLines(RenderStyle::initialNamedGridRowLines())
, m_orderedNamedGridColumnLines(RenderStyle::initialOrderedNamedGridColumnLines())
@@ -48,8 +48,8 @@ StyleGridData::StyleGridData()
StyleGridData::StyleGridData(const StyleGridData& o)
: RefCounted<StyleGridData>()
- , m_gridDefinitionColumns(o.m_gridDefinitionColumns)
- , m_gridDefinitionRows(o.m_gridDefinitionRows)
+ , m_gridTemplateColumns(o.m_gridTemplateColumns)
+ , m_gridTemplateRows(o.m_gridTemplateRows)
, m_namedGridColumnLines(o.m_namedGridColumnLines)
, m_namedGridRowLines(o.m_namedGridRowLines)
, m_orderedNamedGridColumnLines(o.m_orderedNamedGridColumnLines)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.h
index c7f5e5430e7..da14eaa2989 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleGridData.h
@@ -46,7 +46,7 @@ public:
bool operator==(const StyleGridData& o) const
{
- return m_gridDefinitionColumns == o.m_gridDefinitionColumns && m_gridDefinitionRows == o.m_gridDefinitionRows && m_gridAutoFlow == o.m_gridAutoFlow && m_gridAutoRows == o.m_gridAutoRows && m_gridAutoColumns == o.m_gridAutoColumns && m_namedGridColumnLines == o.m_namedGridColumnLines && m_namedGridRowLines == o.m_namedGridRowLines && m_orderedNamedGridColumnLines == o.m_orderedNamedGridColumnLines && m_orderedNamedGridRowLines == o.m_orderedNamedGridRowLines && m_namedGridArea == o.m_namedGridArea && m_namedGridArea == o.m_namedGridArea && m_namedGridAreaRowCount == o.m_namedGridAreaRowCount && m_namedGridAreaColumnCount == o.m_namedGridAreaColumnCount;
+ return m_gridTemplateColumns == o.m_gridTemplateColumns && m_gridTemplateRows == o.m_gridTemplateRows && m_gridAutoFlow == o.m_gridAutoFlow && m_gridAutoRows == o.m_gridAutoRows && m_gridAutoColumns == o.m_gridAutoColumns && m_namedGridColumnLines == o.m_namedGridColumnLines && m_namedGridRowLines == o.m_namedGridRowLines && m_orderedNamedGridColumnLines == o.m_orderedNamedGridColumnLines && m_orderedNamedGridRowLines == o.m_orderedNamedGridRowLines && m_namedGridArea == o.m_namedGridArea && m_namedGridArea == o.m_namedGridArea && m_namedGridAreaRowCount == o.m_namedGridAreaRowCount && m_namedGridAreaColumnCount == o.m_namedGridAreaColumnCount;
}
bool operator!=(const StyleGridData& o) const
@@ -54,8 +54,8 @@ public:
return !(*this == o);
}
- Vector<GridTrackSize> m_gridDefinitionColumns;
- Vector<GridTrackSize> m_gridDefinitionRows;
+ Vector<GridTrackSize> m_gridTemplateColumns;
+ Vector<GridTrackSize> m_gridTemplateRows;
NamedGridLinesMap m_namedGridColumnLines;
NamedGridLinesMap m_namedGridRowLines;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleImage.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleImage.h
index bca329ac568..b487e2c33ce 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleImage.h
@@ -49,9 +49,9 @@ public:
return data() == other.data();
}
- virtual PassRefPtr<CSSValue> cssValue() const = 0;
+ virtual PassRefPtrWillBeRawPtr<CSSValue> cssValue() const = 0;
- virtual bool canRender(const RenderObject*, float /*multiplier*/) const { return true; }
+ virtual bool canRender(const RenderObject&, float /*multiplier*/) const { return true; }
virtual bool isLoaded() const { return true; }
virtual bool errorOccurred() const { return false; }
virtual LayoutSize imageSize(const RenderObject*, float multiplier) const = 0;
@@ -73,16 +73,6 @@ public:
ALWAYS_INLINE bool isGeneratedImage() const { return m_isGeneratedImage; }
ALWAYS_INLINE bool isImageResourceSet() const { return m_isImageResourceSet; }
- static bool imagesEquivalent(const StyleImage* image1, const StyleImage* image2)
- {
- if (image1 != image2) {
- if (!image1 || !image2)
- return false;
- return *image1 == *image2;
- }
- return true;
- }
-
protected:
StyleImage()
: m_isImageResource(false)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.cpp
index 063e7d2286c..1b961aa497e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.cpp
@@ -32,6 +32,7 @@ StyleInheritedData::StyleInheritedData()
, line_height(RenderStyle::initialLineHeight())
, color(RenderStyle::initialColor())
, visitedLinkColor(RenderStyle::initialColor())
+ , textAutosizingMultiplier(1)
{
}
@@ -47,6 +48,7 @@ StyleInheritedData::StyleInheritedData(const StyleInheritedData& o)
, font(o.font)
, color(o.color)
, visitedLinkColor(o.visitedLinkColor)
+ , textAutosizingMultiplier(o.textAutosizingMultiplier)
{
}
@@ -57,6 +59,7 @@ bool StyleInheritedData::operator==(const StyleInheritedData& o) const
&& color == o.color
&& visitedLinkColor == o.visitedLinkColor
&& horizontal_border_spacing == o.horizontal_border_spacing
+ && textAutosizingMultiplier == o.textAutosizingMultiplier
&& vertical_border_spacing == o.vertical_border_spacing;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.h
index 11613a4abf7..7466a7c78fd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleInheritedData.h
@@ -56,6 +56,7 @@ public:
Font font;
Color color;
Color visitedLinkColor;
+ float textAutosizingMultiplier;
private:
StyleInheritedData();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.cpp
index 90897bb28bf..f7a7c5337e5 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.cpp
@@ -30,6 +30,7 @@ StyleMultiColData::StyleMultiColData()
: m_width(0)
, m_count(RenderStyle::initialColumnCount())
, m_gap(0)
+ , m_visitedLinkColumnRuleColor(StyleColor::currentColor())
, m_autoWidth(true)
, m_autoCount(true)
, m_normalGap(true)
@@ -38,8 +39,6 @@ StyleMultiColData::StyleMultiColData()
, m_breakBefore(RenderStyle::initialPageBreak())
, m_breakAfter(RenderStyle::initialPageBreak())
, m_breakInside(RenderStyle::initialPageBreak())
- , m_axis(RenderStyle::initialColumnAxis())
- , m_progression(RenderStyle::initialColumnProgression())
{
}
@@ -58,8 +57,6 @@ StyleMultiColData::StyleMultiColData(const StyleMultiColData& o)
, m_breakBefore(o.m_breakBefore)
, m_breakAfter(o.m_breakAfter)
, m_breakInside(o.m_breakInside)
- , m_axis(o.m_axis)
- , m_progression(o.m_progression)
{
}
@@ -69,8 +66,7 @@ bool StyleMultiColData::operator==(const StyleMultiColData& o) const
&& m_rule == o.m_rule && m_visitedLinkColumnRuleColor == o.m_visitedLinkColumnRuleColor && m_breakBefore == o.m_breakBefore
&& m_autoWidth == o.m_autoWidth && m_autoCount == o.m_autoCount && m_normalGap == o.m_normalGap
&& m_fill == o.m_fill && m_columnSpan == o.m_columnSpan
- && m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside
- && m_axis == o.m_axis && m_progression == o.m_progression;
+ && m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside;
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.h
index fcf66802667..27441be85cd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleMultiColData.h
@@ -57,7 +57,7 @@ public:
unsigned short m_count;
float m_gap;
BorderValue m_rule;
- Color m_visitedLinkColumnRuleColor;
+ StyleColor m_visitedLinkColumnRuleColor;
bool m_autoWidth : 1;
bool m_autoCount : 1;
@@ -67,8 +67,6 @@ public:
unsigned m_breakBefore : 2; // EPageBreak
unsigned m_breakAfter : 2; // EPageBreak
unsigned m_breakInside : 2; // EPageBreak
- unsigned m_axis : 2; // ColumnAxis
- unsigned m_progression : 2; // ColumnProgression
private:
StyleMultiColData();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingImage.h b/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingImage.h
index 4589f59a63d..d735175bb68 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingImage.h
@@ -39,32 +39,32 @@ namespace WebCore {
// style resolution, in order to avoid loading images that are not referenced by the final style.
// They should never exist in a RenderStyle after it has been returned from the style selector.
-class StylePendingImage : public StyleImage {
+class StylePendingImage FINAL : public StyleImage {
public:
static PassRefPtr<StylePendingImage> create(CSSValue* value) { return adoptRef(new StylePendingImage(value)); }
- virtual WrappedImagePtr data() const { return m_value; }
+ virtual WrappedImagePtr data() const OVERRIDE { return m_value; }
- virtual PassRefPtr<CSSValue> cssValue() const { return m_value; }
+ virtual PassRefPtrWillBeRawPtr<CSSValue> cssValue() const OVERRIDE { return m_value; }
CSSImageValue* cssImageValue() const { return m_value->isImageValue() ? toCSSImageValue(m_value) : 0; }
CSSImageGeneratorValue* cssImageGeneratorValue() const { return m_value->isImageGeneratorValue() ? toCSSImageGeneratorValue(m_value) : 0; }
CSSCursorImageValue* cssCursorImageValue() const { return m_value->isCursorImageValue() ? toCSSCursorImageValue(m_value) : 0; }
CSSImageSetValue* cssImageSetValue() const { return m_value->isImageSetValue() ? toCSSImageSetValue(m_value) : 0; }
virtual LayoutSize imageSize(const RenderObject*, float /*multiplier*/) const OVERRIDE { return LayoutSize(); }
- virtual bool imageHasRelativeWidth() const { return false; }
- virtual bool imageHasRelativeHeight() const { return false; }
- virtual void computeIntrinsicDimensions(const RenderObject*, Length& /* intrinsicWidth */ , Length& /* intrinsicHeight */, FloatSize& /* intrinsicRatio */) { }
- virtual bool usesImageContainerSize() const { return false; }
- 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 bool imageHasRelativeWidth() const OVERRIDE { return false; }
+ virtual bool imageHasRelativeHeight() const OVERRIDE { return false; }
+ virtual void computeIntrinsicDimensions(const RenderObject*, Length& /* intrinsicWidth */ , Length& /* intrinsicHeight */, FloatSize& /* intrinsicRatio */) OVERRIDE { }
+ virtual bool usesImageContainerSize() const OVERRIDE { return false; }
+ virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float) OVERRIDE { }
+ virtual void addClient(RenderObject*) OVERRIDE { }
+ virtual void removeClient(RenderObject*) OVERRIDE { }
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const OVERRIDE
{
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
- virtual bool knownToBeOpaque(const RenderObject*) const { return false; }
+ virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE { return false; }
private:
StylePendingImage(CSSValue* value)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingShader.h b/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingShader.h
deleted file mode 100644
index 1158e33a740..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StylePendingShader.h
+++ /dev/null
@@ -1,60 +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 StylePendingShader_h
-#define StylePendingShader_h
-
-#include "core/css/CSSShaderValue.h"
-#include "core/css/CSSValue.h"
-#include "core/rendering/style/StyleShader.h"
-#include "wtf/PassRefPtr.h"
-
-namespace WebCore {
-
-class WebKitCSSShaderValue;
-
-class StylePendingShader : public StyleShader {
-public:
- static PassRefPtr<StylePendingShader> create(CSSShaderValue* value) { return adoptRef(new StylePendingShader(value)); }
-
- virtual PassRefPtr<CSSValue> cssValue() const { return m_value; }
- CSSShaderValue* cssShaderValue() const { return m_value; }
-private:
- StylePendingShader(CSSShaderValue* value)
- : m_value(value)
- {
- m_isPendingShader = true;
- }
-
- CSSShaderValue* m_value; // Not retained; it owns us.
-};
-
-}
-
-#endif // StylePendingShader_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.cpp
index 1a1769c787f..741d22d7801 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.cpp
@@ -22,7 +22,9 @@
#include "config.h"
#include "core/rendering/style/StyleRareInheritedData.h"
-#include "core/rendering/style/CursorList.h"
+#include "core/rendering/style/AppliedTextDecoration.h"
+#include "core/rendering/style/CursorData.h"
+#include "core/rendering/style/DataEquivalency.h"
#include "core/rendering/style/QuotesData.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/style/RenderStyleConstants.h"
@@ -37,8 +39,8 @@ struct SameSizeAsStyleRareInheritedData : public RefCounted<SameSizeAsStyleRareI
float firstFloat;
Color colors[5];
void* ownPtrs[1];
- AtomicString atomicStrings[5];
- void* refPtrs[2];
+ AtomicString atomicStrings[4];
+ void* refPtrs[3];
Length lengths[1];
float secondFloat;
unsigned m_bitfields[2];
@@ -47,8 +49,6 @@ struct SameSizeAsStyleRareInheritedData : public RefCounted<SameSizeAsStyleRareI
short hyphenationShorts[3];
Color touchColors;
-
- void* variableDataRefs[1];
};
COMPILE_ASSERT(sizeof(StyleRareInheritedData) == sizeof(SameSizeAsStyleRareInheritedData), StyleRareInheritedData_should_bit_pack);
@@ -62,6 +62,12 @@ StyleRareInheritedData::StyleRareInheritedData()
, orphans(RenderStyle::initialOrphans())
, m_hasAutoWidows(true)
, m_hasAutoOrphans(true)
+ , m_textStrokeColorIsCurrentColor(true)
+ , m_textFillColorIsCurrentColor(true)
+ , m_textEmphasisColorIsCurrentColor(true)
+ , m_visitedLinkTextStrokeColorIsCurrentColor(true)
+ , m_visitedLinkTextFillColorIsCurrentColor(true)
+ , m_visitedLinkTextEmphasisColorIsCurrentColor(true)
, textSecurity(RenderStyle::initialTextSecurity())
, userModify(READ_ONLY)
, wordBreak(RenderStyle::initialWordBreak())
@@ -78,33 +84,31 @@ StyleRareInheritedData::StyleRareInheritedData()
, m_textJustify(RenderStyle::initialTextJustify())
, m_textOrientation(TextOrientationVerticalRight)
, m_textIndentLine(RenderStyle::initialTextIndentLine())
+ , m_textIndentType(RenderStyle::initialTextIndentLine())
, m_lineBoxContain(RenderStyle::initialLineBoxContain())
, m_imageRendering(RenderStyle::initialImageRendering())
- , m_lineSnap(RenderStyle::initialLineSnap())
- , m_lineAlign(RenderStyle::initialLineAlign())
, m_textUnderlinePosition(RenderStyle::initialTextUnderlinePosition())
, m_rubyPosition(RenderStyle::initialRubyPosition())
, m_touchActionDelay(RenderStyle::initialTouchActionDelay())
+ , m_subtreeWillChangeContents(false)
, hyphenationLimitBefore(-1)
, hyphenationLimitAfter(-1)
, hyphenationLimitLines(-1)
- , m_lineGrid(RenderStyle::initialLineGrid())
, m_tabSize(RenderStyle::initialTabSize())
, tapHighlightColor(RenderStyle::initialTapHighlightColor())
{
- m_variables.init();
}
StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
: RefCounted<StyleRareInheritedData>()
, listStyleImage(o.listStyleImage)
- , textStrokeColor(o.textStrokeColor)
+ , m_textStrokeColor(o.m_textStrokeColor)
, textStrokeWidth(o.textStrokeWidth)
- , textFillColor(o.textFillColor)
- , textEmphasisColor(o.textEmphasisColor)
- , visitedLinkTextStrokeColor(o.visitedLinkTextStrokeColor)
- , visitedLinkTextFillColor(o.visitedLinkTextFillColor)
- , visitedLinkTextEmphasisColor(o.visitedLinkTextEmphasisColor)
+ , m_textFillColor(o.m_textFillColor)
+ , m_textEmphasisColor(o.m_textEmphasisColor)
+ , m_visitedLinkTextStrokeColor(o.m_visitedLinkTextStrokeColor)
+ , m_visitedLinkTextFillColor(o.m_visitedLinkTextFillColor)
+ , m_visitedLinkTextEmphasisColor(o.m_visitedLinkTextEmphasisColor)
, textShadow(o.textShadow)
, highlight(o.highlight)
, cursorData(o.cursorData)
@@ -114,6 +118,12 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
, orphans(o.orphans)
, m_hasAutoWidows(o.m_hasAutoWidows)
, m_hasAutoOrphans(o.m_hasAutoOrphans)
+ , m_textStrokeColorIsCurrentColor(o.m_textStrokeColorIsCurrentColor)
+ , m_textFillColorIsCurrentColor(o.m_textFillColorIsCurrentColor)
+ , m_textEmphasisColorIsCurrentColor(o.m_textEmphasisColorIsCurrentColor)
+ , m_visitedLinkTextStrokeColorIsCurrentColor(o.m_visitedLinkTextStrokeColorIsCurrentColor)
+ , m_visitedLinkTextFillColorIsCurrentColor(o.m_visitedLinkTextFillColorIsCurrentColor)
+ , m_visitedLinkTextEmphasisColorIsCurrentColor(o.m_visitedLinkTextEmphasisColorIsCurrentColor)
, textSecurity(o.textSecurity)
, userModify(o.userModify)
, wordBreak(o.wordBreak)
@@ -130,23 +140,22 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
, m_textJustify(o.m_textJustify)
, m_textOrientation(o.m_textOrientation)
, m_textIndentLine(o.m_textIndentLine)
+ , m_textIndentType(o.m_textIndentType)
, m_lineBoxContain(o.m_lineBoxContain)
, m_imageRendering(o.m_imageRendering)
- , m_lineSnap(o.m_lineSnap)
- , m_lineAlign(o.m_lineAlign)
, m_textUnderlinePosition(o.m_textUnderlinePosition)
, m_rubyPosition(o.m_rubyPosition)
, m_touchActionDelay(o.m_touchActionDelay)
+ , m_subtreeWillChangeContents(o.m_subtreeWillChangeContents)
, hyphenationString(o.hyphenationString)
, hyphenationLimitBefore(o.hyphenationLimitBefore)
, hyphenationLimitAfter(o.hyphenationLimitAfter)
, hyphenationLimitLines(o.hyphenationLimitLines)
, locale(o.locale)
, textEmphasisCustomMark(o.textEmphasisCustomMark)
- , m_lineGrid(o.m_lineGrid)
, m_tabSize(o.m_tabSize)
, tapHighlightColor(o.tapHighlightColor)
- , m_variables(o.m_variables)
+ , appliedTextDecorations(o.appliedTextDecorations)
{
}
@@ -154,34 +163,31 @@ StyleRareInheritedData::~StyleRareInheritedData()
{
}
-static bool cursorDataEquivalent(const CursorList* c1, const CursorList* c2)
-{
- if (c1 == c2)
- return true;
- if ((!c1 && c2) || (c1 && !c2))
- return false;
- return (*c1 == *c2);
-}
-
bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
{
- return textStrokeColor == o.textStrokeColor
+ return m_textStrokeColor == o.m_textStrokeColor
&& textStrokeWidth == o.textStrokeWidth
- && textFillColor == o.textFillColor
- && textEmphasisColor == o.textEmphasisColor
- && visitedLinkTextStrokeColor == o.visitedLinkTextStrokeColor
- && visitedLinkTextFillColor == o.visitedLinkTextFillColor
- && visitedLinkTextEmphasisColor == o.visitedLinkTextEmphasisColor
+ && m_textFillColor == o.m_textFillColor
+ && m_textEmphasisColor == o.m_textEmphasisColor
+ && m_visitedLinkTextStrokeColor == o.m_visitedLinkTextStrokeColor
+ && m_visitedLinkTextFillColor == o.m_visitedLinkTextFillColor
+ && m_visitedLinkTextEmphasisColor == o.m_visitedLinkTextEmphasisColor
&& tapHighlightColor == o.tapHighlightColor
&& shadowDataEquivalent(o)
&& highlight == o.highlight
- && cursorDataEquivalent(cursorData.get(), o.cursorData.get())
+ && dataEquivalent(cursorData.get(), o.cursorData.get())
&& indent == o.indent
&& m_effectiveZoom == o.m_effectiveZoom
&& widows == o.widows
&& orphans == o.orphans
&& m_hasAutoWidows == o.m_hasAutoWidows
&& m_hasAutoOrphans == o.m_hasAutoOrphans
+ && m_textStrokeColorIsCurrentColor == o.m_textStrokeColorIsCurrentColor
+ && m_textFillColorIsCurrentColor == o.m_textFillColorIsCurrentColor
+ && m_textEmphasisColorIsCurrentColor == o.m_textEmphasisColorIsCurrentColor
+ && m_visitedLinkTextStrokeColorIsCurrentColor == o.m_visitedLinkTextStrokeColorIsCurrentColor
+ && m_visitedLinkTextFillColorIsCurrentColor == o.m_visitedLinkTextFillColorIsCurrentColor
+ && m_visitedLinkTextEmphasisColorIsCurrentColor == o.m_visitedLinkTextEmphasisColorIsCurrentColor
&& textSecurity == o.textSecurity
&& userModify == o.userModify
&& wordBreak == o.wordBreak
@@ -202,29 +208,29 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& m_textJustify == o.m_textJustify
&& m_textOrientation == o.m_textOrientation
&& m_textIndentLine == o.m_textIndentLine
+ && m_textIndentType == o.m_textIndentType
&& m_lineBoxContain == o.m_lineBoxContain
+ && m_subtreeWillChangeContents == o.m_subtreeWillChangeContents
&& hyphenationString == o.hyphenationString
&& locale == o.locale
&& textEmphasisCustomMark == o.textEmphasisCustomMark
- && QuotesData::equals(quotes.get(), o.quotes.get())
+ && quotesDataEquivalent(o)
&& m_tabSize == o.m_tabSize
- && m_lineGrid == o.m_lineGrid
&& m_imageRendering == o.m_imageRendering
&& m_textUnderlinePosition == o.m_textUnderlinePosition
&& m_rubyPosition == o.m_rubyPosition
- && m_lineSnap == o.m_lineSnap
- && m_variables == o.m_variables
- && m_lineAlign == o.m_lineAlign
- && StyleImage::imagesEquivalent(listStyleImage.get(), o.listStyleImage.get());
+ && dataEquivalent(listStyleImage.get(), o.listStyleImage.get())
+ && dataEquivalent(appliedTextDecorations, o.appliedTextDecorations);
}
bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const
{
- if ((!textShadow && o.textShadow) || (textShadow && !o.textShadow))
- return false;
- if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
- return false;
- return true;
+ return dataEquivalent(textShadow.get(), o.textShadow.get());
+}
+
+bool StyleRareInheritedData::quotesDataEquivalent(const StyleRareInheritedData& o) const
+{
+ return dataEquivalent(quotes, o.quotes);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.h
index 11d3c4b0f52..4dd0ba554a2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareInheritedData.h
@@ -25,21 +25,26 @@
#ifndef StyleRareInheritedData_h
#define StyleRareInheritedData_h
+#include "core/css/StyleColor.h"
#include "core/rendering/style/DataRef.h"
-#include "core/rendering/style/StyleVariableData.h"
#include "platform/Length.h"
#include "platform/graphics/Color.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
+#include "wtf/RefVector.h"
#include "wtf/text/AtomicString.h"
namespace WebCore {
-class CursorList;
+class AppliedTextDecoration;
+class CursorData;
class QuotesData;
class ShadowList;
class StyleImage;
+typedef RefVector<AppliedTextDecoration> AppliedTextDecorationList;
+typedef RefVector<CursorData> CursorList;
+
// This struct is for rarely used inherited CSS3, CSS2, and WebKit-specific properties.
// By grouping them together, we save space, and only allocate this object when someone
// actually uses one of these properties.
@@ -55,17 +60,32 @@ public:
return !(*this == o);
}
bool shadowDataEquivalent(const StyleRareInheritedData&) const;
+ bool quotesDataEquivalent(const StyleRareInheritedData&) const;
RefPtr<StyleImage> listStyleImage;
- Color textStrokeColor;
+ StyleColor textStrokeColor() const { return m_textStrokeColorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_textStrokeColor); }
+ StyleColor textFillColor() const { return m_textFillColorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_textFillColor); }
+ StyleColor textEmphasisColor() const { return m_textEmphasisColorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_textEmphasisColor); }
+ StyleColor visitedLinkTextStrokeColor() const { return m_visitedLinkTextStrokeColorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_visitedLinkTextStrokeColor); }
+ StyleColor visitedLinkTextFillColor() const { return m_visitedLinkTextFillColorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_visitedLinkTextFillColor); }
+ StyleColor visitedLinkTextEmphasisColor() const { return m_visitedLinkTextEmphasisColorIsCurrentColor ? StyleColor::currentColor() : StyleColor(m_visitedLinkTextEmphasisColor); }
+
+ void setTextStrokeColor(const StyleColor& color) { m_textStrokeColor = color.resolve(Color()); m_textStrokeColorIsCurrentColor = color.isCurrentColor(); }
+ void setTextFillColor(const StyleColor& color) { m_textFillColor = color.resolve(Color()); m_textFillColorIsCurrentColor = color.isCurrentColor(); }
+ void setTextEmphasisColor(const StyleColor& color) { m_textEmphasisColor = color.resolve(Color()); m_textEmphasisColorIsCurrentColor = color.isCurrentColor(); }
+ void setVisitedLinkTextStrokeColor(const StyleColor& color) { m_visitedLinkTextStrokeColor = color.resolve(Color()); m_visitedLinkTextStrokeColorIsCurrentColor = color.isCurrentColor(); }
+ void setVisitedLinkTextFillColor(const StyleColor& color) { m_visitedLinkTextFillColor = color.resolve(Color()); m_visitedLinkTextFillColorIsCurrentColor = color.isCurrentColor(); }
+ void setVisitedLinkTextEmphasisColor(const StyleColor& color) { m_visitedLinkTextEmphasisColor = color.resolve(Color()); m_visitedLinkTextEmphasisColorIsCurrentColor = color.isCurrentColor(); }
+
+ Color m_textStrokeColor;
float textStrokeWidth;
- Color textFillColor;
- Color textEmphasisColor;
+ Color m_textFillColor;
+ Color m_textEmphasisColor;
- Color visitedLinkTextStrokeColor;
- Color visitedLinkTextFillColor;
- Color visitedLinkTextEmphasisColor;
+ Color m_visitedLinkTextStrokeColor;
+ Color m_visitedLinkTextFillColor;
+ Color m_visitedLinkTextEmphasisColor;
RefPtr<ShadowList> textShadow; // Our text shadow information for shadowed text drawing.
AtomicString highlight; // Apple-specific extension for custom highlight rendering.
@@ -80,6 +100,13 @@ public:
unsigned m_hasAutoWidows : 1;
unsigned m_hasAutoOrphans : 1;
+ unsigned m_textStrokeColorIsCurrentColor : 1;
+ unsigned m_textFillColorIsCurrentColor : 1;
+ unsigned m_textEmphasisColorIsCurrentColor : 1;
+ unsigned m_visitedLinkTextStrokeColorIsCurrentColor : 1;
+ unsigned m_visitedLinkTextFillColorIsCurrentColor : 1;
+ unsigned m_visitedLinkTextEmphasisColorIsCurrentColor : 1;
+
unsigned textSecurity : 2; // ETextSecurity
unsigned userModify : 2; // EUserModify (editing)
unsigned wordBreak : 2; // EWordBreak
@@ -96,15 +123,18 @@ public:
unsigned m_textJustify : 2; // TextJustify
unsigned m_textOrientation : 2; // TextOrientation
unsigned m_textIndentLine : 1; // TextIndentEachLine
+ unsigned m_textIndentType : 1; // TextIndentHanging
unsigned m_lineBoxContain: 7; // LineBoxContain
// CSS Image Values Level 3
unsigned m_imageRendering : 2; // EImageRendering
- unsigned m_lineSnap : 2; // LineSnap
- unsigned m_lineAlign : 1; // LineAlign
unsigned m_textUnderlinePosition : 2; // TextUnderlinePosition
unsigned m_rubyPosition : 1; // RubyPosition
unsigned m_touchActionDelay : 1; // TouchActionDelay
+ // Though will-change is not itself an inherited property, the intent
+ // expressed by 'will-change: contents' includes descendants.
+ unsigned m_subtreeWillChangeContents : 1;
+
AtomicString hyphenationString;
short hyphenationLimitBefore;
short hyphenationLimitAfter;
@@ -115,12 +145,11 @@ public:
AtomicString textEmphasisCustomMark;
RefPtr<QuotesData> quotes;
- AtomicString m_lineGrid;
unsigned m_tabSize;
Color tapHighlightColor;
- DataRef<StyleVariableData> m_variables;
+ RefPtr<AppliedTextDecorationList> appliedTextDecorations;
private:
StyleRareInheritedData();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.cpp
index 2d312788ec6..165edc705a4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.cpp
@@ -23,6 +23,7 @@
#include "core/rendering/style/StyleRareNonInheritedData.h"
#include "core/rendering/style/ContentData.h"
+#include "core/rendering/style/DataEquivalency.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/style/ShadowList.h"
#include "core/rendering/style/StyleFilterData.h"
@@ -42,27 +43,28 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, m_draggableRegionMode(DraggableRegionNone)
, m_mask(MaskFillLayer, true)
, m_pageSize()
- , m_shapeInside(RenderStyle::initialShapeInside())
, m_shapeOutside(RenderStyle::initialShapeOutside())
, m_shapeMargin(RenderStyle::initialShapeMargin())
- , m_shapePadding(RenderStyle::initialShapePadding())
, m_shapeImageThreshold(RenderStyle::initialShapeImageThreshold())
, m_clipPath(RenderStyle::initialClipPath())
+ , m_textDecorationColor(StyleColor::currentColor())
+ , m_visitedLinkTextDecorationColor(StyleColor::currentColor())
, m_visitedLinkBackgroundColor(RenderStyle::initialBackgroundColor())
+ , m_visitedLinkOutlineColor(StyleColor::currentColor())
+ , m_visitedLinkBorderLeftColor(StyleColor::currentColor())
+ , m_visitedLinkBorderRightColor(StyleColor::currentColor())
+ , m_visitedLinkBorderTopColor(StyleColor::currentColor())
+ , m_visitedLinkBorderBottomColor(StyleColor::currentColor())
, m_order(RenderStyle::initialOrder())
, m_objectPosition(RenderStyle::initialObjectPosition())
- , m_flowThread(RenderStyle::initialFlowThread())
- , m_regionThread(RenderStyle::initialRegionThread())
- , m_regionFragment(RenderStyle::initialRegionFragment())
- , m_regionBreakAfter(RenderStyle::initialPageBreak())
- , m_regionBreakBefore(RenderStyle::initialPageBreak())
- , m_regionBreakInside(RenderStyle::initialPageBreak())
, m_pageSizeType(PAGE_SIZE_AUTO)
, m_transformStyle3D(RenderStyle::initialTransformStyle3D())
, m_backfaceVisibility(RenderStyle::initialBackfaceVisibility())
, m_alignContent(RenderStyle::initialAlignContent())
, m_alignItems(RenderStyle::initialAlignItems())
+ , m_alignItemsOverflowAlignment(RenderStyle::initialAlignItemsOverflowAlignment())
, m_alignSelf(RenderStyle::initialAlignSelf())
+ , m_alignSelfOverflowAlignment(RenderStyle::initialAlignSelfOverflowAlignment())
, m_justifyContent(RenderStyle::initialJustifyContent())
, userDrag(RenderStyle::initialUserDrag())
, textOverflow(RenderStyle::initialTextOverflow())
@@ -74,12 +76,21 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, m_textDecorationStyle(RenderStyle::initialTextDecorationStyle())
, m_wrapFlow(RenderStyle::initialWrapFlow())
, m_wrapThrough(RenderStyle::initialWrapThrough())
- , m_runningAcceleratedAnimation(false)
+ , m_hasCurrentOpacityAnimation(false)
+ , m_hasCurrentTransformAnimation(false)
+ , m_hasCurrentFilterAnimation(false)
+ , m_runningOpacityAnimationOnCompositor(false)
+ , m_runningTransformAnimationOnCompositor(false)
+ , m_runningFilterAnimationOnCompositor(false)
, m_hasAspectRatio(false)
, m_effectiveBlendMode(RenderStyle::initialBlendMode())
, m_touchAction(RenderStyle::initialTouchAction())
, m_objectFit(RenderStyle::initialObjectFit())
, m_isolation(RenderStyle::initialIsolation())
+ , m_justifySelf(RenderStyle::initialJustifySelf())
+ , m_justifySelfOverflowAlignment(RenderStyle::initialJustifySelfOverflowAlignment())
+ , m_scrollBehavior(RenderStyle::initialScrollBehavior())
+ , m_requiresAcceleratedCompositingForExternalReasons(false)
{
m_maskBoxImage.setMaskDefaults();
}
@@ -99,6 +110,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_marquee(o.m_marquee)
, m_multiCol(o.m_multiCol)
, m_transform(o.m_transform)
+ , m_willChange(o.m_willChange)
, m_filter(o.m_filter)
, m_grid(o.m_grid)
, m_gridItem(o.m_gridItem)
@@ -106,15 +118,13 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_counterDirectives(o.m_counterDirectives ? clone(*o.m_counterDirectives) : nullptr)
, m_boxShadow(o.m_boxShadow)
, m_boxReflect(o.m_boxReflect)
- , m_animations(o.m_animations ? adoptPtr(new CSSAnimationDataList(*o.m_animations)) : nullptr)
- , m_transitions(o.m_transitions ? adoptPtr(new CSSAnimationDataList(*o.m_transitions)) : nullptr)
+ , m_animations(o.m_animations ? CSSAnimationData::create(*o.m_animations) : nullptr)
+ , m_transitions(o.m_transitions ? CSSTransitionData::create(*o.m_transitions) : nullptr)
, m_mask(o.m_mask)
, m_maskBoxImage(o.m_maskBoxImage)
, m_pageSize(o.m_pageSize)
- , m_shapeInside(o.m_shapeInside)
, m_shapeOutside(o.m_shapeOutside)
, m_shapeMargin(o.m_shapeMargin)
- , m_shapePadding(o.m_shapePadding)
, m_shapeImageThreshold(o.m_shapeImageThreshold)
, m_clipPath(o.m_clipPath)
, m_textDecorationColor(o.m_textDecorationColor)
@@ -127,18 +137,14 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_visitedLinkBorderBottomColor(o.m_visitedLinkBorderBottomColor)
, m_order(o.m_order)
, m_objectPosition(o.m_objectPosition)
- , m_flowThread(o.m_flowThread)
- , m_regionThread(o.m_regionThread)
- , m_regionFragment(o.m_regionFragment)
- , m_regionBreakAfter(o.m_regionBreakAfter)
- , m_regionBreakBefore(o.m_regionBreakBefore)
- , m_regionBreakInside(o.m_regionBreakInside)
, m_pageSizeType(o.m_pageSizeType)
, m_transformStyle3D(o.m_transformStyle3D)
, m_backfaceVisibility(o.m_backfaceVisibility)
, m_alignContent(o.m_alignContent)
, m_alignItems(o.m_alignItems)
+ , m_alignItemsOverflowAlignment(o.m_alignItemsOverflowAlignment)
, m_alignSelf(o.m_alignSelf)
+ , m_alignSelfOverflowAlignment(o.m_alignSelfOverflowAlignment)
, m_justifyContent(o.m_justifyContent)
, userDrag(o.userDrag)
, textOverflow(o.textOverflow)
@@ -150,12 +156,21 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_textDecorationStyle(o.m_textDecorationStyle)
, m_wrapFlow(o.m_wrapFlow)
, m_wrapThrough(o.m_wrapThrough)
- , m_runningAcceleratedAnimation(o.m_runningAcceleratedAnimation)
+ , m_hasCurrentOpacityAnimation(o.m_hasCurrentOpacityAnimation)
+ , m_hasCurrentTransformAnimation(o.m_hasCurrentTransformAnimation)
+ , m_hasCurrentFilterAnimation(o.m_hasCurrentFilterAnimation)
+ , m_runningOpacityAnimationOnCompositor(o.m_runningOpacityAnimationOnCompositor)
+ , m_runningTransformAnimationOnCompositor(o.m_runningTransformAnimationOnCompositor)
+ , m_runningFilterAnimationOnCompositor(o.m_runningFilterAnimationOnCompositor)
, m_hasAspectRatio(o.m_hasAspectRatio)
, m_effectiveBlendMode(o.m_effectiveBlendMode)
, m_touchAction(o.m_touchAction)
, m_objectFit(o.m_objectFit)
, m_isolation(o.m_isolation)
+ , m_justifySelf(o.m_justifySelf)
+ , m_justifySelfOverflowAlignment(o.m_justifySelfOverflowAlignment)
+ , m_scrollBehavior(o.m_scrollBehavior)
+ , m_requiresAcceleratedCompositingForExternalReasons(o.m_requiresAcceleratedCompositingForExternalReasons)
{
}
@@ -181,6 +196,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_marquee == o.m_marquee
&& m_multiCol == o.m_multiCol
&& m_transform == o.m_transform
+ && m_willChange == o.m_willChange
&& m_filter == o.m_filter
&& m_grid == o.m_grid
&& m_gridItem == o.m_gridItem
@@ -193,10 +209,8 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_mask == o.m_mask
&& m_maskBoxImage == o.m_maskBoxImage
&& m_pageSize == o.m_pageSize
- && m_shapeInside == o.m_shapeInside
&& m_shapeOutside == o.m_shapeOutside
&& m_shapeMargin == o.m_shapeMargin
- && m_shapePadding == o.m_shapePadding
&& m_shapeImageThreshold == o.m_shapeImageThreshold
&& m_clipPath == o.m_clipPath
&& m_textDecorationColor == o.m_textDecorationColor
@@ -210,18 +224,14 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_order == o.m_order
&& m_objectPosition == o.m_objectPosition
&& m_callbackSelectors == o.m_callbackSelectors
- && m_flowThread == o.m_flowThread
- && m_regionThread == o.m_regionThread
- && m_regionFragment == o.m_regionFragment
- && m_regionBreakAfter == o.m_regionBreakAfter
- && m_regionBreakBefore == o.m_regionBreakBefore
- && m_regionBreakInside == o.m_regionBreakInside
&& m_pageSizeType == o.m_pageSizeType
&& m_transformStyle3D == o.m_transformStyle3D
&& m_backfaceVisibility == o.m_backfaceVisibility
&& m_alignContent == o.m_alignContent
&& m_alignItems == o.m_alignItems
+ && m_alignItemsOverflowAlignment == o.m_alignItemsOverflowAlignment
&& m_alignSelf == o.m_alignSelf
+ && m_alignSelfOverflowAlignment == o.m_alignSelfOverflowAlignment
&& m_justifyContent == o.m_justifyContent
&& userDrag == o.userDrag
&& textOverflow == o.textOverflow
@@ -233,12 +243,18 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_textDecorationStyle == o.m_textDecorationStyle
&& m_wrapFlow == o.m_wrapFlow
&& m_wrapThrough == o.m_wrapThrough
- && !m_runningAcceleratedAnimation && !o.m_runningAcceleratedAnimation
+ && m_hasCurrentOpacityAnimation == o.m_hasCurrentOpacityAnimation
+ && m_hasCurrentTransformAnimation == o.m_hasCurrentTransformAnimation
+ && m_hasCurrentFilterAnimation == o.m_hasCurrentFilterAnimation
&& m_effectiveBlendMode == o.m_effectiveBlendMode
&& m_hasAspectRatio == o.m_hasAspectRatio
&& m_touchAction == o.m_touchAction
&& m_objectFit == o.m_objectFit
- && m_isolation == o.m_isolation;
+ && m_isolation == o.m_isolation
+ && m_justifySelf == o.m_justifySelf
+ && m_justifySelfOverflowAlignment == o.m_justifySelfOverflowAlignment
+ && m_scrollBehavior == o.m_scrollBehavior
+ && m_requiresAcceleratedCompositingForExternalReasons == o.m_requiresAcceleratedCompositingForExternalReasons;
}
bool StyleRareNonInheritedData::contentDataEquivalent(const StyleRareNonInheritedData& o) const
@@ -256,50 +272,35 @@ bool StyleRareNonInheritedData::contentDataEquivalent(const StyleRareNonInherite
bool StyleRareNonInheritedData::counterDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if (m_counterDirectives.get() == o.m_counterDirectives.get())
- return true;
-
- if (m_counterDirectives && o.m_counterDirectives && *m_counterDirectives == *o.m_counterDirectives)
- return true;
-
- return false;
+ return dataEquivalent(m_counterDirectives, o.m_counterDirectives);
}
bool StyleRareNonInheritedData::shadowDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if ((!m_boxShadow && o.m_boxShadow) || (m_boxShadow && !o.m_boxShadow))
- return false;
- if (m_boxShadow && o.m_boxShadow && (*m_boxShadow != *o.m_boxShadow))
- return false;
- return true;
+ return dataEquivalent(m_boxShadow, o.m_boxShadow);
}
bool StyleRareNonInheritedData::reflectionDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if (m_boxReflect != o.m_boxReflect) {
- if (!m_boxReflect || !o.m_boxReflect)
- return false;
- return *m_boxReflect == *o.m_boxReflect;
- }
- return true;
+ return dataEquivalent(m_boxReflect, o.m_boxReflect);
}
bool StyleRareNonInheritedData::animationDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if ((!m_animations && o.m_animations) || (m_animations && !o.m_animations))
- return false;
- if (m_animations && o.m_animations && (*m_animations != *o.m_animations))
+ if (!m_animations && !o.m_animations)
+ return true;
+ if (!m_animations || !o.m_animations)
return false;
- return true;
+ return m_animations->animationsMatchForStyleRecalc(*o.m_animations);
}
bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if ((!m_transitions && o.m_transitions) || (m_transitions && !o.m_transitions))
- return false;
- if (m_transitions && o.m_transitions && (*m_transitions != *o.m_transitions))
+ if (!m_transitions && !o.m_transitions)
+ return true;
+ if (!m_transitions || !o.m_transitions)
return false;
- return true;
+ return m_transitions->transitionsMatchForStyleRecalc(*o.m_transitions);
}
bool StyleRareNonInheritedData::hasFilters() const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.h
index 9ce04870219..f23461abab3 100755..100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleRareNonInheritedData.h
@@ -25,6 +25,7 @@
#ifndef StyleRareNonInheritedData_h
#define StyleRareNonInheritedData_h
+#include "core/css/StyleColor.h"
#include "core/rendering/ClipPathOperation.h"
#include "core/rendering/style/BasicShapes.h"
#include "core/rendering/style/CounterDirectives.h"
@@ -43,7 +44,9 @@
namespace WebCore {
class ContentData;
-class CSSAnimationDataList;
+class CSSAnimationData;
+class CSSTransitionData;
+class LengthSize;
class ShadowList;
class StyleDeprecatedFlexibleBoxData;
class StyleFilterData;
@@ -53,10 +56,8 @@ class StyleGridItemData;
class StyleMarqueeData;
class StyleMultiColData;
class StyleReflection;
-class StyleResolver;
class StyleTransformData;
-
-struct LengthSize;
+class StyleWillChangeData;
// Page size type.
// StyleRareNonInheritedData::m_pageSize is meaningful only when
@@ -106,6 +107,7 @@ public:
DataRef<StyleMarqueeData> m_marquee; // Marquee properties
DataRef<StyleMultiColData> m_multiCol; // CSS3 multicol properties
DataRef<StyleTransformData> m_transform; // Transform properties (rotate, scale, skew, etc.)
+ DataRef<StyleWillChangeData> m_willChange; // CSS Will Change
DataRef<StyleFilterData> m_filter; // Filter operations (url, sepia, blur, etc.)
@@ -119,30 +121,28 @@ public:
RefPtr<StyleReflection> m_boxReflect;
- OwnPtr<CSSAnimationDataList> m_animations;
- OwnPtr<CSSAnimationDataList> m_transitions;
+ OwnPtrWillBePersistent<CSSAnimationData> m_animations;
+ OwnPtrWillBePersistent<CSSTransitionData> m_transitions;
FillLayer m_mask;
NinePieceImage m_maskBoxImage;
LengthSize m_pageSize;
- RefPtr<ShapeValue> m_shapeInside;
RefPtr<ShapeValue> m_shapeOutside;
Length m_shapeMargin;
- Length m_shapePadding;
float m_shapeImageThreshold;
RefPtr<ClipPathOperation> m_clipPath;
- Color m_textDecorationColor;
- Color m_visitedLinkTextDecorationColor;
- Color m_visitedLinkBackgroundColor;
- Color m_visitedLinkOutlineColor;
- Color m_visitedLinkBorderLeftColor;
- Color m_visitedLinkBorderRightColor;
- Color m_visitedLinkBorderTopColor;
- Color m_visitedLinkBorderBottomColor;
+ StyleColor m_textDecorationColor;
+ StyleColor m_visitedLinkTextDecorationColor;
+ StyleColor m_visitedLinkBackgroundColor;
+ StyleColor m_visitedLinkOutlineColor;
+ StyleColor m_visitedLinkBorderLeftColor;
+ StyleColor m_visitedLinkBorderRightColor;
+ StyleColor m_visitedLinkBorderTopColor;
+ StyleColor m_visitedLinkBorderBottomColor;
int m_order;
@@ -150,21 +150,15 @@ public:
Vector<String> m_callbackSelectors;
- AtomicString m_flowThread;
- AtomicString m_regionThread;
- unsigned m_regionFragment : 1; // RegionFragment
-
- unsigned m_regionBreakAfter : 2; // EPageBreak
- unsigned m_regionBreakBefore : 2; // EPageBreak
- unsigned m_regionBreakInside : 2; // EPageBreak
-
unsigned m_pageSizeType : 2; // PageSizeType
unsigned m_transformStyle3D : 1; // ETransformStyle3D
unsigned m_backfaceVisibility : 1; // EBackfaceVisibility
unsigned m_alignContent : 3; // EAlignContent
- unsigned m_alignItems : 3; // EAlignItems
- unsigned m_alignSelf : 3; // EAlignItems
+ unsigned m_alignItems : 4; // ItemPosition
+ unsigned m_alignItemsOverflowAlignment : 2; // OverflowAlignment
+ unsigned m_alignSelf : 4; // ItemPosition
+ unsigned m_alignSelfOverflowAlignment : 2; // OverflowAlignment
unsigned m_justifyContent : 3; // EJustifyContent
unsigned userDrag : 2; // EUserDrag
@@ -179,7 +173,12 @@ public:
unsigned m_wrapFlow: 3; // WrapFlow
unsigned m_wrapThrough: 1; // WrapThrough
- unsigned m_runningAcceleratedAnimation : 1;
+ unsigned m_hasCurrentOpacityAnimation : 1;
+ unsigned m_hasCurrentTransformAnimation : 1;
+ unsigned m_hasCurrentFilterAnimation : 1;
+ unsigned m_runningOpacityAnimationOnCompositor : 1;
+ unsigned m_runningTransformAnimationOnCompositor : 1;
+ unsigned m_runningFilterAnimationOnCompositor : 1;
unsigned m_hasAspectRatio : 1; // Whether or not an aspect ratio has been specified.
@@ -191,6 +190,19 @@ public:
unsigned m_isolation : 1; // Isolation
+ unsigned m_justifySelf : 4; // ItemPosition
+ unsigned m_justifySelfOverflowAlignment : 2; // OverflowAlignment
+
+ // ScrollBehavior. 'scroll-behavior' has 2 accepted values, but ScrollBehavior has a third
+ // value (that can only be specified using CSSOM scroll APIs) so 2 bits are needed.
+ unsigned m_scrollBehavior: 2;
+
+ // Plugins require accelerated compositing for reasons external to blink.
+ // In which case, we need to update the RenderStyle on the RenderEmbeddedObject,
+ // so store this bit so that the style actually changes when the plugin
+ // becomes composited.
+ unsigned m_requiresAcceleratedCompositingForExternalReasons: 1;
+
private:
StyleRareNonInheritedData();
StyleRareNonInheritedData(const StyleRareNonInheritedData&);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleShader.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleShader.h
deleted file mode 100644
index c5927e67591..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleShader.h
+++ /dev/null
@@ -1,64 +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 StyleShader_h
-#define StyleShader_h
-
-#include "wtf/RefCounted.h"
-
-namespace WebCore {
-
-class ShaderResource;
-class CSSValue;
-
-class StyleShader : public RefCounted<StyleShader> {
-public:
- virtual ~StyleShader() { }
-
- ALWAYS_INLINE bool isShaderResource() const { return m_isShaderResource; }
- ALWAYS_INLINE bool isPendingShader() const { return m_isPendingShader; }
-
- virtual PassRefPtr<CSSValue> cssValue() const = 0;
-
- virtual ShaderResource* resource() const { return 0; }
-
-protected:
- StyleShader()
- : m_isShaderResource(false)
- , m_isPendingShader(false)
- {
- }
- bool m_isShaderResource : 1;
- bool m_isPendingShader : 1;
-};
-
-}
-
-
-#endif // StyleShader_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleVariableData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleVariableData.h
deleted file mode 100644
index 23429f19c2e..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleVariableData.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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 StyleVariableData_h
-#define StyleVariableData_h
-
-#include "wtf/Forward.h"
-#include "wtf/HashMap.h"
-#include "wtf/RefCounted.h"
-#include "wtf/text/AtomicStringHash.h"
-
-namespace WebCore {
-
-class CursorList;
-class QuotesData;
-class ShadowData;
-
-class StyleVariableData : public RefCounted<StyleVariableData> {
-public:
- static PassRefPtr<StyleVariableData> create() { return adoptRef(new StyleVariableData()); }
- PassRefPtr<StyleVariableData> copy() const { return adoptRef(new StyleVariableData(*this)); }
-
- bool operator==(const StyleVariableData& other) const { return other.m_data == m_data; }
- bool operator!=(const StyleVariableData& other) const { return !(*this == other); }
-
- void setVariable(const AtomicString& name, const String& value) { m_data.set(name, value); }
-
- HashMap<AtomicString, String> m_data;
-private:
- explicit StyleVariableData() : RefCounted<StyleVariableData>() { }
- StyleVariableData(const StyleVariableData& other) : RefCounted<StyleVariableData>(), m_data(HashMap<AtomicString, String>(other.m_data)) { }
-};
-
-} // namespace WebCore
-
-#endif /* StyleVariableData_h */
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.cpp
index db87122431b..e2774374bef 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.cpp
@@ -29,7 +29,6 @@ namespace WebCore {
StyleVisualData::StyleVisualData()
: hasClip(false)
, textDecoration(RenderStyle::initialTextDecoration())
- , m_textAutosizingMultiplier(1)
, m_zoom(RenderStyle::initialZoom())
{
}
@@ -43,7 +42,6 @@ StyleVisualData::StyleVisualData(const StyleVisualData& o)
, clip(o.clip)
, hasClip(o.hasClip)
, textDecoration(o.textDecoration)
- , m_textAutosizingMultiplier(o.m_textAutosizingMultiplier)
, m_zoom(RenderStyle::initialZoom())
{
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.h
index 2657b93ceec..ed79ea1aece 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleVisualData.h
@@ -43,7 +43,6 @@ public:
return clip == o.clip
&& hasClip == o.hasClip
&& textDecoration == o.textDecoration
- && m_textAutosizingMultiplier == o.m_textAutosizingMultiplier
&& m_zoom == o.m_zoom;
}
bool operator!=(const StyleVisualData& o) const { return !(*this == o); }
@@ -52,7 +51,6 @@ public:
bool hasClip : 1;
unsigned textDecoration : TextDecorationBits; // Text decorations defined *only* by this element.
- float m_textAutosizingMultiplier;
float m_zoom;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.cpp b/chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.cpp
new file mode 100644
index 00000000000..7cd2bcbf0aa
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.cpp
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/rendering/style/StyleWillChangeData.h"
+
+namespace WebCore {
+
+StyleWillChangeData::StyleWillChangeData()
+ : m_contents(false)
+ , m_scrollPosition(false)
+{
+}
+
+StyleWillChangeData::StyleWillChangeData(const StyleWillChangeData& o)
+ : RefCounted<StyleWillChangeData>()
+ , m_properties(o.m_properties)
+ , m_contents(o.m_contents)
+ , m_scrollPosition(o.m_scrollPosition)
+{
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.h b/chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.h
new file mode 100644
index 00000000000..9a9b6e76212
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/rendering/style/StyleWillChangeData.h
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef StyleWillChangeData_h
+#define StyleWillChangeData_h
+
+#include "core/CSSPropertyNames.h"
+#include "core/CSSValueKeywords.h"
+#include "wtf/PassRefPtr.h"
+#include "wtf/RefCounted.h"
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+class StyleWillChangeData : public RefCounted<StyleWillChangeData> {
+public:
+ static PassRefPtr<StyleWillChangeData> create() { return adoptRef(new StyleWillChangeData); }
+ PassRefPtr<StyleWillChangeData> copy() const { return adoptRef(new StyleWillChangeData(*this)); }
+
+ bool operator==(const StyleWillChangeData& o) const
+ {
+ return m_properties == o.m_properties && m_contents == o.m_contents && m_scrollPosition == o.m_scrollPosition;
+ }
+
+ bool operator!=(const StyleWillChangeData& o) const
+ {
+ return !(*this == o);
+ }
+
+ Vector<CSSPropertyID> m_properties;
+ unsigned m_contents : 1;
+ unsigned m_scrollPosition : 1;
+
+private:
+ StyleWillChangeData();
+ StyleWillChangeData(const StyleWillChangeData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleWillChangeData_h
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp
index 8c0a5c517a4..a53a3dcf118 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/ReferenceFilterBuilder.cpp
@@ -29,9 +29,9 @@
#include "core/rendering/svg/ReferenceFilterBuilder.h"
-#include "SVGNames.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSPrimitiveValueMappings.h"
+#include "core/css/StylePropertySet.h"
#include "core/dom/Element.h"
#include "core/fetch/DocumentResource.h"
#include "core/rendering/svg/RenderSVGResourceFilter.h"
@@ -80,10 +80,11 @@ static bool getSVGElementColorSpace(SVGElement* svgElement, ColorSpace& cs)
if (svgStyle) {
// If a layout has been performed, then we can use the fast path to get this attribute
eColorInterpolation = svgStyle->colorInterpolationFilters();
+ } else if (!svgElement->presentationAttributeStyle()) {
+ return false;
} else {
// Otherwise, use the slow path by using string comparison (used by external svg files)
- RefPtr<CSSValue> cssValue = svgElement->getPresentationAttribute(
- SVGNames::color_interpolation_filtersAttr.toString());
+ RefPtrWillBeRawPtr<CSSValue> cssValue = svgElement->presentationAttributeStyle()->getPropertyCSSValue(CSSPropertyColorInterpolationFilters);
if (cssValue.get() && cssValue->isPrimitiveValue()) {
const CSSPrimitiveValue& primitiveValue = *((CSSPrimitiveValue*)cssValue.get());
eColorInterpolation = (EColorInterpolation)primitiveValue;
@@ -110,9 +111,9 @@ static bool getSVGElementColorSpace(SVGElement* svgElement, ColorSpace& cs)
PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, RenderObject* renderer, FilterEffect* previousEffect, const ReferenceFilterOperation* filterOperation)
{
if (!renderer)
- return 0;
+ return nullptr;
- Document* document = &renderer->document();
+ TreeScope* treeScope = &renderer->node()->treeScope();
if (DocumentResourceReference* documentResourceRef = documentResourceReference(filterOperation)) {
DocumentResource* cachedSVGDocument = documentResourceRef->document();
@@ -120,25 +121,25 @@ PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, Ren
// If we have an SVG document, this is an external reference. Otherwise
// we look up the referenced node in the current document.
if (cachedSVGDocument)
- document = cachedSVGDocument->document();
+ treeScope = cachedSVGDocument->document();
}
- if (!document)
- return 0;
+ if (!treeScope)
+ return nullptr;
- Element* filter = document->getElementById(filterOperation->fragment());
+ Element* filter = treeScope->getElementById(filterOperation->fragment());
if (!filter) {
// Although we did not find the referenced filter, it might exist later
- // in the document
- document->accessSVGExtensions()->addPendingResource(filterOperation->fragment(), toElement(renderer->node()));
- return 0;
+ // in the document.
+ treeScope->document().accessSVGExtensions().addPendingResource(filterOperation->fragment(), toElement(renderer->node()));
+ return nullptr;
}
- if (!filter->isSVGElement() || !filter->hasTagName(SVGNames::filterTag))
- return 0;
+ if (!isSVGFilterElement(*filter))
+ return nullptr;
- SVGFilterElement* filterElement = toSVGFilterElement(toSVGElement(filter));
+ SVGFilterElement& filterElement = toSVGFilterElement(*filter);
// FIXME: Figure out what to do with SourceAlpha. Right now, we're
// using the alpha of the original input layer, which is obviously
@@ -148,13 +149,9 @@ PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, Ren
RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(parentFilter));
ColorSpace filterColorSpace = ColorSpaceDeviceRGB;
- bool useFilterColorSpace = getSVGElementColorSpace(filterElement, filterColorSpace);
-
- for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
- if (!node->isSVGElement())
- continue;
+ bool useFilterColorSpace = getSVGElementColorSpace(&filterElement, filterColorSpace);
- SVGElement* element = toSVGElement(node);
+ for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) {
if (!element->isFilterEffect())
continue;
@@ -165,11 +162,11 @@ PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, Ren
continue;
effectElement->setStandardAttributes(effect.get());
- effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnitsCurrentValue(), parentFilter->sourceImageRect()));
+ effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), parentFilter->sourceImageRect()));
ColorSpace colorSpace = filterColorSpace;
if (useFilterColorSpace || getSVGElementColorSpace(effectElement, colorSpace))
effect->setOperatingColorSpace(colorSpace);
- builder->add(effectElement->resultCurrentValue(), effect);
+ builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect);
}
return builder->lastEffect();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp
index ab40394a4b3..8eddc1f1e6f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.cpp
@@ -23,7 +23,9 @@
#include "core/rendering/svg/RenderSVGBlock.h"
+#include "core/rendering/RenderView.h"
#include "core/rendering/style/ShadowList.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGElement.h"
@@ -50,7 +52,7 @@ void RenderSVGBlock::updateFromStyle()
// RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasOverflowClip(true).
// RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both
- // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText.
+ // Render(SVGText|ForeignObject) return 'NoLayer' on 'layerTypeRequired'. Fine for RenderSVGText.
//
// If we want to support overflow rules for <foreignObject> we can choose between two solutions:
// a) make RenderSVGForeignObject require layers and SVG layer aware
@@ -77,11 +79,46 @@ void RenderSVGBlock::willBeDestroyed()
void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout)
+ if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
RenderBlock::styleDidChange(diff, oldStyle);
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
+void RenderSVGBlock::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
+{
+ SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
+}
+
+const RenderObject* RenderSVGBlock::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+ return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
+LayoutRect RenderSVGBlock::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
+{
+ return SVGRenderSupport::clippedOverflowRectForRepaint(this, paintInvalidationContainer);
+}
+
+void RenderSVGBlock::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
+{
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, paintInvalidationRect, fixed);
+}
+
+bool RenderSVGBlock::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void RenderSVGBlock::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
+{
+ if (!shouldCheckForPaintInvalidationAfterLayout())
+ return;
+
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+ RenderBlockFlow::invalidateTreeAfterLayout(paintInvalidationContainer);
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h
index 6f08eb1f72f..1e21c7c639a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGBlock.h
@@ -32,19 +32,33 @@ public:
virtual LayoutRect visualOverflowRect() const OVERRIDE FINAL;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE FINAL;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
+
+ virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
+ virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
+
+ virtual AffineTransform localTransform() const OVERRIDE FINAL { return m_localTransform; }
+
+ virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NoLayer; }
+
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE;
+
protected:
virtual void willBeDestroyed() OVERRIDE;
+ AffineTransform m_localTransform;
+
private:
virtual void updateFromStyle() OVERRIDE FINAL;
- virtual bool isRenderSVGBlock() const OVERRIDE FINAL { return true; };
-
- virtual bool supportsPartialLayout() const OVERRIDE { return false; }
+ virtual bool isSVG() const OVERRIDE FINAL { return true; }
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp
index 04f28cae872..5767807922e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.cpp
@@ -25,13 +25,15 @@
#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/frame/Settings.h"
#include "core/rendering/GraphicsContextAnnotator.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
+#include "platform/graphics/GraphicsContextCullSaver.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
namespace WebCore {
@@ -52,9 +54,8 @@ void RenderSVGContainer::layout()
ASSERT(needsLayout());
// RenderSVGRoot disables layoutState for the SVG rendering tree.
- ASSERT(!view()->layoutStateEnabled());
+ ASSERT(!view()->layoutStateCachedOffsetsEnabled());
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) || selfWillPaint());
// Allow RenderSVGViewportContainer to update its viewport.
@@ -116,7 +117,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
if (!firstChild() && !selfWillPaint())
return;
- FloatRect repaintRect = repaintRectInLocalCoordinates();
+ FloatRect repaintRect = paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(repaintRect, localToParentTransform(), paintInfo))
return;
@@ -130,10 +131,14 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
childPaintInfo.applyTransform(localToParentTransform());
SVGRenderingContext renderingContext;
+ GraphicsContextCullSaver cullSaver(*childPaintInfo.context);
bool continueRendering = true;
if (childPaintInfo.phase == PaintPhaseForeground) {
renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
continueRendering = renderingContext.isRenderingPrepared();
+
+ if (continueRendering && document().settings()->containerCullingEnabled())
+ cullSaver.cull(paintInvalidationRectInLocalCoordinates());
}
if (continueRendering) {
@@ -144,11 +149,11 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
}
// FIXME: This really should be drawn from local coordinates, but currently we hack it
- // to avoid our clip killing our outline rect. Thus we translate our
+ // to avoid our clip killing our outline rect. Thus we translate our
// outline rect into parent coords before drawing.
// FIXME: This means our focus ring won't share our rotation like it should.
// We should instead disable our clip during PaintPhaseOutline
- if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) {
+ if (paintInfo.phase == PaintPhaseForeground && style()->outlineWidth() && style()->visibility() == VISIBLE) {
IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect));
paintOutline(paintInfo, paintRectInParent);
}
@@ -157,7 +162,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call
void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
- IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
+ IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(paintInvalidationRectInLocalCoordinates()));
if (!paintRectInParent.isEmpty())
rects.append(paintRectInParent);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h
index fd4e74db96b..b7235fbaded 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGContainer.h
@@ -37,12 +37,15 @@ public:
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderSVGContainer, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual void setNeedsBoundariesUpdate() OVERRIDE FINAL { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE FINAL { return m_needsBoundariesUpdate; }
virtual bool didTransformToRootUpdate() { return false; }
bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
@@ -51,9 +54,9 @@ protected:
virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
virtual bool isSVGContainer() const OVERRIDE FINAL { return true; }
- virtual const char* renderName() const { return "RenderSVGContainer"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGContainer"; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE FINAL;
virtual void removeChild(RenderObject*) OVERRIDE FINAL;
@@ -61,9 +64,9 @@ protected:
virtual FloatRect objectBoundingBox() const OVERRIDE FINAL { return m_objectBoundingBox; }
virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL { return m_strokeBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
// Allow RenderSVGTransformableContainer to hook in at the right time in layout()
virtual bool calculateLocalTransform() { return false; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp
index ac5c6491fc3..b9a75029ae0 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.cpp
@@ -28,9 +28,9 @@
#include "core/rendering/svg/RenderSVGEllipse.h"
-#include "SVGNames.h"
#include "core/svg/SVGCircleElement.h"
#include "core/svg/SVGEllipseElement.h"
+#include "platform/graphics/GraphicsContext.h"
namespace WebCore {
@@ -53,20 +53,22 @@ void RenderSVGEllipse::updateShapeFromElement()
m_center = FloatPoint();
m_radii = FloatSize();
- // Fallback to RenderSVGShape if shape has a non-scaling stroke.
- if (hasNonScalingStroke()) {
- RenderSVGShape::updateShapeFromElement();
- m_usePathFallback = true;
- return;
- } else
- m_usePathFallback = false;
-
calculateRadiiAndCenter();
- // Spec: "A value of zero disables rendering of the element."
- if (m_radii.width() <= 0 || m_radii.height() <= 0)
+ // Spec: "A negative value is an error. A value of zero disables rendering of the element."
+ if (m_radii.width() < 0 || m_radii.height() < 0)
return;
+ if (!m_radii.isEmpty()) {
+ // Fallback to RenderSVGShape if shape has a non-scaling stroke.
+ if (hasNonScalingStroke()) {
+ RenderSVGShape::updateShapeFromElement();
+ m_usePathFallback = true;
+ return;
+ }
+ m_usePathFallback = false;
+ }
+
m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
m_strokeBoundingBox = m_fillBoundingBox;
if (style()->svgStyle()->hasStroke())
@@ -76,21 +78,21 @@ void RenderSVGEllipse::updateShapeFromElement()
void RenderSVGEllipse::calculateRadiiAndCenter()
{
ASSERT(element());
- if (element()->hasTagName(SVGNames::circleTag)) {
- SVGCircleElement* circle = toSVGCircleElement(element());
+ if (isSVGCircleElement(*element())) {
+ SVGCircleElement& circle = toSVGCircleElement(*element());
- SVGLengthContext lengthContext(circle);
- float radius = circle->rCurrentValue().value(lengthContext);
+ SVGLengthContext lengthContext(&circle);
+ float radius = circle.r()->currentValue()->value(lengthContext);
m_radii = FloatSize(radius, radius);
- m_center = FloatPoint(circle->cxCurrentValue().value(lengthContext), circle->cyCurrentValue().value(lengthContext));
+ m_center = FloatPoint(circle.cx()->currentValue()->value(lengthContext), circle.cy()->currentValue()->value(lengthContext));
return;
}
- SVGEllipseElement* ellipse = toSVGEllipseElement(element());
+ SVGEllipseElement& ellipse = toSVGEllipseElement(*element());
- SVGLengthContext lengthContext(ellipse);
- m_radii = FloatSize(ellipse->rxCurrentValue().value(lengthContext), ellipse->ryCurrentValue().value(lengthContext));
- m_center = FloatPoint(ellipse->cxCurrentValue().value(lengthContext), ellipse->cyCurrentValue().value(lengthContext));
+ SVGLengthContext lengthContext(&ellipse);
+ m_radii = FloatSize(ellipse.rx()->currentValue()->value(lengthContext), ellipse.ry()->currentValue()->value(lengthContext));
+ m_center = FloatPoint(ellipse.cx()->currentValue()->value(lengthContext), ellipse.cy()->currentValue()->value(lengthContext));
}
void RenderSVGEllipse::fillShape(GraphicsContext* context) const
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h
index f06e5c16cf0..b73b5526853 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGEllipse.h
@@ -37,14 +37,14 @@ public:
virtual ~RenderSVGEllipse();
private:
- virtual const char* renderName() const { return "RenderSVGEllipse"; }
-
- virtual void updateShapeFromElement();
- virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
- virtual bool shapeDependentStrokeContains(const FloatPoint&);
- virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGEllipse"; }
+
+ virtual void updateShapeFromElement() OVERRIDE;
+ virtual bool isShapeEmpty() const OVERRIDE { return m_usePathFallback ? RenderSVGShape::isShapeEmpty() : m_fillBoundingBox.isEmpty(); }
+ virtual void fillShape(GraphicsContext*) const OVERRIDE;
+ virtual void strokeShape(GraphicsContext*) const OVERRIDE;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&) OVERRIDE;
+ virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const OVERRIDE;
void calculateRadiiAndCenter();
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp
index e27e037926f..9a9459836e1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.cpp
@@ -24,7 +24,6 @@
#include "core/rendering/svg/RenderSVGForeignObject.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/SVGRenderSupport.h"
@@ -45,6 +44,12 @@ RenderSVGForeignObject::~RenderSVGForeignObject()
{
}
+bool RenderSVGForeignObject::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+ // Disallow arbitary SVG content. Only allow proper <svg xmlns="svgNS"> subdocuments.
+ return !child->isSVG() || child->isSVGRoot();
+}
+
void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
if (paintInfo.context->paintingDisabled()
@@ -85,16 +90,6 @@ void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&)
}
}
-LayoutRect RenderSVGForeignObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
-{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
-}
-
-void RenderSVGForeignObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
-{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
-}
-
const AffineTransform& RenderSVGForeignObject::localToParentTransform() const
{
m_localToParentTransform = localTransform();
@@ -121,9 +116,8 @@ void RenderSVGForeignObject::computeLogicalHeight(LayoutUnit, LayoutUnit logical
void RenderSVGForeignObject::layout()
{
ASSERT(needsLayout());
- ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
+ ASSERT(!view()->layoutStateCachedOffsetsEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this));
SVGForeignObjectElement* foreign = toSVGForeignObjectElement(node());
@@ -138,8 +132,8 @@ void RenderSVGForeignObject::layout()
// Cache viewport boundaries
SVGLengthContext lengthContext(foreign);
- FloatPoint viewportLocation(foreign->xCurrentValue().value(lengthContext), foreign->yCurrentValue().value(lengthContext));
- m_viewport = FloatRect(viewportLocation, FloatSize(foreign->widthCurrentValue().value(lengthContext), foreign->heightCurrentValue().value(lengthContext)));
+ FloatPoint viewportLocation(foreign->x()->currentValue()->value(lengthContext), foreign->y()->currentValue()->value(lengthContext));
+ m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width()->currentValue()->value(lengthContext), foreign->height()->currentValue()->value(lengthContext)));
if (!updateCachedBoundariesInParents)
updateCachedBoundariesInParents = oldViewport != m_viewport;
@@ -165,6 +159,14 @@ void RenderSVGForeignObject::layout()
repainter.repaintAfterLayout();
}
+void RenderSVGForeignObject::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer,
+ LayoutRect& rect, bool fixed) const
+{
+ FloatRect r(rect);
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, r, fixed);
+ rect = enclosingLayoutRect(r);
+}
+
bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
// Embedded content is drawn in the foreground phase.
@@ -184,20 +186,4 @@ bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, Hit
|| RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds);
}
-bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-void RenderSVGForeignObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
-{
- SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
-}
-
-const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
-{
- return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h
index 63cdac1d35b..d57b723aa18 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGForeignObject.h
@@ -32,38 +32,32 @@ public:
explicit RenderSVGForeignObject(SVGForeignObjectElement*);
virtual ~RenderSVGForeignObject();
- virtual const char* renderName() const { return "RenderSVGForeignObject"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGForeignObject"; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual bool requiresLayer() const { return false; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual FloatRect strokeBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(FloatPoint(), m_viewport.size()); }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return FloatRect(FloatPoint(), m_viewport.size()); }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return FloatRect(FloatPoint(), m_viewport.size()); }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return FloatRect(FloatPoint(), m_viewport.size()); }
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual bool isSVGForeignObject() const { return true; }
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
+ virtual bool isSVGForeignObject() const OVERRIDE { return true; }
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
private:
virtual void updateLogicalWidth() OVERRIDE;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const;
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE;
bool m_needsTransformUpdate : 1;
FloatRect m_viewport;
- AffineTransform m_localTransform;
mutable AffineTransform m_localToParentTransform;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp
index ca5f315a7bc..d9ce3bf7015 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.cpp
@@ -21,15 +21,12 @@
#include "core/rendering/svg/RenderSVGGradientStop.h"
-#include "SVGNames.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
#include "core/svg/SVGGradientElement.h"
#include "core/svg/SVGStopElement.h"
namespace WebCore {
-using namespace SVGNames;
-
RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement* element)
: RenderObject(element)
{
@@ -42,7 +39,7 @@ RenderSVGGradientStop::~RenderSVGGradientStop()
void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderObject::styleDidChange(diff, oldStyle);
- if (diff == StyleDifferenceEqual)
+ if (diff.hasNoChange())
return;
// <stop> elements should only be allowed to make renderers under gradient elements
@@ -67,9 +64,8 @@ void RenderSVGGradientStop::layout()
SVGGradientElement* RenderSVGGradientStop::gradientElement() const
{
ContainerNode* parentNode = node()->parentNode();
- if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag))
- return toSVGGradientElement(parentNode);
- return 0;
+ ASSERT(parentNode);
+ return isSVGGradientElement(*parentNode) ? toSVGGradientElement(parentNode) : 0;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h
index e56274e3ffc..4d6fee11121 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGGradientStop.h
@@ -34,21 +34,22 @@ public:
explicit RenderSVGGradientStop(SVGStopElement*);
virtual ~RenderSVGGradientStop();
- virtual bool isSVGGradientStop() const { return true; }
- virtual const char* renderName() const { return "RenderSVGGradientStop"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGGradientStop"; }
+ virtual bool isSVGGradientStop() const OVERRIDE { return true; }
+ virtual bool isSVG() const OVERRIDE { return true; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
// This overrides are needed to prevent ASSERTs on <svg><stop /></svg>
// RenderObject's default implementations ASSERT_NOT_REACHED()
// https://bugs.webkit.org/show_bug.cgi?id=20400
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const OVERRIDE { return LayoutRect(); }
- virtual FloatRect objectBoundingBox() const { return FloatRect(); }
- virtual FloatRect strokeBoundingBox() const { return FloatRect(); }
- virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*) const OVERRIDE { return LayoutRect(); }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return FloatRect(); }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return FloatRect(); }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return FloatRect(); }
protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
private:
SVGGradientElement* gradientElement() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
index 0f1578935a5..0e5af52bb57 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
@@ -20,8 +20,7 @@
#include "config.h"
#include "core/rendering/svg/RenderSVGHiddenContainer.h"
-
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
namespace WebCore {
@@ -33,7 +32,6 @@ RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGElement* element)
void RenderSVGHiddenContainer::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
SVGRenderSupport::layoutChildren(this, selfNeedsLayout());
updateCachedBoundaries();
clearNeedsLayout();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h
index f8e57d33f1d..0616b76b719 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGHiddenContainer.h
@@ -32,17 +32,17 @@ class RenderSVGHiddenContainer : public RenderSVGContainer {
public:
explicit RenderSVGHiddenContainer(SVGElement*);
- virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGHiddenContainer"; }
protected:
- virtual void layout();
+ virtual void layout() OVERRIDE;
private:
virtual bool isSVGHiddenContainer() const OVERRIDE FINAL { return true; }
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const OVERRIDE FINAL { return LayoutRect(); }
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*) const OVERRIDE FINAL { return LayoutRect(); }
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE FINAL;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp
index 9e2e4cd9414..b483670d4f2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.cpp
@@ -29,11 +29,11 @@
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/ImageQualityController.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/PointerEventsHitRules.h"
#include "core/rendering/RenderImageResource.h"
#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
@@ -64,12 +64,12 @@ bool RenderSVGImage::updateImageViewport()
bool updatedViewport = false;
SVGLengthContext lengthContext(image);
- m_objectBoundingBox = FloatRect(image->xCurrentValue().value(lengthContext), image->yCurrentValue().value(lengthContext), image->widthCurrentValue().value(lengthContext), image->heightCurrentValue().value(lengthContext));
+ m_objectBoundingBox = FloatRect(image->x()->currentValue()->value(lengthContext), image->y()->currentValue()->value(lengthContext), image->width()->currentValue()->value(lengthContext), image->height()->currentValue()->value(lengthContext));
// Images with preserveAspectRatio=none should force non-uniform scaling. This can be achieved
// by setting the image's container size to its intrinsic size.
// See: http://www.w3.org/TR/SVG/single-page.html, 7.8 The ‘preserveAspectRatio’ attribute.
- if (image->preserveAspectRatioCurrentValue().align() == SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) {
+ if (image->preserveAspectRatio()->currentValue()->align() == SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) {
if (ImageResource* cachedImage = m_imageResource->cachedImage()) {
LayoutSize intrinsicSize = cachedImage->imageSizeForRenderer(0, style()->effectiveZoom());
if (intrinsicSize != m_imageResource->imageSize(style()->effectiveZoom())) {
@@ -93,7 +93,6 @@ void RenderSVGImage::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout());
updateImageViewport();
@@ -126,33 +125,38 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
- if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage())
+ if (paintInfo.context->paintingDisabled()
+ || paintInfo.phase != PaintPhaseForeground
+ || style()->visibility() == HIDDEN
+ || !m_imageResource->hasImage())
return;
- FloatRect boundingBox = repaintRectInLocalCoordinates();
+ FloatRect boundingBox = paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
return;
PaintInfo childPaintInfo(paintInfo);
- bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
- if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
- childPaintInfo.applyTransform(m_localTransform);
+ GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
- if (childPaintInfo.phase == PaintPhaseForeground && !m_objectBoundingBox.isEmpty()) {
- SVGRenderingContext renderingContext(this, childPaintInfo);
+ if (!m_localTransform.isIdentity()) {
+ stateSaver.save();
+ childPaintInfo.applyTransform(m_localTransform, false);
+ }
+ if (!m_objectBoundingBox.isEmpty()) {
+ // SVGRenderingContext may taint the state - make sure we're always saving.
+ SVGRenderingContext renderingContext(this, childPaintInfo, stateSaver.saved() ?
+ SVGRenderingContext::DontSaveGraphicsContext : SVGRenderingContext::SaveGraphicsContext);
- if (renderingContext.isRenderingPrepared()) {
- if (style()->svgStyle()->bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground))
- return;
+ if (renderingContext.isRenderingPrepared()) {
+ if (style()->svgStyle()->bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground))
+ return;
- paintForeground(childPaintInfo);
- }
+ paintForeground(childPaintInfo);
}
-
- if (drawsOutline)
- paintOutline(childPaintInfo, IntRect(boundingBox));
}
+
+ if (style()->outlineWidth())
+ paintOutline(childPaintInfo, IntRect(boundingBox));
}
void RenderSVGImage::paintForeground(PaintInfo& paintInfo)
@@ -162,13 +166,16 @@ void RenderSVGImage::paintForeground(PaintInfo& paintInfo)
FloatRect srcRect(0, 0, image->width(), image->height());
SVGImageElement* imageElement = toSVGImageElement(element());
- imageElement->preserveAspectRatioCurrentValue().transformRect(destRect, srcRect);
+ imageElement->preserveAspectRatio()->currentValue()->transformRect(destRect, srcRect);
- bool useLowQualityScaling = false;
+ InterpolationQuality interpolationQuality = InterpolationDefault;
if (style()->svgStyle()->bufferedRendering() != BR_STATIC)
- useLowQualityScaling = ImageQualityController::imageQualityController()->shouldPaintAtLowQuality(paintInfo.context, this, image.get(), image.get(), LayoutSize(destRect.size()));
+ interpolationQuality = ImageQualityController::imageQualityController()->chooseInterpolationQuality(paintInfo.context, this, image.get(), image.get(), LayoutSize(destRect.size()));
- paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver, DoNotRespectImageOrientation, useLowQualityScaling);
+ InterpolationQuality previousInterpolationQuality = paintInfo.context->imageInterpolationQuality();
+ paintInfo.context->setImageInterpolationQuality(interpolationQuality);
+ paintInfo.context->drawImage(image.get(), destRect, srcRect, CompositeSourceOver);
+ paintInfo.context->setImageInterpolationQuality(previousInterpolationQuality);
}
void RenderSVGImage::invalidateBufferedForeground()
@@ -218,13 +225,13 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*)
invalidateBufferedForeground();
- repaint();
+ paintInvalidationForWholeRenderer();
}
void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
// this is called from paint() after the localTransform has already been applied
- IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
+ IntRect contentRect = enclosingIntRect(paintInvalidationRectInLocalCoordinates());
if (!contentRect.isEmpty())
rects.append(contentRect);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h
index e87392e04fa..644bdd15027 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGImage.h
@@ -37,9 +37,8 @@ public:
virtual ~RenderSVGImage();
bool updateImageViewport();
- virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesUpdate; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void setNeedsBoundariesUpdate() OVERRIDE { m_needsBoundariesUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
RenderImageResource* imageResource() { return m_imageResource.get(); }
@@ -47,27 +46,27 @@ public:
void paintForeground(PaintInfo&);
private:
- virtual const char* renderName() const { return "RenderSVGImage"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGImage"; }
virtual bool isSVGImage() const OVERRIDE { return true; }
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localTransform; }
- virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return m_objectBoundingBox; }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return m_objectBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return m_repaintBoundingBox; }
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE;
- virtual void layout();
- virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void layout() OVERRIDE;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
void invalidateBufferedForeground();
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual AffineTransform localTransform() const OVERRIDE { return m_localTransform; }
bool m_needsBoundariesUpdate : 1;
bool m_needsTransformUpdate : 1;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp
index 68b1a4029cd..07c0a58c4d9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.cpp
@@ -27,12 +27,22 @@
#include "core/rendering/svg/SVGInlineFlowBox.h"
#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGAElement.h"
namespace WebCore {
bool RenderSVGInline::isChildAllowed(RenderObject* child, RenderStyle* style) const
{
- if (SVGRenderSupport::isEmptySVGInlineText(child))
+ if (child->isText())
+ return SVGRenderSupport::isRenderableTextNode(child);
+
+ if (isSVGAElement(*node())) {
+ // Disallow direct descendant 'a'.
+ if (isSVGAElement(*child->node()))
+ return false;
+ }
+
+ if (!child->isSVGInline() && !child->isSVGInlineText())
return false;
return RenderInline::isChildAllowed(child, style);
@@ -46,7 +56,7 @@ RenderSVGInline::RenderSVGInline(Element* element)
InlineFlowBox* RenderSVGInline::createInlineFlowBox()
{
- InlineFlowBox* box = new SVGInlineFlowBox(this);
+ InlineFlowBox* box = new SVGInlineFlowBox(*this);
box->setHasVirtualLogicalHeight();
return box;
}
@@ -67,22 +77,22 @@ FloatRect RenderSVGInline::strokeBoundingBox() const
return FloatRect();
}
-FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const
+FloatRect RenderSVGInline::paintInvalidationRectInLocalCoordinates() const
{
if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
- return object->repaintRectInLocalCoordinates();
+ return object->paintInvalidationRectInLocalCoordinates();
return FloatRect();
}
-LayoutRect RenderSVGInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderSVGInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+ return SVGRenderSupport::clippedOverflowRectForRepaint(this, paintInvalidationContainer);
}
-void RenderSVGInline::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+void RenderSVGInline::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, paintInvalidationRect, fixed);
}
void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -114,7 +124,7 @@ void RenderSVGInline::willBeDestroyed()
void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout)
+ if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
RenderInline::styleDidChange(diff, oldStyle);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h
index 43634a39c22..1c09c5666f6 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInline.h
@@ -29,9 +29,10 @@ class RenderSVGInline : public RenderInline {
public:
explicit RenderSVGInline(Element*);
- virtual const char* renderName() const { return "RenderSVGInline"; }
- virtual bool requiresLayer() const OVERRIDE FINAL { return false; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGInline"; }
+ virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NoLayer; }
virtual bool isSVGInline() const OVERRIDE FINAL { return true; }
+ virtual bool isSVG() const OVERRIDE FINAL { return true; }
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
@@ -42,10 +43,10 @@ public:
// this element, since we need it for filters.
virtual FloatRect objectBoundingBox() const OVERRIDE FINAL;
virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL;
- virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL;
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE FINAL;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE FINAL;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE FINAL;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
@@ -60,6 +61,8 @@ private:
virtual void removeChild(RenderObject*) OVERRIDE FINAL;
};
+DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderSVGInline, isSVGInline());
+
}
#endif // !RenderSVGTSpan_H
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp
index e8041f8c1c2..d19fed0516d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.cpp
@@ -89,17 +89,17 @@ void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle
return;
}
- if (diff != StyleDifferenceLayout)
+ if (!diff.needsFullLayout())
return;
// The text metrics may be influenced by style changes.
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeStyleDidChange(this);
+ textRenderer->setNeedsLayoutAndFullPaintInvalidation();
}
InlineTextBox* RenderSVGInlineText::createTextBox()
{
- InlineTextBox* box = new SVGInlineTextBox(this);
+ InlineTextBox* box = new SVGInlineTextBox(*this);
box->setHasVirtualLogicalHeight();
return box;
}
@@ -186,8 +186,7 @@ PositionWithAffinity RenderSVGInlineText::positionForPoint(const LayoutPoint& po
const SVGTextFragment& fragment = fragments.at(i);
FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) +
powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2);
@@ -226,7 +225,7 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c
return;
}
- if (style->fontDescription().textRenderingMode() == GeometricPrecision)
+ if (style->fontDescription().textRendering() == GeometricPrecision)
scalingFactor = 1;
FontDescription fontDescription(style->fontDescription());
@@ -235,7 +234,7 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c
// FIXME: We need to better handle the case when we compute very small fonts below (below 1pt).
fontDescription.setComputedSize(FontSize::getComputedSizeFromSpecifiedSize(&document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), DoNotUseSmartMinimumForFontSize));
- scaledFont = Font(fontDescription, 0, 0);
+ scaledFont = Font(fontDescription);
scaledFont.update(document.styleEngine()->fontSelector());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h
index 8c7f711a68f..b7fc9add99b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGInlineText.h
@@ -27,8 +27,6 @@
namespace WebCore {
-class SVGInlineTextBox;
-
class RenderSVGInlineText FINAL : public RenderText {
public:
RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
@@ -45,19 +43,20 @@ public:
FloatRect floatLinesBoundingBox() const;
private:
- virtual const char* renderName() const { return "RenderSVGInlineText"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGInlineText"; }
- virtual void setTextInternal(PassRefPtr<StringImpl>);
- virtual void styleDidChange(StyleDifference, const RenderStyle*);
+ virtual void setTextInternal(PassRefPtr<StringImpl>) OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return floatLinesBoundingBox(); }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return floatLinesBoundingBox(); }
- virtual bool isSVGInlineText() const { return true; }
+ virtual bool isSVGInlineText() const OVERRIDE { return true; }
+ virtual bool isSVG() const OVERRIDE { return true; }
- virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
- virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
- virtual IntRect linesBoundingBox() const;
- virtual InlineTextBox* createTextBox();
+ virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
+ virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) OVERRIDE;
+ virtual IntRect linesBoundingBox() const OVERRIDE;
+ virtual InlineTextBox* createTextBox() OVERRIDE;
float m_scalingFactor;
Font m_scaledFont;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp
index 12da706b521..a6918a93535 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.cpp
@@ -29,11 +29,12 @@
*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGModelObject.h"
-#include "SVGNames.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGGraphicsElement.h"
@@ -44,14 +45,19 @@ RenderSVGModelObject::RenderSVGModelObject(SVGElement* node)
{
}
-LayoutRect RenderSVGModelObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+bool RenderSVGModelObject::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isSVG() && !(child->isSVGInline() || child->isSVGInlineText());
+}
+
+LayoutRect RenderSVGModelObject::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+ return SVGRenderSupport::clippedOverflowRectForRepaint(this, paintInvalidationContainer);
}
-void RenderSVGModelObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+void RenderSVGModelObject::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+ SVGRenderSupport::computeFloatRectForRepaint(this, paintInvalidationContainer, paintInvalidationRect, fixed);
}
void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
@@ -64,18 +70,6 @@ const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLay
return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
}
-// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
-// FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends
-// on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
-LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const
-{
- LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates());
- adjustRectForOutlineAndShadow(box);
-
- FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
- return containerRelativeQuad.enclosingBoundingBox();
-}
-
void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
IntRect rect = enclosingIntRect(strokeBoundingBox());
@@ -107,7 +101,7 @@ void RenderSVGModelObject::addLayerHitTestRects(LayerHitTestRects&, const Render
void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout) {
+ if (diff.needsFullLayout()) {
setNeedsBoundariesUpdate();
if (style()->hasTransform())
setNeedsTransformUpdate();
@@ -123,82 +117,53 @@ bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, co
return false;
}
-static void getElementCTM(SVGGraphicsElement* element, AffineTransform& transform)
+// The SVG addFocusRingRects() method adds rects in local coordinates so the default absoluteFocusRingQuads
+// returns incorrect values for SVG objects. Overriding this method provides access to the absolute bounds.
+void RenderSVGModelObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
{
- ASSERT(element);
- element->document().updateLayoutIgnorePendingStylesheets();
-
- SVGElement* stopAtElement = element->nearestViewportElement();
- ASSERT(stopAtElement);
+ quads.append(localToAbsoluteQuad(FloatQuad(paintInvalidationRectInLocalCoordinates())));
+}
- AffineTransform localTransform;
- Node* current = element;
+void RenderSVGModelObject::invalidateTreeAfterLayout(const RenderLayerModelObject& paintInvalidationContainer)
+{
+ // Note: This is a reduced version of RenderBox::invalidateTreeAfterLayout().
+ // FIXME: Should share code with RenderBox::invalidateTreeAfterLayout().
+ ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled());
+ ASSERT(!needsLayout());
- while (current && current->isSVGElement()) {
- SVGElement* currentElement = toSVGElement(current);
- localTransform = currentElement->renderer()->localToParentTransform();
- transform = localTransform.multiply(transform);
- // For getCTM() computation, stop at the nearest viewport element
- if (currentElement == stopAtElement)
- break;
+ if (!shouldCheckForPaintInvalidationAfterLayout())
+ return;
- current = current->parentOrShadowHostNode();
- }
-}
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
-// FloatRect::intersects does not consider horizontal or vertical lines (because of isEmpty()).
-// So special-case handling of such lines.
-static bool intersectsAllowingEmpty(const FloatRect& r, const FloatRect& other)
-{
- if (r.isEmpty() && other.isEmpty())
- return false;
- if (r.isEmpty() && !other.isEmpty()) {
- return (other.contains(r.x(), r.y()) && !other.contains(r.maxX(), r.maxY()))
- || (!other.contains(r.x(), r.y()) && other.contains(r.maxX(), r.maxY()));
- }
- if (other.isEmpty() && !r.isEmpty())
- return intersectsAllowingEmpty(other, r);
- return r.intersects(other);
-}
+ const LayoutRect oldPaintInvalidationRect = previousPaintInvalidationRect();
+ const LayoutPoint oldPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
+ const RenderLayerModelObject& newPaintInvalidationContainer = *containerForPaintInvalidation();
+ setPreviousPaintInvalidationRect(clippedOverflowRectForPaintInvalidation(&newPaintInvalidationContainer));
+ setPreviousPositionFromPaintInvalidationContainer(RenderLayer::positionFromPaintInvalidationContainer(this, &newPaintInvalidationContainer));
-// One of the element types that can cause graphics to be drawn onto the target canvas. Specifically: circle, ellipse,
-// image, line, path, polygon, polyline, rect, text and use.
-static bool isGraphicsElement(RenderObject* renderer)
-{
- return renderer->isSVGShape() || renderer->isSVGText() || renderer->isSVGImage() || renderer->node()->hasTagName(SVGNames::useTag);
-}
+ // If an ancestor container had its transform changed, then we just
+ // need to update the RenderSVGModelObject's repaint rect above. The invalidation
+ // will be handled by the container where the transform changed. This essentially
+ // means that we prune the entire branch for performance.
+ if (!SVGRenderSupport::parentTransformDidChange(this))
+ return;
-// The SVG addFocusRingRects() method adds rects in local coordinates so the default absoluteFocusRingQuads
-// returns incorrect values for SVG objects. Overriding this method provides access to the absolute bounds.
-void RenderSVGModelObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
-{
- quads.append(localToAbsoluteQuad(FloatQuad(repaintRectInLocalCoordinates())));
-}
+ // If we are set to do a full paint invalidation that means the RenderView will be
+ // issue paint invalidations. We can then skip issuing of paint invalidations for the child
+ // renderers as they'll be covered by the RenderView.
+ if (view()->doingFullRepaint()) {
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
+ return;
+ }
-bool RenderSVGModelObject::checkIntersection(RenderObject* renderer, const SVGRect& rect)
-{
- if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
- return false;
- if (!isGraphicsElement(renderer))
- return false;
- AffineTransform ctm;
- SVGGraphicsElement* svgElement = toSVGGraphicsElement(renderer->node());
- getElementCTM(svgElement, ctm);
- ASSERT(svgElement->renderer());
- return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
-}
+ const LayoutRect& newPaintInvalidationRect = previousPaintInvalidationRect();
+ const LayoutPoint& newPositionFromPaintInvalidationContainer = previousPositionFromPaintInvalidationContainer();
+ invalidatePaintAfterLayoutIfNeeded(containerForPaintInvalidation(),
+ shouldDoFullPaintInvalidationAfterLayout(), oldPaintInvalidationRect, oldPositionFromPaintInvalidationContainer,
+ &newPaintInvalidationRect, &newPositionFromPaintInvalidationContainer);
-bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const SVGRect& rect)
-{
- if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
- return false;
- if (!isGraphicsElement(renderer))
- return false;
- AffineTransform ctm;
- SVGGraphicsElement* svgElement = toSVGGraphicsElement(renderer->node());
- getElementCTM(svgElement, ctm);
- ASSERT(svgElement->renderer());
- return rect.contains(ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
+ RenderObject::invalidateTreeAfterLayout(newPaintInvalidationContainer);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h
index c8df10aca7d..41bc62ae412 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGModelObject.h
@@ -32,9 +32,8 @@
#define RenderSVGModelObject_h
#include "core/rendering/RenderObject.h"
-#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/svg/SVGElement.h"
-#include "core/svg/SVGRect.h"
+#include "platform/geometry/FloatRect.h"
namespace WebCore {
@@ -49,34 +48,37 @@ class RenderSVGModelObject : public RenderObject {
public:
explicit RenderSVGModelObject(SVGElement*);
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const OVERRIDE FINAL;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+ virtual bool canHaveWhitespaceChildren() const OVERRIDE { return false; }
+
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
- static bool checkIntersection(RenderObject*, const SVGRect&);
- static bool checkEnclosure(RenderObject*, const SVGRect&);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
- virtual void computeLayerHitTestRects(LayerHitTestRects&) const OVERRIDE;
+ virtual void computeLayerHitTestRects(LayerHitTestRects&) const OVERRIDE FINAL;
SVGElement* element() const { return toSVGElement(RenderObject::node()); }
+ virtual bool isSVG() const OVERRIDE FINAL { return true; }
+
+ virtual void invalidateTreeAfterLayout(const RenderLayerModelObject&) OVERRIDE;
+
protected:
- virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE;
- virtual void willBeDestroyed();
+ virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const OVERRIDE FINAL;
+ virtual void willBeDestroyed() OVERRIDE;
private:
// RenderSVGModelObject subclasses should use element() instead.
void node() const WTF_DELETED_FUNCTION;
// This method should never be called, SVG uses a different nodeAtPoint method
- bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
virtual void absoluteFocusRingQuads(Vector<FloatQuad>&) OVERRIDE FINAL;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h
index 8cec15c4c92..48b36762e04 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGPath.h
@@ -37,7 +37,7 @@ public:
private:
virtual bool isSVGPath() const OVERRIDE { return true; }
- virtual const char* renderName() const { return "RenderSVGPath"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGPath"; }
virtual void updateShapeFromElement() OVERRIDE;
FloatRect calculateUpdatedStrokeBoundingBox() const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp
index dfe447156f6..5fd79e7f626 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.cpp
@@ -28,8 +28,7 @@
#include "config.h"
#include "core/rendering/svg/RenderSVGRect.h"
-
-#include "SVGNames.h"
+#include "platform/graphics/GraphicsContext.h"
namespace WebCore {
@@ -54,19 +53,24 @@ void RenderSVGRect::updateShapeFromElement()
ASSERT(rect);
SVGLengthContext lengthContext(rect);
- // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
- if (rect->rxCurrentValue().value(lengthContext) > 0 || rect->ryCurrentValue().value(lengthContext) > 0 || hasNonScalingStroke()) {
- RenderSVGShape::updateShapeFromElement();
- m_usePathFallback = true;
- return;
- }
+ FloatSize boundingBoxSize(rect->width()->currentValue()->value(lengthContext), rect->height()->currentValue()->value(lengthContext));
- m_usePathFallback = false;
- FloatSize boundingBoxSize(rect->widthCurrentValue().value(lengthContext), rect->heightCurrentValue().value(lengthContext));
- if (boundingBoxSize.isEmpty())
+ // Spec: "A negative value is an error."
+ if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0)
return;
- m_fillBoundingBox = FloatRect(FloatPoint(rect->xCurrentValue().value(lengthContext), rect->yCurrentValue().value(lengthContext)), boundingBoxSize);
+ // Spec: "A value of zero disables rendering of the element."
+ if (!boundingBoxSize.isEmpty()) {
+ // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
+ if (rect->rx()->currentValue()->value(lengthContext) > 0 || rect->ry()->currentValue()->value(lengthContext) > 0 || hasNonScalingStroke()) {
+ RenderSVGShape::updateShapeFromElement();
+ m_usePathFallback = true;
+ return;
+ }
+ m_usePathFallback = false;
+ }
+
+ m_fillBoundingBox = FloatRect(FloatPoint(rect->x()->currentValue()->value(lengthContext), rect->y()->currentValue()->value(lengthContext)), boundingBoxSize);
// To decide if the stroke contains a point we create two rects which represent the inner and
// the outer stroke borders. A stroke contains the point, if the point is between them.
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h
index 1a5d6e091e4..7ae39625755 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRect.h
@@ -39,14 +39,14 @@ public:
virtual ~RenderSVGRect();
private:
- virtual const char* renderName() const { return "RenderSVGRect"; }
-
- virtual void updateShapeFromElement();
- virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
- virtual void fillShape(GraphicsContext*) const;
- virtual void strokeShape(GraphicsContext*) const;
- virtual bool shapeDependentStrokeContains(const FloatPoint&);
- virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGRect"; }
+
+ virtual void updateShapeFromElement() OVERRIDE;
+ virtual bool isShapeEmpty() const OVERRIDE { return m_usePathFallback ? RenderSVGShape::isShapeEmpty() : m_fillBoundingBox.isEmpty(); }
+ virtual void fillShape(GraphicsContext*) const OVERRIDE;
+ virtual void strokeShape(GraphicsContext*) const OVERRIDE;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&) OVERRIDE;
+ virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const OVERRIDE;
private:
FloatRect m_innerStrokeRect;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp
index 4dd3ae01c90..0c67bc8d070 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.cpp
@@ -24,8 +24,8 @@
#include "core/rendering/svg/RenderSVGResource.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/svg/RenderSVGResourceClipper.h"
#include "core/rendering/svg/RenderSVGResourceFilter.h"
#include "core/rendering/svg/RenderSVGResourceMasker.h"
@@ -35,22 +35,25 @@
namespace WebCore {
-static inline bool inheritColorFromParentStyleIfNeeded(RenderObject* object, bool applyToFill, Color& color)
+static inline bool inheritColorFromParentStyle(RenderObject* object, bool applyToFill, Color& color)
{
- if (color.isValid())
- return true;
if (!object->parent() || !object->parent()->style())
return false;
const SVGRenderStyle* parentSVGStyle = object->parent()->style()->svgStyle();
+ SVGPaint::SVGPaintType paintType = applyToFill ? parentSVGStyle->fillPaintType() : parentSVGStyle->strokePaintType();
+ if (paintType != SVGPaint::SVG_PAINTTYPE_RGBCOLOR && paintType != SVGPaint::SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR)
+ return false;
color = applyToFill ? parentSVGStyle->fillPaintColor() : parentSVGStyle->strokePaintColor();
return true;
}
-static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, bool& hasFallback)
{
ASSERT(object);
ASSERT(style);
+ hasFallback = false;
+
// If we have no style at all, ignore it.
const SVGRenderStyle* svgStyle = style->svgStyle();
if (!svgStyle)
@@ -78,10 +81,10 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
bool applyToFill = mode == ApplyToFillMode;
SVGPaint::SVGPaintType paintType = applyToFill ? svgStyle->fillPaintType() : svgStyle->strokePaintType();
- if (paintType == SVGPaint::SVG_PAINTTYPE_NONE)
- return 0;
+ ASSERT(paintType != SVGPaint::SVG_PAINTTYPE_NONE);
Color color;
+ bool hasColor = false;
switch (paintType) {
case SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR:
case SVGPaint::SVG_PAINTTYPE_RGBCOLOR:
@@ -90,6 +93,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR:
case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR:
color = applyToFill ? svgStyle->fillPaintColor() : svgStyle->strokePaintColor();
+ hasColor = true;
default:
break;
}
@@ -101,15 +105,15 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
// For SVG_PAINTTYPE_CURRENTCOLOR, 'color' already contains the 'visitedColor'.
if (visitedPaintType < SVGPaint::SVG_PAINTTYPE_URI_NONE && visitedPaintType != SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) {
const Color& visitedColor = applyToFill ? svgStyle->visitedLinkFillPaintColor() : svgStyle->visitedLinkStrokePaintColor();
- if (visitedColor.isValid())
- color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
+ color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
+ hasColor = true;
}
}
// If the primary resource is just a color, return immediately.
RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource();
if (paintType < SVGPaint::SVG_PAINTTYPE_URI_NONE) {
- if (!inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+ if (!hasColor && !inheritColorFromParentStyle(object, applyToFill, color))
return 0;
colorResource->setColor(color);
@@ -119,7 +123,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
// If no resources are associated with the given renderer, return the color resource.
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
if (!resources) {
- if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || !inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+ if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || (!hasColor && !inheritColorFromParentStyle(object, applyToFill, color)))
return 0;
colorResource->setColor(color);
@@ -129,7 +133,7 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
// If the requested resource is not available, return the color resource.
RenderSVGResource* uriResource = mode == ApplyToFillMode ? resources->fill() : resources->stroke();
if (!uriResource) {
- if (!inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+ if (!hasColor && !inheritColorFromParentStyle(object, applyToFill, color))
return 0;
colorResource->setColor(color);
@@ -137,19 +141,22 @@ static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode m
}
// The paint server resource exists, though it may be invalid (pattern with width/height=0). Pass the fallback color to our caller
- // so it can use the solid color painting resource, if applyResource() on the URI resource failed.
- fallbackColor = color;
+ // via sharedSolidPaintingResource so it can use the solid color painting resource, if applyResource() on the URI resource failed.
+ if (hasColor) {
+ colorResource->setColor(color);
+ hasFallback = true;
+ }
return uriResource;
}
-RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, bool& hasFallback)
{
- return requestPaintingResource(ApplyToFillMode, object, style, fallbackColor);
+ return requestPaintingResource(ApplyToFillMode, object, style, hasFallback);
}
-RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, bool& hasFallback)
{
- return requestPaintingResource(ApplyToStrokeMode, object, style, fallbackColor);
+ return requestPaintingResource(ApplyToStrokeMode, object, style, hasFallback);
}
RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
@@ -176,13 +183,28 @@ static inline void removeFromCacheAndInvalidateDependencies(RenderObject* object
if (!object->node() || !object->node()->isSVGElement())
return;
- HashSet<SVGElement*>* dependencies = object->document().accessSVGExtensions()->setOfElementsReferencingTarget(toSVGElement(object->node()));
+ SVGElementSet* dependencies = object->document().accessSVGExtensions().setOfElementsReferencingTarget(toSVGElement(object->node()));
if (!dependencies)
return;
- HashSet<SVGElement*>::iterator end = dependencies->end();
- for (HashSet<SVGElement*>::iterator it = dependencies->begin(); it != end; ++it) {
- if (RenderObject* renderer = (*it)->renderer())
+
+ // We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive
+ // reference graph adjustments on changes, so we need to break possible cycles here.
+ // This strong reference is safe, as it is guaranteed that this set will be emptied
+ // at the end of recursion.
+ typedef WillBeHeapHashSet<RawPtrWillBeMember<SVGElement> > SVGElementSet;
+ DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<SVGElementSet>, invalidatingDependencies, (adoptPtrWillBeNoop(new SVGElementSet)));
+
+ SVGElementSet::iterator end = dependencies->end();
+ for (SVGElementSet::iterator it = dependencies->begin(); it != end; ++it) {
+ if (RenderObject* renderer = (*it)->renderer()) {
+ if (UNLIKELY(!invalidatingDependencies->add(*it).isNewEntry)) {
+ // Reference cycle: we are in process of invalidating this dependant.
+ continue;
+ }
+
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, needsLayout);
+ invalidatingDependencies->remove(*it);
+ }
}
}
@@ -192,7 +214,7 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject*
ASSERT(object->node());
if (needsLayout && !object->documentBeingDestroyed())
- object->setNeedsLayout();
+ object->setNeedsLayoutAndFullPaintInvalidation();
removeFromCacheAndInvalidateDependencies(object, needsLayout);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h
index 676562dd01c..d1d3a89926b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResource.h
@@ -43,9 +43,8 @@ enum RenderSVGResourceMode {
ApplyToStrokeMode = 1 << 2,
ApplyToTextMode = 1 << 3 // used in combination with ApplyTo{Fill|Stroke}Mode
};
+typedef unsigned RenderSVGResourceModeFlags;
-class Color;
-class FloatRect;
class GraphicsContext;
class Path;
class RenderObject;
@@ -75,8 +74,9 @@ public:
}
// Helper utilities used in the render tree to access resources used for painting shapes/text (gradients & patterns & solid colors only)
- static RenderSVGResource* fillPaintingResource(RenderObject*, const RenderStyle*, Color& fallbackColor);
- static RenderSVGResource* strokePaintingResource(RenderObject*, const RenderStyle*, Color& fallbackColor);
+ // If hasFallback gets set to true, the sharedSolidPaintingResource is set to a fallback color.
+ static RenderSVGResource* fillPaintingResource(RenderObject*, const RenderStyle*, bool& hasFallback);
+ static RenderSVGResource* strokePaintingResource(RenderObject*, const RenderStyle*, bool& hasFallback);
static RenderSVGResourceSolidColor* sharedSolidPaintingResource();
static void markForLayoutAndParentResourceInvalidation(RenderObject*, bool needsLayout = true);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
index b98db0f7c86..62db92f8c1a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
@@ -24,15 +24,16 @@
#include "core/rendering/svg/RenderSVGResourceClipper.h"
-#include "RuntimeEnabledFeatures.h"
-#include "SVGNames.h"
-#include "core/frame/Frame.h"
+#include "core/SVGNames.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/HitTestResult.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGUseElement.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/DisplayList.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "wtf/TemporaryChange.h"
@@ -78,7 +79,7 @@ bool RenderSVGResourceClipper::applyStatefulResource(RenderObject* object, Graph
clearInvalidationMask();
- return applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context, clipperContext);
+ return applyClippingToContext(object, object->objectBoundingBox(), object->paintInvalidationRectInLocalCoordinates(), context, clipperContext);
}
bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
@@ -89,16 +90,16 @@ bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
WindRule clipRule = RULE_NONZERO;
Path clipPath = Path();
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
+ for (Element* childElement = ElementTraversal::firstWithin(*element()); childElement; childElement = ElementTraversal::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
if (!renderer)
continue;
// Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts.
if (renderer->isSVGText())
return false;
- if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGGraphicsElement())
+ if (!childElement->isSVGElement() || !toSVGElement(childElement)->isSVGGraphicsElement())
continue;
- SVGGraphicsElement* styled = toSVGGraphicsElement(childNode);
+ SVGGraphicsElement* styled = toSVGGraphicsElement(childElement);
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
@@ -127,7 +128,7 @@ bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context,
}
}
// Only one visible shape/path was found. Directly continue clipping and transform the content to userspace if necessary.
- if (toSVGClipPathElement(element())->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
@@ -148,7 +149,6 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
const FloatRect& repaintRect, GraphicsContext* context, ClipperContext& clipperContext)
{
ASSERT(target);
- ASSERT(target->node());
ASSERT(context);
ASSERT(clipperContext.state == ClipperContext::NotAppliedState);
ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
@@ -161,8 +161,8 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
// When drawing a clip for non-SVG elements, the CTM does not include the zoom factor.
// In this case, we need to apply the zoom scale explicitly - but only for clips with
// userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolved lengths).
- if (!target->node()->isSVGElement()
- && toSVGClipPathElement(element())->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
+ if (!target->isSVG()
+ && toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
ASSERT(style());
animatedLocalTransform.scale(style()->effectiveZoom());
}
@@ -238,7 +238,7 @@ void RenderSVGResourceClipper::drawClipMaskContent(GraphicsContext* context, con
ASSERT(context);
AffineTransform contentTransformation;
- SVGUnitTypes::SVGUnitType contentUnits = toSVGClipPathElement(element())->clipPathUnitsCurrentValue();
+ SVGUnitTypes::SVGUnitType contentUnits = toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue();
if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y());
contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
@@ -258,7 +258,10 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
ASSERT(context);
ASSERT(frame());
- context->beginRecording(repaintRectInLocalCoordinates());
+ // Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection
+ // with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and
+ // userSpaceOnUse units (http://crbug.com/294900).
+ context->beginRecording(strokeBoundingBox());
// Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints:
// - fill-opacity/stroke-opacity/opacity set to 1
@@ -268,9 +271,9 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
PaintBehavior oldBehavior = frame()->view()->paintBehavior();
frame()->view()->setPaintBehavior(oldBehavior | PaintBehaviorRenderingSVGMask);
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
RenderStyle* style = renderer->style();
@@ -278,13 +281,13 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
continue;
WindRule newClipRule = style->svgStyle()->clipRule();
- bool isUseElement = childNode->hasTagName(SVGNames::useTag);
+ bool isUseElement = isSVGUseElement(*childElement);
if (isUseElement) {
- SVGUseElement* useElement = toSVGUseElement(childNode);
- renderer = useElement->rendererClipChild();
+ SVGUseElement& useElement = toSVGUseElement(*childElement);
+ renderer = useElement.rendererClipChild();
if (!renderer)
continue;
- if (!useElement->hasAttribute(SVGNames::clip_ruleAttr))
+ if (!useElement.hasAttribute(SVGNames::clip_ruleAttr))
newClipRule = renderer->style()->svgStyle()->clipRule();
}
@@ -295,7 +298,7 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
context->setFillRule(newClipRule);
if (isUseElement)
- renderer = childNode->renderer();
+ renderer = childElement->renderer();
SVGRenderingContext::renderSubtree(context, renderer, contentTransformation);
}
@@ -308,16 +311,16 @@ PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext*
void RenderSVGResourceClipper::calculateClipContentRepaintRect()
{
// This is a rough heuristic to appraise the clip size and doesn't consider clip on clip.
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
- if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag))
+ if (!renderer->isSVGShape() && !renderer->isSVGText() && !isSVGUseElement(*childElement))
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
- m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+ m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->paintInvalidationRectInLocalCoordinates()));
}
m_clipBoundaries = toSVGClipPathElement(element())->animatedLocalTransform().mapRect(m_clipBoundaries);
}
@@ -329,7 +332,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
return false;
SVGClipPathElement* clipPathElement = toSVGClipPathElement(element());
- if (clipPathElement->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (clipPathElement->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
@@ -338,11 +341,11 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
point = clipPathElement->animatedLocalTransform().inverse().mapPoint(point);
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
- if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag))
+ if (!renderer->isSVGShape() && !renderer->isSVGText() && !isSVGUseElement(*childElement))
continue;
IntPoint hitPoint;
HitTestResult result(hitPoint);
@@ -353,7 +356,7 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
return false;
}
-FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
+FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject* object)
{
// Resource was not layouted yet. Give back the boundingBox of the object.
if (selfNeedsLayout())
@@ -362,7 +365,7 @@ FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
if (m_clipBoundaries.isEmpty())
calculateClipContentRepaintRect();
- if (toSVGClipPathElement(element())->clipPathUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
FloatRect objectBoundingBox = object->objectBoundingBox();
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h
index ae89b1e3df5..75a805859ff 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceClipper.h
@@ -45,13 +45,13 @@ public:
explicit RenderSVGResourceClipper(SVGClipPathElement*);
virtual ~RenderSVGResourceClipper();
- virtual const char* renderName() const { return "RenderSVGResourceClipper"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceClipper"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE FINAL;
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) OVERRIDE FINAL;
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) OVERRIDE;
// FIXME: Filters are also stateful resources that could benefit from having their state managed
// on the caller stack instead of the current hashmap. We should look at refactoring these
@@ -64,13 +64,13 @@ public:
// FIXME: We made applyClippingToContext public because we cannot call applyResource on HTML elements (it asserts on RenderObject::objectBoundingBox)
bool applyClippingToContext(RenderObject*, const FloatRect&, const FloatRect&, GraphicsContext*, ClipperContext&);
- FloatRect resourceBoundingBox(RenderObject*);
+ FloatRect resourceBoundingBox(const RenderObject*);
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
bool hitTestClipContent(const FloatRect&, const FloatPoint&);
- SVGUnitTypes::SVGUnitType clipPathUnits() const { return toSVGClipPathElement(element())->clipPathUnitsCurrentValue(); }
+ SVGUnitTypes::SVGUnitType clipPathUnits() const { return toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumValue(); }
static const RenderSVGResourceType s_resourceType;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
index 55405a77a08..8434f4fe4ee 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
@@ -21,7 +21,6 @@
#include "core/rendering/svg/RenderSVGResourceContainer.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/SVGRenderingContext.h"
@@ -32,7 +31,7 @@
namespace WebCore {
-static inline SVGDocumentExtensions* svgExtensionsFromElement(SVGElement* element)
+static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement* element)
{
ASSERT(element);
return element->document().accessSVGExtensions();
@@ -51,7 +50,7 @@ RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement* node)
RenderSVGResourceContainer::~RenderSVGResourceContainer()
{
if (m_registered)
- svgExtensionsFromElement(element())->removeResource(m_id);
+ svgExtensionsFromElement(element()).removeResource(m_id);
}
void RenderSVGResourceContainer::layout()
@@ -62,7 +61,6 @@ void RenderSVGResourceContainer::layout()
if (m_isInLayout)
return;
- LayoutRectRecorder recorder(*this);
TemporaryChange<bool> inLayoutChange(m_isInLayout, true);
RenderSVGHiddenContainer::layout();
@@ -92,8 +90,8 @@ void RenderSVGResourceContainer::idChanged()
removeAllClientsFromCache();
// Remove old id, that is guaranteed to be present in cache.
- SVGDocumentExtensions* extensions = svgExtensionsFromElement(element());
- extensions->removeResource(m_id);
+ SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
+ extensions.removeResource(m_id);
m_id = element()->getIdAttribute();
registerResource();
@@ -150,10 +148,10 @@ void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client,
break;
case RepaintInvalidation:
if (client->view()) {
- if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInLayout())
- client->setShouldDoFullRepaintAfterLayout(true);
+ if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && frameView()->isInPerformLayout())
+ client->setShouldDoFullPaintInvalidationAfterLayout(true);
else
- client->repaint();
+ client->paintInvalidationForWholeRenderer();
}
break;
case ParentOnlyInvalidation:
@@ -202,7 +200,7 @@ void RenderSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutSc
if (selfNeedsLayout())
return;
- setNeedsLayout(MarkContainingBlockChain, layoutScope);
+ setNeedsLayoutAndFullPaintInvalidation(MarkContainingBlockChain, layoutScope);
if (everHadLayout())
removeAllClientsFromCache();
@@ -210,33 +208,36 @@ void RenderSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutSc
void RenderSVGResourceContainer::registerResource()
{
- SVGDocumentExtensions* extensions = svgExtensionsFromElement(element());
- if (!extensions->hasPendingResource(m_id)) {
- extensions->addResource(m_id, this);
+ SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
+ if (!extensions.hasPendingResource(m_id)) {
+ extensions.addResource(m_id, this);
return;
}
- OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions->removePendingResource(m_id));
+ OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions.removePendingResource(m_id));
// Cache us with the new id.
- extensions->addResource(m_id, this);
+ extensions.addResource(m_id, this);
// Update cached resources of pending clients.
const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();
for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) {
ASSERT((*it)->hasPendingResources());
- extensions->clearHasPendingResourcesIfPossible(*it);
+ extensions.clearHasPendingResourcesIfPossible(*it);
RenderObject* renderer = (*it)->renderer();
if (!renderer)
continue;
- SVGResourcesCache::clientStyleChanged(renderer, StyleDifferenceLayout, renderer->style());
- renderer->setNeedsLayout();
+
+ StyleDifference diff;
+ diff.setNeedsFullLayout();
+ SVGResourcesCache::clientStyleChanged(renderer, diff, renderer->style());
+ renderer->setNeedsLayoutAndFullPaintInvalidation();
}
}
-bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
+static bool shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
{
- ASSERT_UNUSED(object, object);
+ ASSERT(object);
// This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline());
@@ -251,6 +252,26 @@ bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* obj
return true;
}
+AffineTransform RenderSVGResourceContainer::computeResourceSpaceTransform(RenderObject* object, const AffineTransform& baseTransform, const SVGRenderStyle* svgStyle, unsigned short resourceMode)
+{
+ AffineTransform computedSpaceTransform = baseTransform;
+ if (resourceMode & ApplyToTextMode) {
+ // Depending on the font scaling factor, we may need to apply an
+ // additional transform (scale-factor) the paintserver, since text
+ // painting removes the scale factor from the context. (See
+ // SVGInlineTextBox::paintTextWithShadows.)
+ AffineTransform additionalTextTransformation;
+ if (shouldTransformOnTextPainting(object, additionalTextTransformation))
+ computedSpaceTransform = additionalTextTransformation * computedSpaceTransform;
+ }
+ if (resourceMode & ApplyToStrokeMode) {
+ // Non-scaling stroke needs to reset the transform back to the host transform.
+ if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
+ computedSpaceTransform = transformOnNonScalingStroke(object, computedSpaceTransform);
+ }
+ return computedSpaceTransform;
+}
+
// FIXME: This does not belong here.
AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
{
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h
index 71d3c6f0cf1..52b50c394a3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceContainer.h
@@ -33,12 +33,11 @@ public:
explicit RenderSVGResourceContainer(SVGElement*);
virtual ~RenderSVGResourceContainer();
- virtual void layout();
+ virtual void layout() OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
virtual bool isSVGResourceContainer() const OVERRIDE FINAL { return true; }
- static bool shouldTransformOnTextPainting(RenderObject*, AffineTransform&);
static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform);
void idChanged();
@@ -64,6 +63,8 @@ protected:
void clearInvalidationMask() { m_invalidationMask = 0; }
+ static AffineTransform computeResourceSpaceTransform(RenderObject*, const AffineTransform& baseTransform, const SVGRenderStyle*, unsigned short resourceMode);
+
bool m_isInLayout;
private:
@@ -86,21 +87,21 @@ private:
HashSet<RenderLayer*> m_clientLayers;
};
-inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document& document, const AtomicString& id)
+inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(TreeScope& treeScope, const AtomicString& id)
{
if (id.isEmpty())
return 0;
- if (RenderSVGResourceContainer* renderResource = document.accessSVGExtensions()->resourceById(id))
+ if (RenderSVGResourceContainer* renderResource = treeScope.document().accessSVGExtensions().resourceById(id))
return renderResource;
return 0;
}
template<typename Renderer>
-Renderer* getRenderSVGResourceById(Document& document, const AtomicString& id)
+Renderer* getRenderSVGResourceById(TreeScope& treeScope, const AtomicString& id)
{
- if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id))
+ if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(treeScope, id))
return container->cast<Renderer>();
return 0;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
index 840c563c4c2..80f0a30a0c2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
@@ -30,9 +30,9 @@
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
+#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
#include "platform/graphics/filters/SourceAlpha.h"
#include "platform/graphics/filters/SourceGraphic.h"
-#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
using namespace std;
@@ -50,6 +50,11 @@ RenderSVGResourceFilter::~RenderSVGResourceFilter()
m_filter.clear();
}
+bool RenderSVGResourceFilter::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isSVGResourceFilterPrimitive();
+}
+
void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation)
{
m_filter.clear();
@@ -77,11 +82,7 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter*
// Add effects to the builder
RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(SourceGraphic::create(filter), SourceAlpha::create(filter));
- for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
- if (!node->isSVGElement())
- continue;
-
- SVGElement* element = toSVGElement(node);
+ for (SVGElement* element = Traversal<SVGElement>::firstChild(*filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) {
if (!element->isFilterEffect() || !element->renderer())
continue;
@@ -89,46 +90,40 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter*
RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter);
if (!effect) {
builder->clearEffects();
- return 0;
+ return nullptr;
}
builder->appendEffectToEffectReferences(effect, effectElement->renderer());
effectElement->setStandardAttributes(effect.get());
- effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnitsCurrentValue(), targetBoundingBox));
+ effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->currentValue()->enumValue(), targetBoundingBox));
effect->setOperatingColorSpace(
effectElement->renderer()->style()->svgStyle()->colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
- builder->add(effectElement->resultCurrentValue(), effect);
+ builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect);
}
return builder.release();
}
-bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
+void RenderSVGResourceFilter::adjustScaleForMaximumImageSize(const FloatSize& size, FloatSize& filterScale)
{
- bool matchesFilterSize = true;
- if (size.width() > kMaxFilterSize) {
- scale.setWidth(scale.width() * kMaxFilterSize / size.width());
- matchesFilterSize = false;
- }
- if (size.height() > kMaxFilterSize) {
- scale.setHeight(scale.height() * kMaxFilterSize / size.height());
- matchesFilterSize = false;
- }
+ FloatSize scaledSize(size);
+ scaledSize.scale(filterScale.width(), filterScale.height());
+ float scaledArea = scaledSize.width() * scaledSize.height();
+
+ if (scaledArea <= FilterEffect::maxFilterArea())
+ return;
- return matchesFilterSize;
+ // If area of scaled size is bigger than the upper limit, adjust the scale
+ // to fit.
+ filterScale.scale(sqrt(FilterEffect::maxFilterArea() / scaledArea));
}
-static bool createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform,
- OwnPtr<ImageBuffer>& imageBuffer, bool accelerated)
+static bool createImageBuffer(const Filter* filter, OwnPtr<ImageBuffer>& imageBuffer)
{
- IntRect paintRect = SVGRenderingContext::calculateImageBufferRect(targetRect, absoluteTransform);
+ IntRect paintRect = filter->sourceImageRect();
// Don't create empty ImageBuffers.
if (paintRect.isEmpty())
return false;
- OwnPtr<ImageBufferSurface> surface;
- if (accelerated)
- surface = adoptPtr(new AcceleratedImageBufferSurface(paintRect.size()));
- if (!accelerated || !surface->isValid())
- surface = adoptPtr(new UnacceleratedImageBufferSurface(paintRect.size()));
+ OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSurface(paintRect.size()));
if (!surface->isValid())
return false;
OwnPtr<ImageBuffer> image = ImageBuffer::create(surface.release());
@@ -137,12 +132,71 @@ static bool createImageBuffer(const FloatRect& targetRect, const AffineTransform
ASSERT(imageContext);
imageContext->translate(-paintRect.x(), -paintRect.y());
- imageContext->concatCTM(absoluteTransform);
-
+ imageContext->concatCTM(filter->absoluteTransform());
imageBuffer = image.release();
return true;
}
+static void beginDeferredFilter(GraphicsContext* context, FilterData* filterData, SVGFilterElement* filterElement)
+{
+ SkiaImageFilterBuilder builder(context);
+ RefPtr<ImageFilter> imageFilter = builder.build(filterData->builder->lastEffect(), ColorSpaceDeviceRGB);
+ // FIXME: Remove the cache when impl-size painting is enabled on every platform and the non impl-side painting path is removed
+ if (!context->isRecordingCanvas()) // Recording canvases do not use the cache
+ filterData->filter->enableCache();
+ FloatRect boundaries = enclosingIntRect(filterData->boundaries);
+ context->save();
+ float scaledArea = boundaries.width() * boundaries.height();
+
+ // If area of scaled size is bigger than the upper limit, adjust the scale
+ // to fit.
+ if (scaledArea > FilterEffect::maxFilterArea()) {
+ float scale = sqrtf(FilterEffect::maxFilterArea() / scaledArea);
+ context->scale(scale, scale);
+ }
+ // Clip drawing of filtered image to primitive boundaries.
+ context->clipRect(boundaries);
+ if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
+ // Get boundaries in device coords.
+ // FIXME: See crbug.com/382491. Is the use of getCTM OK here, given it does not include device
+ // zoom or High DPI adjustments?
+ FloatSize size = context->getCTM().mapSize(boundaries.size());
+ // Compute the scale amount required so that the resulting offscreen is exactly filterResX by filterResY pixels.
+ float filterResScaleX = filterElement->filterResX()->currentValue()->value() / size.width();
+ float filterResScaleY = filterElement->filterResY()->currentValue()->value() / size.height();
+ // Scale the CTM so the primitive is drawn to filterRes.
+ context->scale(filterResScaleX, filterResScaleY);
+ // Create a resize filter with the inverse scale.
+ AffineTransform resizeMatrix;
+ resizeMatrix.scale(1 / filterResScaleX, 1 / filterResScaleY);
+ imageFilter = builder.buildTransform(resizeMatrix, imageFilter.get());
+ }
+ // If the CTM contains rotation or shearing, apply the filter to
+ // the unsheared/unrotated matrix, and do the shearing/rotation
+ // as a final pass.
+ AffineTransform ctm = context->getCTM();
+ if (ctm.b() || ctm.c()) {
+ AffineTransform scaleAndTranslate;
+ scaleAndTranslate.translate(ctm.e(), ctm.f());
+ scaleAndTranslate.scale(ctm.xScale(), ctm.yScale());
+ ASSERT(scaleAndTranslate.isInvertible());
+ AffineTransform shearAndRotate = scaleAndTranslate.inverse();
+ shearAndRotate.multiply(ctm);
+ context->setCTM(scaleAndTranslate);
+ imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get());
+ }
+ context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get());
+}
+
+static void endDeferredFilter(GraphicsContext* context, FilterData* filterData)
+{
+ context->endLayer();
+ context->restore();
+ // FIXME: Remove the cache when impl-size painting is enabled on every platform and the non impl-side painting path is removed
+ if (!context->isRecordingCanvas()) // Recording canvases do not use the cache
+ filterData->filter->disableCache();
+}
+
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(object);
@@ -151,10 +205,16 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
clearInvalidationMask();
+ bool deferredFiltersEnabled = object->document().settings()->deferredFiltersEnabled();
if (m_filter.contains(object)) {
FilterData* filterData = m_filter.get(object);
if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
filterData->state = FilterData::CycleDetected;
+ if (deferredFiltersEnabled && filterData->state == FilterData::Built) {
+ SVGFilterElement* filterElement = toSVGFilterElement(element());
+ beginDeferredFilter(context, filterData, filterElement);
+ return true;
+ }
return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
}
@@ -162,64 +222,65 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
FloatRect targetBoundingBox = object->objectBoundingBox();
SVGFilterElement* filterElement = toSVGFilterElement(element());
- filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnitsCurrentValue(), targetBoundingBox);
+ filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox);
if (filterData->boundaries.isEmpty())
return false;
// Determine absolute transformation matrix for filter.
AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform);
+ SVGRenderingContext::calculateDeviceSpaceTransformation(object, absoluteTransform);
if (!absoluteTransform.isInvertible())
return false;
- // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
- filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);
+ // Filters cannot handle a full transformation, only scales in each direction.
+ FloatSize filterScale;
+
+ // Calculate the scale factor for the filter.
+ // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
+ if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
+ // If resolution is specified, scale to match it.
+ filterScale = FloatSize(
+ filterElement->filterResX()->currentValue()->value() / filterData->boundaries.width(),
+ filterElement->filterResY()->currentValue()->value() / filterData->boundaries.height());
+ } else {
+ // Otherwise, use the scale of the absolute transform.
+ filterScale = FloatSize(absoluteTransform.xScale(), absoluteTransform.yScale());
+ }
+ // The size of the scaled filter boundaries shouldn't be bigger than kMaxFilterSize.
+ // Intermediate filters are limited by the filter boundaries so they can't be bigger than this.
+ adjustScaleForMaximumImageSize(filterData->boundaries.size(), filterScale);
- // Determine absolute boundaries of the filter and the drawing region.
- FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
filterData->drawingRegion = object->strokeBoundingBox();
filterData->drawingRegion.intersect(filterData->boundaries);
- FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(filterData->drawingRegion);
+ FloatRect absoluteDrawingRegion = filterData->drawingRegion;
+ if (!deferredFiltersEnabled)
+ absoluteDrawingRegion.scale(filterScale.width(), filterScale.height());
+
+ IntRect intDrawingRegion = enclosingIntRect(absoluteDrawingRegion);
// Create the SVGFilter object.
- bool primitiveBoundingBoxMode = filterElement->primitiveUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
- filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
+ bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ filterData->shearFreeAbsoluteTransform = AffineTransform();
+ if (!deferredFiltersEnabled)
+ filterData->shearFreeAbsoluteTransform.scale(filterScale.width(), filterScale.height());
+ filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
// Create all relevant filter primitives.
filterData->builder = buildPrimitives(filterData->filter.get());
if (!filterData->builder)
return false;
- // Calculate the scale factor for the use of filterRes.
- // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
- FloatSize scale(1, 1);
- if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
- scale.setWidth(filterElement->filterResXCurrentValue() / absoluteFilterBoundaries.width());
- scale.setHeight(filterElement->filterResYCurrentValue() / absoluteFilterBoundaries.height());
- }
-
- if (scale.isEmpty())
- return false;
-
- // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
- FloatRect tempSourceRect = absoluteDrawingRegion;
- tempSourceRect.scale(scale.width(), scale.height());
- fitsInMaximumImageSize(tempSourceRect.size(), scale);
-
- // Set the scale level in SVGFilter.
- filterData->filter->setFilterResolution(scale);
-
FilterEffect* lastEffect = filterData->builder->lastEffect();
if (!lastEffect)
return false;
lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
- FloatRect subRegion = lastEffect->maxEffectRect();
- // At least one FilterEffect has a too big image size,
- // recalculate the effect sizes with new scale factors.
- if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
- filterData->filter->setFilterResolution(scale);
- lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
+
+ if (deferredFiltersEnabled) {
+ FilterData* data = filterData.get();
+ m_filter.set(object, filterData.release());
+ beginDeferredFilter(context, data, filterElement);
+ return true;
}
// If the drawingRegion is empty, we have something like <g filter=".."/>.
@@ -231,23 +292,14 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
return false;
}
- // Change the coordinate transformation applied to the filtered element to reflect the resolution of the filter.
- AffineTransform effectiveTransform;
- effectiveTransform.scale(scale.width(), scale.height());
- effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);
-
OwnPtr<ImageBuffer> sourceGraphic;
- bool isAccelerated = object->document().settings()->acceleratedFiltersEnabled();
- if (!createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, isAccelerated)) {
+ if (!createImageBuffer(filterData->filter.get(), sourceGraphic)) {
ASSERT(!m_filter.contains(object));
filterData->savedContext = context;
m_filter.set(object, filterData.release());
return false;
}
- // Set the rendering mode from the page's settings.
- filterData->filter->setIsAccelerated(isAccelerated);
-
GraphicsContext* sourceGraphicContext = sourceGraphic->context();
ASSERT(sourceGraphicContext);
@@ -272,6 +324,12 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
if (!filterData)
return;
+ if (object->document().settings()->deferredFiltersEnabled() && (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Built)) {
+ endDeferredFilter(context, filterData);
+ filterData->state = FilterData::Built;
+ return;
+ }
+
switch (filterData->state) {
case FilterData::MarkedForRemoval:
m_filter.remove(object);
@@ -319,22 +377,16 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
ImageBuffer* resultImage = lastEffect->asImageBuffer();
if (resultImage) {
- context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());
-
- context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
- context->drawImageBuffer(resultImage, lastEffect->absolutePaintRect());
- context->scale(filterData->filter->filterResolution());
-
- context->concatCTM(filterData->shearFreeAbsoluteTransform);
+ context->drawImageBuffer(resultImage, filterData->filter->mapAbsoluteRectToLocalRect(lastEffect->absolutePaintRect()));
}
}
filterData->sourceGraphicBuffer.clear();
}
-FloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object)
+FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject* object)
{
if (SVGFilterElement* element = toSVGFilterElement(this->element()))
- return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnitsCurrentValue(), object->objectBoundingBox());
+ return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnits()->currentValue()->enumValue(), object->objectBoundingBox());
return FloatRect();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h
index 6455b039284..1c679130ccc 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilter.h
@@ -60,30 +60,32 @@ public:
explicit RenderSVGResourceFilter(SVGFilterElement*);
virtual ~RenderSVGResourceFilter();
- virtual const char* renderName() const { return "RenderSVGResourceFilter"; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceFilter"; }
virtual bool isSVGResourceFilter() const OVERRIDE { return true; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE;
- FloatRect resourceBoundingBox(RenderObject*);
+ FloatRect resourceBoundingBox(const RenderObject*);
PassRefPtr<SVGFilterBuilder> buildPrimitives(SVGFilter*);
- SVGUnitTypes::SVGUnitType filterUnits() const { return toSVGFilterElement(element())->filterUnitsCurrentValue(); }
- SVGUnitTypes::SVGUnitType primitiveUnits() const { return toSVGFilterElement(element())->primitiveUnitsCurrentValue(); }
+ SVGUnitTypes::SVGUnitType filterUnits() const { return toSVGFilterElement(element())->filterUnits()->currentValue()->enumValue(); }
+ SVGUnitTypes::SVGUnitType primitiveUnits() const { return toSVGFilterElement(element())->primitiveUnits()->currentValue()->enumValue(); }
void primitiveAttributeChanged(RenderObject*, const QualifiedName&);
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
FloatRect drawingRegion(RenderObject*) const;
private:
- bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
+ void adjustScaleForMaximumImageSize(const FloatSize&, FloatSize&);
typedef HashMap<RenderObject*, OwnPtr<FilterData> > FilterMap;
FilterMap m_filter;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
index e34449d35ea..f7fce429304 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
@@ -40,16 +40,17 @@ void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, cons
return;
ASSERT(filter->isSVGResourceFilter());
- if (diff == StyleDifferenceEqual || !oldStyle)
+ if (diff.hasNoChange() || !oldStyle)
return;
const SVGRenderStyle* newStyle = this->style()->svgStyle();
- if (element()->hasTagName(SVGNames::feFloodTag)) {
+ ASSERT(element());
+ if (isSVGFEFloodElement(*element())) {
if (newStyle->floodColor() != oldStyle->svgStyle()->floodColor())
toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
if (newStyle->floodOpacity() != oldStyle->svgStyle()->floodOpacity())
toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
- } else if (element()->hasTagName(SVGNames::feDiffuseLightingTag) || element()->hasTagName(SVGNames::feSpecularLightingTag)) {
+ } else if (isSVGFEDiffuseLightingElement(*element()) || isSVGFESpecularLightingElement(*element())) {
if (newStyle->lightingColor() != oldStyle->svgStyle()->lightingColor())
toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
index 704df3d4075..b2a293d68fe 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
@@ -38,10 +38,12 @@ public:
{
}
- virtual void styleDidChange(StyleDifference, const RenderStyle*);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE { return false; }
- virtual const char* renderName() const { return "RenderSVGResourceFilterPrimitive"; }
- virtual bool isSVGResourceFilterPrimitive() const { return true; }
+ virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceFilterPrimitive"; }
+ virtual bool isSVGResourceFilterPrimitive() const OVERRIDE { return true; }
inline void primitiveAttributeChanged(const QualifiedName& attribute)
{
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
index 4e432a56082..6f44a65b116 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
@@ -81,12 +81,10 @@ 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).iterator->value;
+ OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).storedValue->value;
if (!gradientData)
gradientData = adoptPtr(new GradientData);
- bool isPaintingText = resourceMode & ApplyToTextMode;
-
// Create gradient object
if (!gradientData->gradient) {
buildGradient(gradientData.get());
@@ -101,36 +99,29 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
calculateGradientTransform(gradientTransform);
gradientData->userspaceTransform *= gradientTransform;
- if (isPaintingText) {
- // Depending on font scaling factor, we may need to rescale the gradient here since
- // text painting removes the scale factor from the context.
- AffineTransform additionalTextTransform;
- if (shouldTransformOnTextPainting(object, additionalTextTransform))
- gradientData->userspaceTransform *= additionalTextTransform;
- }
- gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
}
if (!gradientData->gradient)
return false;
+ const SVGRenderStyle* svgStyle = style->svgStyle();
+ ASSERT(svgStyle);
+
+ AffineTransform computedGradientSpaceTransform = computeResourceSpaceTransform(object, gradientData->userspaceTransform, svgStyle, resourceMode);
+ gradientData->gradient->setGradientSpaceTransform(computedGradientSpaceTransform);
+
// Draw gradient
context->save();
- if (isPaintingText)
+ if (resourceMode & ApplyToTextMode)
context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFill : TextModeStroke);
- const SVGRenderStyle* svgStyle = style->svgStyle();
- ASSERT(svgStyle);
-
if (resourceMode & ApplyToFillMode) {
- context->setAlpha(svgStyle->fillOpacity());
+ context->setAlphaAsFloat(svgStyle->fillOpacity());
context->setFillGradient(gradientData->gradient);
context->setFillRule(svgStyle->fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
- if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
- gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(object, gradientData->userspaceTransform));
- context->setAlpha(svgStyle->strokeOpacity());
+ context->setAlphaAsFloat(svgStyle->strokeOpacity());
context->setStrokeGradient(gradientData->gradient);
SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
index ba1c3d27884..b829e403004 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
@@ -33,15 +33,15 @@ public:
explicit RenderSVGResourceLinearGradient(SVGLinearGradientElement*);
virtual ~RenderSVGResourceLinearGradient();
- virtual const char* renderName() const { return "RenderSVGResourceLinearGradient"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceLinearGradient"; }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
- virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
- virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
- virtual bool collectGradientAttributes(SVGGradientElement*);
- virtual void buildGradient(GradientData*) const;
+ virtual SVGUnitTypes::SVGUnitType gradientUnits() const OVERRIDE { return m_attributes.gradientUnits(); }
+ virtual void calculateGradientTransform(AffineTransform& transform) OVERRIDE { transform = m_attributes.gradientTransform(); }
+ virtual bool collectGradientAttributes(SVGGradientElement*) OVERRIDE;
+ virtual void buildGradient(GradientData*) const OVERRIDE;
FloatPoint startPoint(const LinearGradientAttributes&) const;
FloatPoint endPoint(const LinearGradientAttributes&) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
index d3de3b7cc64..be93b479b2d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
@@ -23,7 +23,7 @@
#include "core/rendering/svg/RenderSVGResourceMarker.h"
-#include "core/rendering/LayoutRectRecorder.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/svg/RenderSVGContainer.h"
#include "core/rendering/svg/SVGRenderSupport.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
@@ -49,13 +49,8 @@ void RenderSVGResourceMarker::layout()
if (m_isInLayout)
return;
- LayoutRectRecorder recorder(*this);
TemporaryChange<bool> inLayoutChange(m_isInLayout, true);
- // Invalidate all resources if our layout changed.
- if (everHadLayout() && selfNeedsLayout())
- removeAllClientsFromCache();
-
// RenderSVGHiddenContainer overwrites layout(). We need the
// layouting of RenderSVGContainer for calculating local
// transformations and repaint.
@@ -83,7 +78,7 @@ void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo)
FloatRect RenderSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const
{
- FloatRect coordinates = RenderSVGContainer::repaintRectInLocalCoordinates();
+ FloatRect coordinates = RenderSVGContainer::paintInvalidationRectInLocalCoordinates();
// Map repaint rect into parent coordinate space, in which the marker boundaries have to be evaluated
coordinates = localToParentTransform().mapRect(coordinates);
@@ -105,7 +100,7 @@ FloatPoint RenderSVGResourceMarker::referencePoint() const
ASSERT(marker);
SVGLengthContext lengthContext(marker);
- return FloatPoint(marker->refXCurrentValue().value(lengthContext), marker->refYCurrentValue().value(lengthContext));
+ return FloatPoint(marker->refX()->currentValue()->value(lengthContext), marker->refY()->currentValue()->value(lengthContext));
}
float RenderSVGResourceMarker::angle() const
@@ -114,8 +109,8 @@ float RenderSVGResourceMarker::angle() const
ASSERT(marker);
float angle = -1;
- if (marker->orientTypeCurrentValue() == SVGMarkerOrientAngle)
- angle = marker->orientAngleCurrentValue().value();
+ if (marker->orientType()->currentValue()->enumValue() == SVGMarkerOrientAngle)
+ angle = marker->orientAngle()->currentValue()->value();
return angle;
}
@@ -126,7 +121,7 @@ AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint&
ASSERT(marker);
float markerAngle = angle();
- bool useStrokeWidth = marker->markerUnitsCurrentValue() == SVGMarkerUnitsStrokeWidth;
+ bool useStrokeWidth = marker->markerUnits()->currentValue()->enumValue() == SVGMarkerUnitsStrokeWidth;
AffineTransform transform;
transform.translate(origin.x(), origin.y());
@@ -142,12 +137,15 @@ void RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform&
// An empty viewBox disables rendering.
SVGMarkerElement* marker = toSVGMarkerElement(element());
ASSERT(marker);
- if (marker->hasAttribute(SVGNames::viewBoxAttr) && marker->viewBoxCurrentValue().isValid() && marker->viewBoxCurrentValue().isEmpty())
+ if (marker->hasAttribute(SVGNames::viewBoxAttr) && marker->viewBox()->currentValue()->isValid() && marker->viewBox()->currentValue()->value().isEmpty())
return;
PaintInfo info(paintInfo);
- GraphicsContextStateSaver stateSaver(*info.context);
- info.applyTransform(transform);
+ GraphicsContextStateSaver stateSaver(*info.context, false);
+ if (!transform.isIdentity()) {
+ stateSaver.save();
+ info.applyTransform(transform, false);
+ }
RenderSVGContainer::paint(info, IntPoint());
}
@@ -181,8 +179,8 @@ void RenderSVGResourceMarker::calcViewport()
ASSERT(marker);
SVGLengthContext lengthContext(marker);
- float w = marker->markerWidthCurrentValue().value(lengthContext);
- float h = marker->markerHeightCurrentValue().value(lengthContext);
+ float w = marker->markerWidth()->currentValue()->value(lengthContext);
+ float h = marker->markerHeight()->currentValue()->value(lengthContext);
m_viewport = FloatRect(0, 0, w, h);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h
index 625b37a652a..ba31fb21e45 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMarker.h
@@ -28,7 +28,6 @@
namespace WebCore {
-class AffineTransform;
class RenderObject;
class RenderSVGResourceMarker FINAL : public RenderSVGResourceContainer {
@@ -36,30 +35,30 @@ public:
explicit RenderSVGResourceMarker(SVGMarkerElement*);
virtual ~RenderSVGResourceMarker();
- virtual const char* renderName() const { return "RenderSVGResourceMarker"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceMarker"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
void draw(PaintInfo&, const AffineTransform&);
// Calculates marker boundaries, mapped to the target element's coordinate space
FloatRect markerBoundaries(const AffineTransform& markerTransformation) const;
- virtual void applyViewportClip(PaintInfo&);
- virtual void layout();
- virtual void calcViewport();
+ virtual void applyViewportClip(PaintInfo&) OVERRIDE;
+ virtual void layout() OVERRIDE;
+ virtual void calcViewport() OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const;
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE;
AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) { return false; }
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) OVERRIDE { return false; }
FloatPoint referencePoint() const;
float angle() const;
- SVGMarkerUnitsType markerUnits() const { return toSVGMarkerElement(element())->markerUnitsCurrentValue(); }
+ SVGMarkerUnitsType markerUnits() const { return toSVGMarkerElement(element())->markerUnits()->currentValue()->enumValue(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
index 43c64ca081d..98a6d4c7639 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
@@ -66,8 +66,8 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
clearInvalidationMask();
- FloatRect repaintRect = object->repaintRectInLocalCoordinates();
- if (repaintRect.isEmpty() || !element()->hasChildNodes())
+ FloatRect repaintRect = object->paintInvalidationRectInLocalCoordinates();
+ if (repaintRect.isEmpty() || !element()->hasChildren())
return false;
// Content layer start.
@@ -85,7 +85,7 @@ void RenderSVGResourceMasker::postApplyResource(RenderObject* object, GraphicsCo
ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
- FloatRect repaintRect = object->repaintRectInLocalCoordinates();
+ FloatRect repaintRect = object->paintInvalidationRectInLocalCoordinates();
const SVGRenderStyle* svgStyle = style()->svgStyle();
ASSERT(svgStyle);
@@ -115,7 +115,7 @@ void RenderSVGResourceMasker::drawMaskForRenderer(GraphicsContext* context, cons
ASSERT(context);
AffineTransform contentTransformation;
- SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnitsCurrentValue();
+ SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue();
if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y());
contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
@@ -133,10 +133,13 @@ PassRefPtr<DisplayList> RenderSVGResourceMasker::asDisplayList(GraphicsContext*
{
ASSERT(context);
- context->beginRecording(repaintRectInLocalCoordinates());
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ // Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection
+ // with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and
+ // userSpaceOnUse units (http://crbug.com/294900).
+ context->beginRecording(strokeBoundingBox());
+ for (Element* childElement = ElementTraversal::firstWithin(*element()); childElement; childElement = ElementTraversal::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!childElement->isSVGElement() || !renderer)
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
@@ -150,24 +153,24 @@ PassRefPtr<DisplayList> RenderSVGResourceMasker::asDisplayList(GraphicsContext*
void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
{
- for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) {
- RenderObject* renderer = childNode->renderer();
- if (!childNode->isSVGElement() || !renderer)
+ for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
+ RenderObject* renderer = childElement->renderer();
+ if (!renderer)
continue;
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
- m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+ m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->paintInvalidationRectInLocalCoordinates()));
}
}
-FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object)
+FloatRect RenderSVGResourceMasker::resourceBoundingBox(const RenderObject* object)
{
SVGMaskElement* maskElement = toSVGMaskElement(element());
ASSERT(maskElement);
FloatRect objectBoundingBox = object->objectBoundingBox();
- FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(maskElement, maskElement->maskUnitsCurrentValue(), objectBoundingBox);
+ FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(maskElement, maskElement->maskUnits()->currentValue()->enumValue(), objectBoundingBox);
// Resource was not layouted yet. Give back clipping rect of the mask.
if (selfNeedsLayout())
@@ -177,7 +180,7 @@ FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object)
calculateMaskContentRepaintRect();
FloatRect maskRect = m_maskContentBoundaries;
- if (maskElement->maskContentUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ if (maskElement->maskContentUnits()->currentValue()->value() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h
index 2af52752127..e05fc0d9b95 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceMasker.h
@@ -25,7 +25,6 @@
#include "core/svg/SVGUnitTypes.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntSize.h"
-#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageBuffer.h"
#include "wtf/HashMap.h"
@@ -34,24 +33,25 @@
namespace WebCore {
class DisplayList;
+class GraphicsContext;
class RenderSVGResourceMasker FINAL : public RenderSVGResourceContainer {
public:
explicit RenderSVGResourceMasker(SVGMaskElement*);
virtual ~RenderSVGResourceMasker();
- virtual const char* renderName() const { return "RenderSVGResourceMasker"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceMasker"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) OVERRIDE;
- FloatRect resourceBoundingBox(RenderObject*);
+ FloatRect resourceBoundingBox(const RenderObject*);
- SVGUnitTypes::SVGUnitType maskUnits() const { return toSVGMaskElement(element())->maskUnitsCurrentValue(); }
- SVGUnitTypes::SVGUnitType maskContentUnits() const { return toSVGMaskElement(element())->maskContentUnitsCurrentValue(); }
+ SVGUnitTypes::SVGUnitType maskUnits() const { return toSVGMaskElement(element())->maskUnits()->currentValue()->enumValue(); }
+ SVGUnitTypes::SVGUnitType maskContentUnits() const { return toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue(); }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
private:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
index c107a793f4a..401a29057a8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
@@ -53,6 +53,7 @@ void RenderSVGResourcePattern::removeClientFromCache(RenderObject* client, bool
PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsigned short resourceMode)
{
+ ASSERT(object);
PatternData* currentData = m_patternMap.get(object);
if (currentData && currentData->pattern)
return currentData;
@@ -84,19 +85,18 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
return 0;
AffineTransform absoluteTransformIgnoringRotation;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation);
+ SVGRenderingContext::calculateDeviceSpaceTransformation(object, absoluteTransformIgnoringRotation);
// Ignore 2D rotation, as it doesn't affect the size of the tile.
SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
FloatRect absoluteTileBoundaries = absoluteTransformIgnoringRotation.mapRect(tileBoundaries);
- FloatRect clampedAbsoluteTileBoundaries;
// Scale the tile size to match the scale level of the patternTransform.
absoluteTileBoundaries.scale(static_cast<float>(m_attributes.patternTransform().xScale()),
static_cast<float>(m_attributes.patternTransform().yScale()));
// Build tile image.
- OwnPtr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
+ OwnPtr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform);
if (!tileImage)
return 0;
@@ -117,18 +117,10 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign
if (!patternTransform.isIdentity())
patternData->transform = patternTransform * patternData->transform;
- // Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows.
- if (resourceMode & ApplyToTextMode) {
- AffineTransform additionalTextTransformation;
- if (shouldTransformOnTextPainting(object, additionalTextTransformation))
- patternData->transform *= additionalTextTransformation;
- }
- patternData->pattern->setPatternSpaceTransform(patternData->transform);
-
// Various calls above may trigger invalidations in some fringe cases (ImageBuffer allocation
// failures in the SVG image cache for example). To avoid having our PatternData deleted by
// removeAllClientsFromCache(), we only make it visible in the cache at the very end.
- return m_patternMap.set(object, patternData.release()).iterator->value.get();
+ return m_patternMap.set(object, patternData.release()).storedValue->value.get();
}
bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
@@ -150,20 +142,21 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
if (!patternData)
return false;
- // Draw pattern
- context->save();
-
const SVGRenderStyle* svgStyle = style->svgStyle();
ASSERT(svgStyle);
+ AffineTransform computedPatternSpaceTransform = computeResourceSpaceTransform(object, patternData->transform, svgStyle, resourceMode);
+ patternData->pattern->setPatternSpaceTransform(computedPatternSpaceTransform);
+
+ // Draw pattern
+ context->save();
+
if (resourceMode & ApplyToFillMode) {
- context->setAlpha(svgStyle->fillOpacity());
+ context->setAlphaAsFloat(svgStyle->fillOpacity());
context->setFillPattern(patternData->pattern);
context->setFillRule(svgStyle->fillRule());
} else if (resourceMode & ApplyToStrokeMode) {
- if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
- patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform));
- context->setAlpha(svgStyle->strokeOpacity());
+ context->setAlphaAsFloat(svgStyle->strokeOpacity());
context->setStrokePattern(patternData->pattern);
SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
}
@@ -235,10 +228,9 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes,
const FloatRect& tileBoundaries,
const FloatRect& absoluteTileBoundaries,
- const AffineTransform& tileImageTransform,
- FloatRect& clampedAbsoluteTileBoundaries) const
+ const AffineTransform& tileImageTransform) const
{
- clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
+ FloatRect clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
IntSize imageSize(roundedIntSize(clampedAbsoluteTileBoundaries.size()));
if (imageSize.isEmpty())
@@ -250,11 +242,12 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
GraphicsContext* tileImageContext = tileImage->context();
ASSERT(tileImageContext);
IntSize unclampedImageSize(roundedIntSize(absoluteTileBoundaries.size()));
- tileImageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTileBoundaries.width(), unclampedImageSize.height() / absoluteTileBoundaries.height()));
+ tileImageContext->scale(unclampedImageSize.width() / absoluteTileBoundaries.width(), unclampedImageSize.height() / absoluteTileBoundaries.height());
// The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation).
- tileImageContext->scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
- clampedAbsoluteTileBoundaries.height() / tileBoundaries.height()));
+ tileImageContext->scale(
+ clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
+ clampedAbsoluteTileBoundaries.height() / tileBoundaries.height());
// Apply tile image transformations.
if (!tileImageTransform.isIdentity())
@@ -265,12 +258,12 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
contentTransformation = tileImageTransform;
// Draw the content into the ImageBuffer.
- for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) {
- if (!node->isSVGElement() || !node->renderer())
+ for (Element* element = ElementTraversal::firstWithin(*attributes.patternContentElement()); element; element = ElementTraversal::nextSibling(*element)) {
+ if (!element->isSVGElement() || !element->renderer())
continue;
- if (node->renderer()->needsLayout())
+ if (element->renderer()->needsLayout())
return nullptr;
- SVGRenderingContext::renderSubtree(tileImage->context(), node->renderer(), contentTransformation);
+ SVGRenderingContext::renderSubtree(tileImage->context(), element->renderer(), contentTransformation);
}
return tileImage.release();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h
index 56a8318e06d..d6b4f12e577 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourcePattern.h
@@ -46,23 +46,22 @@ class RenderSVGResourcePattern FINAL : public RenderSVGResourceContainer {
public:
explicit RenderSVGResourcePattern(SVGPatternElement*);
- virtual const char* renderName() const { return "RenderSVGResourcePattern"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourcePattern"; }
- virtual void removeAllClientsFromCache(bool markForInvalidation = true);
- virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+ virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE;
+ virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE;
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE;
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
private:
bool buildTileImageTransform(RenderObject*, const PatternAttributes&, const SVGPatternElement*, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const;
PassOwnPtr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries,
- const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform,
- FloatRect& clampedAbsoluteTileBoundaries) const;
+ const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform) const;
PatternData* buildPattern(RenderObject*, unsigned short resourceMode);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
index 43ee07601e0..1f9145a02bd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
@@ -33,15 +33,15 @@ public:
explicit RenderSVGResourceRadialGradient(SVGRadialGradientElement*);
virtual ~RenderSVGResourceRadialGradient();
- virtual const char* renderName() const { return "RenderSVGResourceRadialGradient"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGResourceRadialGradient"; }
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
- virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
- virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
- virtual bool collectGradientAttributes(SVGGradientElement*);
- virtual void buildGradient(GradientData*) const;
+ virtual SVGUnitTypes::SVGUnitType gradientUnits() const OVERRIDE { return m_attributes.gradientUnits(); }
+ virtual void calculateGradientTransform(AffineTransform& transform) OVERRIDE { transform = m_attributes.gradientTransform(); }
+ virtual bool collectGradientAttributes(SVGGradientElement*) OVERRIDE;
+ virtual void buildGradient(GradientData*) const OVERRIDE;
FloatPoint centerPoint(const RadialGradientAttributes&) const;
FloatPoint focalPoint(const RadialGradientAttributes&) const;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
index a79ad3ad916..fac2a846c9a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
@@ -21,8 +21,8 @@
#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
-#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/svg/RenderSVGShape.h"
#include "core/rendering/svg/SVGRenderSupport.h"
@@ -56,9 +56,9 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl
if (resourceMode & ApplyToFillMode) {
if (!isRenderingMask && svgStyle)
- context->setAlpha(svgStyle->fillOpacity());
+ context->setAlphaAsFloat(svgStyle->fillOpacity());
else
- context->setAlpha(1);
+ context->setAlphaAsFloat(1);
context->setFillColor(m_color);
if (!isRenderingMask)
context->setFillRule(svgStyle ? svgStyle->fillRule() : RULE_NONZERO);
@@ -68,7 +68,7 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl
} else if (resourceMode & ApplyToStrokeMode) {
// When rendering the mask for a RenderSVGResourceClipper, the stroke code path is never hit.
ASSERT(!isRenderingMask);
- context->setAlpha(svgStyle ? svgStyle->strokeOpacity() : 1);
+ context->setAlphaAsFloat(svgStyle ? svgStyle->strokeOpacity() : 1);
context->setStrokeColor(m_color);
if (style)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
index 85937ce9ef1..3583a0d1aec 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
@@ -26,18 +26,18 @@
namespace WebCore {
-class RenderSVGResourceSolidColor : public RenderSVGResource {
+class RenderSVGResourceSolidColor FINAL : public RenderSVGResource {
public:
RenderSVGResourceSolidColor();
virtual ~RenderSVGResourceSolidColor();
- virtual void removeAllClientsFromCache(bool = true) { }
- virtual void removeClientFromCache(RenderObject*, bool = true) { }
+ virtual void removeAllClientsFromCache(bool = true) OVERRIDE { }
+ virtual void removeClientFromCache(RenderObject*, bool = true) OVERRIDE { }
- virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+ virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE;
+ virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE;
- virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+ virtual RenderSVGResourceType resourceType() const OVERRIDE { return s_resourceType; }
static const RenderSVGResourceType s_resourceType;
const Color& color() const { return m_color; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp
index a4355cd4d9a..d88947d3574 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.cpp
@@ -25,19 +25,21 @@
#include "core/rendering/svg/RenderSVGRoot.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderPart.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
#include "core/svg/SVGElement.h"
#include "core/svg/SVGSVGElement.h"
#include "core/svg/graphics/SVGImage.h"
+#include "platform/LengthFunctions.h"
#include "platform/graphics/GraphicsContext.h"
using namespace std;
@@ -49,6 +51,7 @@ RenderSVGRoot::RenderSVGRoot(SVGElement* node)
, m_objectBoundingBoxValid(false)
, m_isLayoutSizeChanged(false)
, m_needsBoundariesOrTransformUpdate(true)
+ , m_hasBoxDecorations(false)
{
}
@@ -56,19 +59,13 @@ RenderSVGRoot::~RenderSVGRoot()
{
}
-void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
{
// Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing
// SVG needs to specify how to calculate some intrinsic sizing properties to enable inclusion within other languages.
// The intrinsic width and height of the viewport of SVG content must be determined from the ‘width’ and ‘height’ attributes.
- // If either of these are not specified, a value of '100%' must be assumed. Note: the ‘width’ and ‘height’ attributes are not
- // the same as the CSS width and height properties. Specifically, percentage values do not provide an intrinsic width or height,
- // and do not indicate a percentage of the containing block. Rather, once the viewport is established, they indicate the portion
- // of the viewport that is actually covered by image data.
SVGSVGElement* svg = toSVGSVGElement(node());
ASSERT(svg);
- Length intrinsicWidthAttribute = svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties);
- Length intrinsicHeightAttribute = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
// The intrinsic aspect ratio of the viewport of SVG content is necessary for example, when including SVG from an ‘object’
// element in HTML styled with CSS. It is possible (indeed, common) for an SVG graphic to have an intrinsic aspect ratio but
@@ -77,33 +74,21 @@ void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, d
// - If the ‘width’ and ‘height’ of the rootmost ‘svg’ element are both specified with unit identifiers (in, mm, cm, pt, pc,
// px, em, ex) or in user units, then the aspect ratio is calculated from the ‘width’ and ‘height’ attributes after
// resolving both values to user units.
- if (intrinsicWidthAttribute.isFixed() || intrinsicHeightAttribute.isFixed()) {
- if (intrinsicWidthAttribute.isFixed())
- intrinsicSize.setWidth(floatValueForLength(intrinsicWidthAttribute, 0, 0));
- if (intrinsicHeightAttribute.isFixed())
- intrinsicSize.setHeight(floatValueForLength(intrinsicHeightAttribute, 0, 0));
- if (!intrinsicSize.isEmpty())
- intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
- return;
- }
+ intrinsicSize.setWidth(floatValueForLength(svg->intrinsicWidth(), 0));
+ intrinsicSize.setHeight(floatValueForLength(svg->intrinsicHeight(), 0));
- // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
- // aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
- // fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
- // calculated and is considered unspecified.
- intrinsicSize = svg->viewBoxCurrentValue().size();
if (!intrinsicSize.isEmpty()) {
- // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
- intrinsicSize = FloatSize();
- return;
- }
-
- // If our intrinsic size is in percentage units, return those to the caller through the intrinsicSize. Notify the caller
- // about the special situation, by setting isPercentageIntrinsicSize=true, so it knows how to interpret the return values.
- if (intrinsicWidthAttribute.isPercent() && intrinsicHeightAttribute.isPercent()) {
- isPercentageIntrinsicSize = true;
- intrinsicSize = FloatSize(intrinsicWidthAttribute.percent(), intrinsicHeightAttribute.percent());
+ } else {
+ // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
+ // aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
+ // fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
+ // calculated and is considered unspecified.
+ FloatSize viewBoxSize = svg->viewBox()->currentValue()->value().size();
+ if (!viewBoxSize.isEmpty()) {
+ // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
+ intrinsicRatio = viewBoxSize.width() / static_cast<double>(viewBoxSize.height());
+ }
}
}
@@ -117,20 +102,20 @@ bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const
if (!node())
return false;
- Frame* frame = node()->document().frame();
+ LocalFrame* frame = node()->document().frame();
if (!frame)
return false;
// If our frame has an owner renderer, we're embedded through eg. object/embed/iframe,
- // but we only negotiate if we're in an SVG document.
- if (!frame->ownerRenderer())
+ // but we only negotiate if we're in an SVG document inside a embedded object (object/embed).
+ if (!frame->ownerRenderer() || !frame->ownerRenderer()->isEmbeddedObject())
return false;
return frame->document()->isSVGDocument();
}
-static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView)
+static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize)
{
- return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1));
+ return static_cast<LayoutUnit>(valueForLength(length, maxSize) * (length.isFixed() ? scale : 1));
}
LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
@@ -142,15 +127,14 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred sho
if (!m_containerSize.isEmpty())
return m_containerSize.width();
+ if (isEmbeddedThroughFrameContainingSVGDocument())
+ return containingBlock()->availableLogicalWidth();
+
if (style()->logicalWidth().isSpecified() || style()->logicalMaxWidth().isSpecified())
return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
- if (svg->widthAttributeEstablishesViewport())
- return resolveLengthAttributeForSVG(svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style()->effectiveZoom(), containingBlock()->availableLogicalWidth(), view());
-
- // SVG embedded through object/embed/iframe.
- if (isEmbeddedThroughFrameContainingSVGDocument())
- return document().frame()->ownerRenderer()->availableLogicalWidth();
+ if (svg->hasIntrinsicWidth())
+ return resolveLengthAttributeForSVG(svg->intrinsicWidth(), style()->effectiveZoom(), containingBlock()->availableLogicalWidth().toFloat());
// SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
@@ -165,27 +149,14 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
if (!m_containerSize.isEmpty())
return m_containerSize.height();
+ if (isEmbeddedThroughFrameContainingSVGDocument())
+ return containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding);
+
if (style()->logicalHeight().isSpecified() || style()->logicalMaxHeight().isSpecified())
return RenderReplaced::computeReplacedLogicalHeight();
- if (svg->heightAttributeEstablishesViewport()) {
- Length height = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
- if (height.isPercent()) {
- RenderBlock* cb = containingBlock();
- ASSERT(cb);
- while (cb->isAnonymous()) {
- cb = cb->containingBlock();
- cb->addPercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
- }
- } else
- RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
-
- return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding), view());
- }
-
- // SVG embedded through object/embed/iframe.
- if (isEmbeddedThroughFrameContainingSVGDocument())
- return document().frame()->ownerRenderer()->availableLogicalHeight(IncludeMarginBorderPadding);
+ if (svg->hasIntrinsicHeight())
+ return resolveLengthAttributeForSVG(svg->intrinsicHeight(), style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding).toFloat());
// SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
return RenderReplaced::computeReplacedLogicalHeight();
@@ -195,13 +166,11 @@ void RenderSVGRoot::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
-
// Arbitrary affine transforms are incompatible with LayoutState.
- LayoutStateDisabler layoutStateDisabler(view());
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
bool needsLayout = selfNeedsLayout();
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout);
+ LayoutRepainter repainter(*this, checkForPaintInvalidationDuringLayout() && needsLayout);
LayoutSize oldSize = size();
updateLogicalWidth();
@@ -222,13 +191,34 @@ void RenderSVGRoot::layout()
m_needsBoundariesOrTransformUpdate = false;
}
- updateLayerTransform();
+ m_overflow.clear();
+ addVisualEffectOverflow();
- repainter.repaintAfterLayout();
+ if (!shouldApplyViewportClip()) {
+ FloatRect contentRepaintRect = paintInvalidationRectInLocalCoordinates();
+ contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect);
+ addVisualOverflow(enclosingLayoutRect(contentRepaintRect));
+ }
+ updateLayerTransformAfterLayout();
+ m_hasBoxDecorations = isDocumentElement() ? calculateHasBoxDecorations() : hasBoxDecorations();
+ invalidateBackgroundObscurationStatus();
+
+ repainter.repaintAfterLayout();
clearNeedsLayout();
}
+bool RenderSVGRoot::shouldApplyViewportClip() const
+{
+ // the outermost svg is clipped if auto, and svg document roots are always clipped
+ // When the svg is stand-alone (isDocumentElement() == true) the viewport clipping should always
+ // be applied, noting that the window scrollbars should be hidden if overflow=hidden.
+ return style()->overflowX() == OHIDDEN
+ || style()->overflowX() == OAUTO
+ || style()->overflowX() == OSCROLL
+ || this->isDocumentElement();
+}
+
void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// An empty viewport disables rendering.
@@ -239,6 +229,10 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
if (paintInfo.context->paintingDisabled())
return;
+ // SVG outlines are painted during PaintPhaseForeground.
+ if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline)
+ return;
+
// An empty viewBox also disables rendering.
// (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute)
SVGSVGElement* svg = toSVGSVGElement(node());
@@ -257,8 +251,9 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint
PaintInfo childPaintInfo(paintInfo);
childPaintInfo.context->save();
- // Apply initial viewport clip - not affected by overflow handling
- childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion)));
+ // Apply initial viewport clip
+ if (shouldApplyViewportClip())
+ childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset)));
// Convert from container offsets (html renderers) to a relative transform (svg renderers).
// Transform from our paint container's coordinate system to our local coords.
@@ -292,13 +287,22 @@ void RenderSVGRoot::willBeDestroyed()
void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- if (diff == StyleDifferenceLayout)
+ if (diff.needsFullLayout())
setNeedsBoundariesUpdate();
+ if (diff.needsRepaint()) {
+ // Box decorations may have appeared/disappeared - recompute status.
+ m_hasBoxDecorations = calculateHasBoxDecorations();
+ }
RenderReplaced::styleDidChange(diff, oldStyle);
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
+bool RenderSVGRoot::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isSVG() && !(child->isSVGInline() || child->isSVGInlineText());
+}
+
void RenderSVGRoot::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderReplaced::addChild(child, beforeChild);
@@ -330,12 +334,13 @@ void RenderSVGRoot::buildLocalToBorderBoxTransform()
SVGSVGElement* svg = toSVGSVGElement(node());
ASSERT(svg);
float scale = style()->effectiveZoom();
- SVGPoint translate = svg->currentTranslate();
+ FloatPoint translate = svg->currentTranslate();
LayoutSize borderAndPadding(borderLeft() + paddingLeft(), borderTop() + paddingTop());
m_localToBorderBoxTransform = svg->viewBoxToViewTransform(contentWidth() / scale, contentHeight() / scale);
- if (borderAndPadding.isEmpty() && scale == 1 && translate == SVGPoint::zero())
+ AffineTransform viewToBorderBoxTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y());
+ if (viewToBorderBoxTransform.isIdentity())
return;
- m_localToBorderBoxTransform = AffineTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()) * m_localToBorderBoxTransform;
+ m_localToBorderBoxTransform = viewToBorderBoxTransform * m_localToBorderBoxTransform;
}
const AffineTransform& RenderSVGRoot::localToParentTransform() const
@@ -349,23 +354,53 @@ const AffineTransform& RenderSVGRoot::localToParentTransform() const
return m_localToParentTransform;
}
-LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+LayoutRect RenderSVGRoot::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const
{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+ // This is an open-coded aggregate of SVGRenderSupport::clippedOverflowRectForPaintInvalidation,
+ // RenderSVGRoot::computeFloatRectForPaintInvalidation and RenderReplaced::clippedOverflowRectForPaintInvalidation.
+ // The reason for this is to optimize/minimize the repaint rect when the box is not "decorated"
+ // (does not have background/border/etc.)
+
+ // Return early for any cases where we don't actually paint.
+ if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+ return LayoutRect();
+
+ // Compute the repaint rect of the content of the SVG in the border-box coordinate space.
+ FloatRect contentRepaintRect = paintInvalidationRectInLocalCoordinates();
+ contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect);
+
+ // Apply initial viewport clip, overflow:visible content is added to visualOverflow
+ // but the most common case is that overflow is hidden, so always intersect.
+ contentRepaintRect.intersect(pixelSnappedBorderBoxRect());
+
+ LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect);
+ // If the box is decorated or is overflowing, extend it to include the border-box and overflow.
+ if (m_hasBoxDecorations || hasRenderOverflow()) {
+ // The selectionRect can project outside of the overflowRect, so take their union
+ // for repainting to avoid selection painting glitches.
+ LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect());
+ repaintRect.unite(decoratedRepaintRect);
+ }
+
+ // Compute the repaint rect in the parent coordinate space.
+ LayoutRect rect = enclosingIntRect(repaintRect);
+ RenderReplaced::mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect);
+ return rect;
}
-void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+void RenderSVGRoot::computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const
{
// Apply our local transforms (except for x/y translation), then our shadow,
// and then call RenderBox's method to handle all the normal CSS Box model bits
- repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect);
+ paintInvalidationRect = m_localToBorderBoxTransform.mapRect(paintInvalidationRect);
- // Apply initial viewport clip - not affected by overflow settings
- repaintRect.intersect(pixelSnappedBorderBoxRect());
+ // Apply initial viewport clip
+ if (shouldApplyViewportClip())
+ paintInvalidationRect.intersect(pixelSnappedBorderBoxRect());
- LayoutRect rect = enclosingIntRect(repaintRect);
- RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed);
- repaintRect = rect;
+ LayoutRect rect = enclosingIntRect(paintInvalidationRect);
+ RenderReplaced::mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, fixed);
+ paintInvalidationRect = rect;
}
// This method expects local CSS box coordinates.
@@ -374,7 +409,9 @@ void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* rep
void RenderSVGRoot::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
{
ASSERT(mode & ~IsFixed); // We should have no fixed content in the SVG rendering tree.
- ASSERT(mode & UseTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
+ // We used to have this ASSERT here, but we removed it when enabling layer squashing.
+ // See http://crbug.com/364901
+ // ASSERT(mode & UseTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
RenderReplaced::mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
}
@@ -388,7 +425,6 @@ void RenderSVGRoot::updateCachedBoundaries()
{
SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
- m_repaintBoundingBox.inflate(borderAndPaddingWidth());
}
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
@@ -412,11 +448,11 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
}
// If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit.
- if (hitTestAction == HitTestBlockBackground && visibleToHitTestRequest(request)) {
- // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase,
- // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need
- // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able
- // to detect these hits anymore.
+ if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && visibleToHitTestRequest(request)) {
+ // Only return true here, if the last hit testing phase 'BlockBackground' (or 'ChildBlockBackground' - depending on context) is executed.
+ // If we'd return true in the 'Foreground' phase, hit testing would stop immediately. For SVG only trees this doesn't matter.
+ // Though when we have a <foreignObject> subtree we need to be able to detect hits on the background of a <div> element.
+ // If we'd return true here in the 'Foreground' phase, we are not able to detect these hits anymore.
LayoutRect boundsRect(accumulatedOffset + location(), size());
if (locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, pointInBorderBox);
@@ -428,27 +464,4 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
return false;
}
-bool RenderSVGRoot::hasRelativeDimensions() const
-{
- SVGSVGElement* svg = toSVGSVGElement(node());
- ASSERT(svg);
-
- return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent() || svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
-bool RenderSVGRoot::hasRelativeIntrinsicLogicalWidth() const
-{
- SVGSVGElement* svg = toSVGSVGElement(node());
- ASSERT(svg);
- return svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
-bool RenderSVGRoot::hasRelativeLogicalHeight() const
-{
- SVGSVGElement* svg = toSVGSVGElement(node());
- ASSERT(svg);
-
- return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent();
-}
-
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h
index f907222eb81..b38d51cbde8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGRoot.h
@@ -24,12 +24,10 @@
#define RenderSVGRoot_h
#include "core/rendering/RenderReplaced.h"
-#include "core/rendering/svg/SVGRenderSupport.h"
#include "platform/geometry/FloatRect.h"
namespace WebCore {
-class AffineTransform;
class SVGElement;
class RenderSVGRoot FINAL : public RenderReplaced {
@@ -40,66 +38,77 @@ public:
bool isEmbeddedThroughSVGImage() const;
bool isEmbeddedThroughFrameContainingSVGDocument() const;
- virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+ virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const OVERRIDE;
RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+ // If you have a RenderSVGRoot, use firstChild or lastChild instead.
+ void slowFirstChild() const WTF_DELETED_FUNCTION;
+ void slowLastChild() const WTF_DELETED_FUNCTION;
+
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
- virtual void setNeedsBoundariesUpdate() { m_needsBoundariesOrTransformUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesOrTransformUpdate; }
- virtual void setNeedsTransformUpdate() { m_needsBoundariesOrTransformUpdate = true; }
+ virtual void setNeedsBoundariesUpdate() OVERRIDE { m_needsBoundariesOrTransformUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsBoundariesOrTransformUpdate = true; }
IntSize containerSize() const { return m_containerSize; }
- void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; }
-
- virtual bool hasRelativeDimensions() const OVERRIDE;
- virtual bool hasRelativeIntrinsicLogicalWidth() const OVERRIDE;
- virtual bool hasRelativeLogicalHeight() const OVERRIDE;
+ void setContainerSize(const IntSize& containerSize)
+ {
+ // SVGImage::draw() does a view layout prior to painting,
+ // and we need that layout to know of the new size otherwise
+ // the rendering may be incorrectly using the old size.
+ if (m_containerSize != containerSize)
+ setNeedsLayoutAndFullPaintInvalidation();
+ m_containerSize = containerSize;
+ }
// localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates.
const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; }
private:
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ virtual RenderObjectChildList* virtualChildren() OVERRIDE { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const OVERRIDE { return children(); }
- virtual bool isSVGRoot() const { return true; }
- virtual const char* renderName() const { return "RenderSVGRoot"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGRoot"; }
+ virtual bool isSVGRoot() const OVERRIDE { return true; }
+ virtual bool isSVG() const OVERRIDE { return true; }
virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const OVERRIDE;
- virtual LayoutUnit computeReplacedLogicalHeight() const;
- virtual void layout();
- virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+ virtual LayoutUnit computeReplacedLogicalHeight() const OVERRIDE;
+ virtual void layout() OVERRIDE;
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
- virtual void willBeDestroyed();
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void willBeDestroyed() OVERRIDE;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
virtual void removeChild(RenderObject*) OVERRIDE;
+ virtual bool canHaveWhitespaceChildren() const OVERRIDE { return false; }
virtual void insertedIntoTree() OVERRIDE;
virtual void willBeRemovedFromTree() OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const;
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
- virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; }
- virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return m_objectBoundingBox; }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE { return m_strokeBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE { return m_repaintBoundingBox; }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const OVERRIDE;
+ virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer) const OVERRIDE;
+ virtual void computeFloatRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, FloatRect& paintInvalidationRect, bool fixed) const OVERRIDE;
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual bool canBeSelectionLeaf() const { return false; }
- virtual bool canHaveChildren() const { return true; }
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return false; }
+ virtual bool canHaveChildren() const OVERRIDE { return true; }
+ bool shouldApplyViewportClip() const;
void updateCachedBoundaries();
void buildLocalToBorderBoxTransform();
@@ -113,6 +122,7 @@ private:
AffineTransform m_localToBorderBoxTransform;
bool m_isLayoutSizeChanged : 1;
bool m_needsBoundariesOrTransformUpdate : 1;
+ bool m_hasBoxDecorations : 1;
};
DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderSVGRoot, isSVGRoot());
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp
index 04298f7e49d..dfd09e70aef 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.cpp
@@ -26,17 +26,16 @@
*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGShape.h"
#include "core/rendering/GraphicsContextAnnotator.h"
#include "core/rendering/HitTestRequest.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
#include "core/rendering/PointerEventsHitRules.h"
#include "core/rendering/svg/RenderSVGResourceMarker.h"
#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
#include "core/rendering/svg/SVGPathData.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/rendering/svg/SVGRenderingContext.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
@@ -63,7 +62,7 @@ void RenderSVGShape::updateShapeFromElement()
{
m_path.clear();
m_path = adoptPtr(new Path);
- ASSERT(RenderSVGShape::isEmpty());
+ ASSERT(RenderSVGShape::isShapeEmpty());
updatePathFromGraphicsElement(toSVGGraphicsElement(element()), path());
processMarkerPositions();
@@ -72,11 +71,6 @@ void RenderSVGShape::updateShapeFromElement()
m_strokeBoundingBox = calculateStrokeBoundingBox();
}
-bool RenderSVGShape::isEmpty() const
-{
- return path().isEmpty();
-}
-
void RenderSVGShape::fillShape(GraphicsContext* context) const
{
context->fillPath(path());
@@ -119,8 +113,8 @@ bool RenderSVGShape::fillContains(const FloatPoint& point, bool requiresFill, co
if (!m_fillBoundingBox.contains(point))
return false;
- Color fallbackColor;
- if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), fallbackColor))
+ bool hasFallback;
+ if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), hasFallback))
return false;
return shapeDependentFillContains(point, fillRule);
@@ -131,8 +125,8 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
if (!strokeBoundingBox().contains(point))
return false;
- Color fallbackColor;
- if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), fallbackColor))
+ bool hasFallback;
+ if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), hasFallback))
return false;
return shapeDependentStrokeContains(point);
@@ -140,7 +134,6 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
void RenderSVGShape::layout()
{
- LayoutRectRecorder recorder(*this);
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout());
bool updateCachedBoundariesInParents = false;
@@ -201,7 +194,7 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const
if (!style()->svgStyle()->hasMarkers())
return false;
- if (!toSVGGraphicsElement(element())->supportsMarkers())
+ if (!SVGResources::supportsMarkers(*toSVGGraphicsElement(element())))
return false;
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
@@ -213,13 +206,12 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const
void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context)
{
- Color fallbackColor;
- if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) {
- if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode))
+ bool hasFallback;
+ if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, hasFallback)) {
+ if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode)) {
fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
- else if (fallbackColor.isValid()) {
+ } else if (hasFallback) {
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
if (fallbackResource->applyResource(this, style, context, ApplyToFillMode))
fallbackResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
}
@@ -228,13 +220,12 @@ void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context)
void RenderSVGShape::strokeShape(RenderStyle* style, GraphicsContext* context)
{
- Color fallbackColor;
- if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor)) {
- if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode))
+ bool hasFallback;
+ if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, hasFallback)) {
+ if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode)) {
strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
- else if (fallbackColor.isValid()) {
+ } else if (hasFallback) {
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode))
fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
}
@@ -244,68 +235,67 @@ void RenderSVGShape::strokeShape(RenderStyle* style, GraphicsContext* context)
void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
-
- if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || isEmpty())
+ if (paintInfo.context->paintingDisabled()
+ || paintInfo.phase != PaintPhaseForeground
+ || style()->visibility() == HIDDEN
+ || isShapeEmpty())
return;
- FloatRect boundingBox = repaintRectInLocalCoordinates();
+
+ FloatRect boundingBox = paintInvalidationRectInLocalCoordinates();
if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
return;
PaintInfo childPaintInfo(paintInfo);
- bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
- if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
- childPaintInfo.applyTransform(m_localTransform);
-
- if (childPaintInfo.phase == PaintPhaseForeground) {
- SVGRenderingContext renderingContext(this, childPaintInfo);
-
- if (renderingContext.isRenderingPrepared()) {
- const SVGRenderStyle* svgStyle = style()->svgStyle();
- if (svgStyle->shapeRendering() == SR_CRISPEDGES)
- childPaintInfo.context->setShouldAntialias(false);
-
- for (int i = 0; i < 3; i++) {
- switch (svgStyle->paintOrderType(i)) {
- case PT_FILL:
- fillShape(this->style(), childPaintInfo.context);
- break;
- case PT_STROKE:
- if (svgStyle->hasVisibleStroke()) {
- GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
- AffineTransform nonScalingTransform;
-
- if (hasNonScalingStroke()) {
- AffineTransform nonScalingTransform = nonScalingStrokeTransform();
- if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
- return;
- }
-
- strokeShape(this->style(), childPaintInfo.context);
- }
- break;
- case PT_MARKERS:
- if (!m_markerPositions.isEmpty())
- drawMarkers(childPaintInfo);
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
+
+ GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+ childPaintInfo.applyTransform(m_localTransform);
+
+ SVGRenderingContext renderingContext(this, childPaintInfo);
+
+ if (renderingContext.isRenderingPrepared()) {
+ const SVGRenderStyle* svgStyle = style()->svgStyle();
+ if (svgStyle->shapeRendering() == SR_CRISPEDGES)
+ childPaintInfo.context->setShouldAntialias(false);
+
+ for (int i = 0; i < 3; i++) {
+ switch (svgStyle->paintOrderType(i)) {
+ case PT_FILL:
+ fillShape(this->style(), childPaintInfo.context);
+ break;
+ case PT_STROKE:
+ if (svgStyle->hasVisibleStroke()) {
+ GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);
+ AffineTransform nonScalingTransform;
+
+ if (hasNonScalingStroke()) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
+ return;
}
+
+ strokeShape(this->style(), childPaintInfo.context);
}
+ break;
+ case PT_MARKERS:
+ if (!m_markerPositions.isEmpty())
+ drawMarkers(childPaintInfo);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
}
}
-
- if (drawsOutline)
- paintOutline(childPaintInfo, IntRect(boundingBox));
}
+
+ if (style()->outlineWidth())
+ paintOutline(childPaintInfo, IntRect(boundingBox));
}
// This method is called from inside paintOutline() since we call paintOutline()
// while transformed to our coord system, return local coords
void RenderSVGShape::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
{
- IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates());
+ IntRect rect = enclosingIntRect(paintInvalidationRectInLocalCoordinates());
if (!rect.isEmpty())
rects.append(rect);
}
@@ -417,7 +407,7 @@ FloatRect RenderSVGShape::calculateStrokeBoundingBox() const
void RenderSVGShape::updateRepaintBoundingBox()
{
m_repaintBoundingBox = strokeBoundingBox();
- if (strokeWidth() < 1.0f)
+ if (strokeWidth() < 1.0f && !m_repaintBoundingBox.isEmpty())
m_repaintBoundingBox.inflate(1);
SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
}
@@ -425,13 +415,13 @@ void RenderSVGShape::updateRepaintBoundingBox()
float RenderSVGShape::strokeWidth() const
{
SVGLengthContext lengthContext(element());
- return style()->svgStyle()->strokeWidth().value(lengthContext);
+ return style()->svgStyle()->strokeWidth()->value(lengthContext);
}
bool RenderSVGShape::hasSmoothStroke() const
{
const SVGRenderStyle* svgStyle = style()->svgStyle();
- return svgStyle->strokeDashArray().isEmpty()
+ return svgStyle->strokeDashArray()->isEmpty()
&& svgStyle->strokeMiterLimit() == svgStyle->initialStrokeMiterLimit()
&& svgStyle->joinStyle() == svgStyle->initialJoinStyle()
&& svgStyle->capStyle() == svgStyle->initialCapStyle();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h
index f800b2db555..12a703f063b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGShape.h
@@ -38,9 +38,6 @@ namespace WebCore {
class FloatPoint;
class GraphicsContextStateSaver;
class PointerEventsHitRules;
-class RenderSVGContainer;
-class RenderSVGPath;
-class RenderSVGResource;
class SVGGraphicsElement;
class RenderSVGShape : public RenderSVGModelObject {
@@ -51,7 +48,6 @@ public:
void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
virtual void setNeedsBoundariesUpdate() OVERRIDE FINAL { m_needsBoundariesUpdate = true; }
- virtual bool needsBoundariesUpdate() OVERRIDE FINAL { return m_needsBoundariesUpdate; }
virtual void setNeedsTransformUpdate() OVERRIDE FINAL { m_needsTransformUpdate = true; }
virtual void fillShape(GraphicsContext*) const;
virtual void strokeShape(GraphicsContext*) const;
@@ -66,7 +62,7 @@ public:
protected:
virtual void updateShapeFromElement();
- virtual bool isEmpty() const;
+ virtual bool isShapeEmpty() const { return path().isEmpty(); }
virtual bool shapeDependentStrokeContains(const FloatPoint&);
virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
float strokeWidth() const;
@@ -85,12 +81,12 @@ private:
bool fillContains(const FloatPoint&, bool requiresFill = true, const WindRule fillRule = RULE_NONZERO);
bool strokeContains(const FloatPoint&, bool requiresStroke = true);
- virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
virtual const AffineTransform& localToParentTransform() const OVERRIDE FINAL { return m_localTransform; }
virtual AffineTransform localTransform() const OVERRIDE FINAL { return m_localTransform; }
virtual bool isSVGShape() const OVERRIDE FINAL { return true; }
- virtual const char* renderName() const { return "RenderSVGShape"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGShape"; }
virtual void layout() OVERRIDE FINAL;
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
@@ -116,7 +112,6 @@ private:
private:
FloatRect m_repaintBoundingBox;
- FloatRect m_repaintBoundingBoxExcludingShadow;
AffineTransform m_localTransform;
OwnPtr<Path> m_path;
Vector<MarkerPosition> m_markerPositions;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp
index 5f34538620b..30c06454d59 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.cpp
@@ -24,6 +24,9 @@
#include "core/rendering/svg/RenderSVGTSpan.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGAltGlyphElement.h"
+
namespace WebCore {
RenderSVGTSpan::RenderSVGTSpan(Element* element)
@@ -31,4 +34,20 @@ RenderSVGTSpan::RenderSVGTSpan(Element* element)
{
}
+bool RenderSVGTSpan::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ // Always allow text (except empty textnodes and <br>).
+ if (child->isText())
+ return SVGRenderSupport::isRenderableTextNode(child);
+
+#if ENABLE(SVG_FONTS)
+ // Only allow other types of children if this is not an 'altGlyph'.
+ ASSERT(node());
+ if (isSVGAltGlyphElement(*node()))
+ return false;
+#endif
+
+ return child->isSVGInline() && !child->isSVGTextPath();
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h
index ba8cb31e1e0..7875119a34f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTSpan.h
@@ -28,7 +28,10 @@ namespace WebCore {
class RenderSVGTSpan FINAL : public RenderSVGInline {
public:
explicit RenderSVGTSpan(Element*);
- virtual const char* renderName() const { return "RenderSVGTSpan"; }
+
+ virtual bool isChildAllowed(RenderObject* child, RenderStyle*) const OVERRIDE;
+
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGTSpan"; }
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp
index ba45ce98f18..8536029524b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.cpp
@@ -30,10 +30,11 @@
#include "core/rendering/HitTestRequest.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/PointerEventsHitRules.h"
#include "core/rendering/style/ShadowList.h"
+#include "core/rendering/svg/RenderSVGInline.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGResource.h"
#include "core/rendering/svg/RenderSVGRoot.h"
@@ -70,7 +71,7 @@ RenderSVGText::~RenderSVGText()
bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const
{
- return child->isInline() && !SVGRenderSupport::isEmptySVGInlineText(child);
+ return child->isSVGInline() || (child->isText() && SVGRenderSupport::isRenderableTextNode(child));
}
RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start)
@@ -93,33 +94,13 @@ const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObje
return toRenderSVGText(start);
}
-LayoutRect RenderSVGText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
-{
- return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
-}
-
-void RenderSVGText::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+void RenderSVGText::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, bool fixed) const
{
FloatRect repaintRect = rect;
- computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+ computeFloatRectForPaintInvalidation(paintInvalidationContainer, repaintRect, fixed);
rect = enclosingLayoutRect(repaintRect);
}
-void RenderSVGText::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
-{
- SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
-}
-
-void RenderSVGText::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
-{
- SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
-}
-
-const RenderObject* RenderSVGText::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
-{
- return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
-}
-
static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes)
{
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
@@ -128,14 +109,15 @@ static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLay
}
}
-static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGInlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
+static inline bool findPreviousAndNextAttributes(RenderSVGText* root, RenderSVGInlineText* locateElement, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
{
- ASSERT(start);
+ ASSERT(root);
ASSERT(locateElement);
- // FIXME: Make this iterative.
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- RenderSVGInlineText* text = toRenderSVGInlineText(child);
+ bool stopAfterNext = false;
+ RenderObject* current = root->firstChild();
+ while (current) {
+ if (current->isSVGInlineText()) {
+ RenderSVGInlineText* text = toRenderSVGInlineText(current);
if (locateElement != text) {
if (stopAfterNext) {
next = text->layoutAttributes();
@@ -143,20 +125,19 @@ static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGI
}
previous = text->layoutAttributes();
+ } else {
+ stopAfterNext = true;
+ }
+ } else if (current->isSVGInline()) {
+ // Descend into text content (if possible).
+ if (RenderObject* child = toRenderSVGInline(current)->firstChild()) {
+ current = child;
continue;
}
-
- stopAfterNext = true;
- continue;
}
- if (!child->isSVGInline())
- continue;
-
- if (findPreviousAndNextAttributes(child, locateElement, stopAfterNext, previous, next))
- return true;
+ current = current->nextInPreOrderAfterChildren(root);
}
-
return false;
}
@@ -201,11 +182,10 @@ void RenderSVGText::subtreeChildWasAdded(RenderObject* child)
attributes = newLayoutAttributes[i];
if (m_layoutAttributes.find(attributes) == kNotFound) {
// Every time this is invoked, there's only a single new entry in the newLayoutAttributes list, compared to the old in m_layoutAttributes.
- bool stopAfterNext = false;
SVGTextLayoutAttributes* previous = 0;
SVGTextLayoutAttributes* next = 0;
ASSERT_UNUSED(child, attributes->context() == child);
- findPreviousAndNextAttributes(this, attributes->context(), stopAfterNext, previous, next);
+ findPreviousAndNextAttributes(this, attributes->context(), previous, next);
if (previous)
m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(previous->context());
@@ -258,11 +238,10 @@ void RenderSVGText::subtreeChildWillBeRemoved(RenderObject* child, Vector<SVGTex
// This logic requires that the 'text' child is still inserted in the tree.
RenderSVGInlineText* text = toRenderSVGInlineText(child);
- bool stopAfterNext = false;
SVGTextLayoutAttributes* previous = 0;
SVGTextLayoutAttributes* next = 0;
if (!documentBeingDestroyed())
- findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next);
+ findPreviousAndNextAttributes(this, text, previous, next);
if (previous)
affectedAttributes.append(previous);
@@ -288,9 +267,8 @@ void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*
m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(affectedAttributes[i]->context());
}
-void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
+void RenderSVGText::subtreeStyleDidChange()
{
- ASSERT(text);
if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
return;
@@ -299,7 +277,7 @@ void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
// Only update the metrics cache, but not the text positioning element cache
// nor the layout attributes cached in the leaf #text renderers.
FontCachePurgePreventer fontCachePurgePreventer;
- for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
+ for (RenderObject* descendant = firstChild(); descendant; descendant = descendant->nextInPreOrder(this)) {
if (descendant->isSVGInlineText())
m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGInlineText(descendant));
}
@@ -344,7 +322,9 @@ static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayout
void RenderSVGText::layout()
{
ASSERT(needsLayout());
- LayoutRectRecorder recorder(*this);
+
+ subtreeStyleDidChange();
+
LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this));
bool updateCachedBoundariesInParents = false;
@@ -408,7 +388,16 @@ void RenderSVGText::layout()
// FIXME: We need to find a way to only layout the child boxes, if needed.
FloatRect oldBoundaries = objectBoundingBox();
ASSERT(childrenInline());
- forceLayoutInlineChildren();
+
+ rebuildFloatsFromIntruding();
+
+ LayoutUnit beforeEdge = borderBefore() + paddingBefore();
+ LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+ setLogicalHeight(beforeEdge);
+
+ LayoutUnit repaintLogicalTop = 0;
+ LayoutUnit repaintLogicalBottom = 0;
+ layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom, afterEdge);
if (m_needsReordering)
m_needsReordering = false;
@@ -430,7 +419,7 @@ void RenderSVGText::layout()
RootInlineBox* RenderSVGText::createRootInlineBox()
{
- RootInlineBox* box = new SVGRootInlineBox(this);
+ RootInlineBox* box = new SVGRootInlineBox(*this);
box->setHasVirtualLogicalHeight();
return box;
}
@@ -458,12 +447,6 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul
return false;
}
-bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInContents)
{
RootInlineBox* rootBox = firstRootBox();
@@ -477,7 +460,7 @@ PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInC
if (!closestBox)
return createPositionWithAffinity(0, DOWNSTREAM);
- return closestBox->renderer()->positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
+ return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
}
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
@@ -491,14 +474,23 @@ void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
return;
if (paintInfo.phase != PaintPhaseForeground
- && paintInfo.phase != PaintPhaseSelfOutline
&& paintInfo.phase != PaintPhaseSelection)
return;
PaintInfo blockInfo(paintInfo);
- GraphicsContextStateSaver stateSaver(*blockInfo.context);
- blockInfo.applyTransform(localToParentTransform());
+ GraphicsContextStateSaver stateSaver(*blockInfo.context, false);
+ const AffineTransform& localTransform = localToParentTransform();
+ if (!localTransform.isIdentity()) {
+ stateSaver.save();
+ blockInfo.applyTransform(localTransform, false);
+ }
RenderBlock::paint(blockInfo, LayoutPoint());
+
+ // Paint the outlines, if any
+ if (paintInfo.phase == PaintPhaseForeground) {
+ blockInfo.phase = PaintPhaseSelfOutline;
+ RenderBlock::paint(blockInfo, LayoutPoint());
+ }
}
FloatRect RenderSVGText::strokeBoundingBox() const
@@ -511,11 +503,11 @@ FloatRect RenderSVGText::strokeBoundingBox() const
ASSERT(node());
ASSERT(node()->isSVGElement());
SVGLengthContext lengthContext(toSVGElement(node()));
- strokeBoundaries.inflate(svgStyle->strokeWidth().value(lengthContext));
+ strokeBoundaries.inflate(svgStyle->strokeWidth()->value(lengthContext));
return strokeBoundaries;
}
-FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
+FloatRect RenderSVGText::paintInvalidationRectInLocalCoordinates() const
{
FloatRect repaintRect = strokeBoundingBox();
SVGRenderSupport::intersectRepaintRectWithResources(this, repaintRect);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h
index 56fb0db8e49..dfac5394a68 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGText.h
@@ -37,12 +37,12 @@ public:
explicit RenderSVGText(SVGTextElement*);
virtual ~RenderSVGText();
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; }
- virtual FloatRect repaintRectInLocalCoordinates() const;
+ virtual FloatRect paintInvalidationRectInLocalCoordinates() const OVERRIDE;
static RenderSVGText* locateRenderSVGTextAncestor(RenderObject*);
static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject*);
@@ -53,42 +53,35 @@ public:
void subtreeChildWasAdded(RenderObject*);
void subtreeChildWillBeRemoved(RenderObject*, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
void subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
- void subtreeStyleDidChange(RenderSVGInlineText*);
+ void subtreeStyleDidChange();
void subtreeTextDidChange(RenderSVGInlineText*);
private:
- virtual const char* renderName() const { return "RenderSVGText"; }
- virtual bool isSVGText() const { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGText"; }
+ virtual bool isSVGText() const OVERRIDE { return true; }
- virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE;
+ virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE;
- virtual bool requiresLayer() const { return false; }
- virtual void layout();
+ virtual void layout() OVERRIDE;
- virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE;
- virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
- virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
- virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
+ virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
- virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
- virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
virtual void removeChild(RenderObject*) OVERRIDE;
virtual void willBeDestroyed() OVERRIDE;
- virtual FloatRect objectBoundingBox() const { return frameRect(); }
- virtual FloatRect strokeBoundingBox() const;
+ virtual FloatRect objectBoundingBox() const OVERRIDE { return frameRect(); }
+ virtual FloatRect strokeBoundingBox() const OVERRIDE;
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
- virtual AffineTransform localTransform() const { return m_localTransform; }
- virtual RootInlineBox* createRootInlineBox();
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localTransform; }
+ virtual RootInlineBox* createRootInlineBox() OVERRIDE;
- virtual RenderBlock* firstLineBlock() const;
- virtual void updateFirstLetter();
+ virtual RenderBlock* firstLineBlock() const OVERRIDE;
+ virtual void updateFirstLetter() OVERRIDE;
bool shouldHandleSubtreeMutations() const;
@@ -96,7 +89,6 @@ private:
bool m_needsPositioningValuesUpdate : 1;
bool m_needsTransformUpdate : 1;
bool m_needsTextMetricsUpdate : 1;
- AffineTransform m_localTransform;
SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder;
Vector<SVGTextLayoutAttributes*> m_layoutAttributes;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp
index aec2da5ac29..f9deafa7276 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.cpp
@@ -21,8 +21,8 @@
#include "core/rendering/svg/RenderSVGTextPath.h"
-#include "SVGNames.h"
#include "core/rendering/svg/SVGPathData.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/svg/SVGPathElement.h"
#include "core/svg/SVGTextPathElement.h"
@@ -33,30 +33,45 @@ RenderSVGTextPath::RenderSVGTextPath(Element* element)
{
}
+bool RenderSVGTextPath::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ if (child->isText())
+ return SVGRenderSupport::isRenderableTextNode(child);
+
+#if ENABLE(SVG_FONTS)
+ // 'altGlyph' is supported by the content model for 'textPath', but...
+ ASSERT(child->node());
+ if (isSVGAltGlyphElement(*child->node()))
+ return false;
+#endif
+
+ return child->isSVGInline() && !child->isSVGTextPath();
+}
+
Path RenderSVGTextPath::layoutPath() const
{
SVGTextPathElement* textPathElement = toSVGTextPathElement(node());
- Element* targetElement = SVGURIReference::targetElementFromIRIString(textPathElement->hrefCurrentValue(), textPathElement->document());
- if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag))
+ Element* targetElement = SVGURIReference::targetElementFromIRIString(textPathElement->href()->currentValue()->value(), textPathElement->treeScope());
+ if (!isSVGPathElement(targetElement))
return Path();
- SVGPathElement* pathElement = toSVGPathElement(targetElement);
+ SVGPathElement& pathElement = toSVGPathElement(*targetElement);
Path pathData;
- updatePathFromGraphicsElement(pathElement, pathData);
+ updatePathFromGraphicsElement(&pathElement, pathData);
// Spec: The transform attribute on the referenced 'path' element represents a
// supplemental transformation relative to the current user coordinate system for
// the current 'text' element, including any adjustments to the current user coordinate
// system due to a possible transform attribute on the current 'text' element.
// http://www.w3.org/TR/SVG/text.html#TextPathElement
- pathData.transform(pathElement->animatedLocalTransform());
+ pathData.transform(pathElement.animatedLocalTransform());
return pathData;
}
float RenderSVGTextPath::startOffset() const
{
- return toSVGTextPathElement(node())->startOffsetCurrentValue().valueAsPercentage();
+ return toSVGTextPathElement(node())->startOffset()->currentValue()->valueAsPercentage();
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h
index 6e14b5528f6..6d98871341f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTextPath.h
@@ -32,10 +32,12 @@ public:
Path layoutPath() const;
float startOffset() const;
- virtual bool isSVGTextPath() const { return true; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+ virtual bool isSVGTextPath() const OVERRIDE { return true; }
private:
- virtual const char* renderName() const { return "RenderSVGTextPath"; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGTextPath"; }
Path m_layoutPath;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
index 52516c4c268..841bec55ec1 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
@@ -23,8 +23,8 @@
#include "core/rendering/svg/RenderSVGTransformableContainer.h"
-#include "SVGNames.h"
#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGGElement.h"
#include "core/svg/SVGGraphicsElement.h"
#include "core/svg/SVGUseElement.h"
@@ -37,25 +37,60 @@ RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElem
{
}
+static bool hasValidPredecessor(const Node* node)
+{
+ ASSERT(node);
+ while ((node = node->previousSibling())) {
+ if (node->isSVGElement() && toSVGElement(node)->isValid())
+ return true;
+ }
+ return false;
+}
+
+bool RenderSVGTransformableContainer::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+ ASSERT(element());
+ if (isSVGSwitchElement(*element())) {
+ Node* node = child->node();
+ // Reject non-SVG/non-valid elements.
+ if (!node->isSVGElement() || !toSVGElement(node)->isValid())
+ return false;
+ // Reject this child if it isn't the first valid node.
+ if (hasValidPredecessor(node))
+ return false;
+ } else if (isSVGAElement(*element())) {
+ // http://www.w3.org/2003/01/REC-SVG11-20030114-errata#linking-text-environment
+ // The 'a' element may contain any element that its parent may contain, except itself.
+ if (isSVGAElement(*child->node()))
+ return false;
+ if (parent() && parent()->isSVG())
+ return parent()->isChildAllowed(child, style);
+ }
+ return RenderSVGContainer::isChildAllowed(child, style);
+}
+
bool RenderSVGTransformableContainer::calculateLocalTransform()
{
SVGGraphicsElement* element = toSVGGraphicsElement(this->element());
+ ASSERT(element);
// If we're either the renderer for a <use> element, or for any <g> element inside the shadow
// tree, that was created during the use/symbol/svg expansion in SVGUseElement. These containers
// need to respect the translations induced by their corresponding use elements x/y attributes.
SVGUseElement* useElement = 0;
- if (element->hasTagName(SVGNames::useTag))
+ if (isSVGUseElement(*element)) {
useElement = toSVGUseElement(element);
- else if (element->isInShadowTree() && element->hasTagName(SVGNames::gTag)) {
+ } else if (isSVGGElement(*element) && toSVGGElement(element)->inUseShadowTree()) {
SVGElement* correspondingElement = element->correspondingElement();
- if (correspondingElement && correspondingElement->hasTagName(SVGNames::useTag))
+ if (isSVGUseElement(correspondingElement))
useElement = toSVGUseElement(correspondingElement);
}
if (useElement) {
SVGLengthContext lengthContext(useElement);
- FloatSize translation(useElement->xCurrentValue().value(lengthContext), useElement->yCurrentValue().value(lengthContext));
+ FloatSize translation(
+ useElement->x()->currentValue()->value(lengthContext),
+ useElement->y()->currentValue()->value(lengthContext));
if (translation != m_lastTranslation)
m_needsTransformUpdate = true;
m_lastTranslation = translation;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h
index 6aa752aa95d..4b03d8a330d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGTransformableContainer.h
@@ -30,14 +30,16 @@ class RenderSVGTransformableContainer FINAL : public RenderSVGContainer {
public:
explicit RenderSVGTransformableContainer(SVGGraphicsElement*);
- virtual bool isSVGTransformableContainer() const { return true; }
- virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
- virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+ virtual bool isSVGTransformableContainer() const OVERRIDE { return true; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localTransform; }
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
+ virtual bool didTransformToRootUpdate() OVERRIDE { return m_didTransformToRootUpdate; }
private:
- virtual bool calculateLocalTransform();
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual bool calculateLocalTransform() OVERRIDE;
+ virtual AffineTransform localTransform() const OVERRIDE { return m_localTransform; }
bool m_needsTransformUpdate : 1;
bool m_didTransformToRootUpdate : 1;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
index 05234c18b57..4b4d3d5d4c3 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
@@ -21,11 +21,10 @@
*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGViewportContainer.h"
-#include "SVGNames.h"
-#include "core/svg/SVGElementInstance.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
#include "core/svg/SVGSVGElement.h"
#include "core/svg/SVGUseElement.h"
#include "platform/graphics/GraphicsContext.h"
@@ -42,7 +41,8 @@ RenderSVGViewportContainer::RenderSVGViewportContainer(SVGElement* node)
void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
{
- if (!element()->hasTagName(SVGNames::svgTag))
+ ASSERT(element());
+ if (!isSVGSVGElement(*element()))
return;
m_isLayoutSizeChanged = toSVGSVGElement(element())->hasRelativeLengths() && selfNeedsLayout();
@@ -57,59 +57,14 @@ void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
void RenderSVGViewportContainer::calcViewport()
{
SVGElement* element = this->element();
- if (!element->hasTagName(SVGNames::svgTag))
+ ASSERT(element);
+ if (!isSVGSVGElement(*element))
return;
SVGSVGElement* svg = toSVGSVGElement(element);
FloatRect oldViewport = m_viewport;
SVGLengthContext lengthContext(element);
- m_viewport = FloatRect(svg->xCurrentValue().value(lengthContext), svg->yCurrentValue().value(lengthContext), svg->widthCurrentValue().value(lengthContext), svg->heightCurrentValue().value(lengthContext));
-
- SVGElement* correspondingElement = svg->correspondingElement();
- if (correspondingElement && svg->isInShadowTree()) {
- const HashSet<SVGElementInstance*>& instances = correspondingElement->instancesForElement();
- ASSERT(!instances.isEmpty());
-
- SVGUseElement* useElement = 0;
- const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
- for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
- const SVGElementInstance* instance = (*it);
- ASSERT(instance->correspondingElement()->hasTagName(SVGNames::svgTag) || instance->correspondingElement()->hasTagName(SVGNames::symbolTag));
- if (instance->shadowTreeElement() == svg) {
- ASSERT(correspondingElement == instance->correspondingElement());
- useElement = instance->directUseElement();
- if (!useElement)
- useElement = instance->correspondingUseElement();
- break;
- }
- }
-
- ASSERT(useElement);
- bool isSymbolElement = correspondingElement->hasTagName(SVGNames::symbolTag);
-
- // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
- // If attributes width and/or height are provided on the 'use' element, then these attributes
- // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
- // the generated 'svg' element will use values of 100% for these attributes.
-
- // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
- // values will override the corresponding attributes on the 'svg' in the generated tree.
-
- SVGLengthContext lengthContext(element);
- if (useElement->hasAttribute(SVGNames::widthAttr))
- m_viewport.setWidth(useElement->widthCurrentValue().value(lengthContext));
- else if (isSymbolElement && svg->hasAttribute(SVGNames::widthAttr)) {
- SVGLength containerWidth(LengthModeWidth, "100%");
- m_viewport.setWidth(containerWidth.value(lengthContext));
- }
-
- if (useElement->hasAttribute(SVGNames::heightAttr))
- m_viewport.setHeight(useElement->heightCurrentValue().value(lengthContext));
- else if (isSymbolElement && svg->hasAttribute(SVGNames::heightAttr)) {
- SVGLength containerHeight(LengthModeHeight, "100%");
- m_viewport.setHeight(containerHeight.value(lengthContext));
- }
- }
+ m_viewport = FloatRect(svg->x()->currentValue()->value(lengthContext), svg->y()->currentValue()->value(lengthContext), svg->width()->currentValue()->value(lengthContext), svg->height()->currentValue()->value(lengthContext));
if (oldViewport != m_viewport) {
setNeedsBoundariesUpdate();
@@ -130,7 +85,8 @@ bool RenderSVGViewportContainer::calculateLocalTransform()
AffineTransform RenderSVGViewportContainer::viewportTransform() const
{
- if (element()->hasTagName(SVGNames::svgTag)) {
+ ASSERT(element());
+ if (isSVGSVGElement(*element())) {
SVGSVGElement* svg = toSVGSVGElement(element());
return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
}
@@ -149,11 +105,10 @@ bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& poi
void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
+ ASSERT(element());
// An empty viewBox disables rendering.
- if (element()->hasTagName(SVGNames::svgTag)) {
- if (toSVGSVGElement(element())->hasEmptyViewBox())
- return;
- }
+ if (isSVGSVGElement(*element()) && toSVGSVGElement(*element()).hasEmptyViewBox())
+ return;
RenderSVGContainer::paint(paintInfo, paintOffset);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h
index b1b79ed5e31..679bd051dc7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/RenderSVGViewportContainer.h
@@ -35,25 +35,25 @@ public:
FloatRect viewport() const { return m_viewport; }
bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
- virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+ virtual bool didTransformToRootUpdate() OVERRIDE { return m_didTransformToRootUpdate; }
- virtual void determineIfLayoutSizeChanged();
- virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+ virtual void determineIfLayoutSizeChanged() OVERRIDE;
+ virtual void setNeedsTransformUpdate() OVERRIDE { m_needsTransformUpdate = true; }
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
private:
- virtual bool isSVGViewportContainer() const { return true; }
- virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+ virtual bool isSVGViewportContainer() const OVERRIDE { return true; }
+ virtual const char* renderName() const OVERRIDE { return "RenderSVGViewportContainer"; }
AffineTransform viewportTransform() const;
- virtual const AffineTransform& localToParentTransform() const { return m_localToParentTransform; }
+ virtual const AffineTransform& localToParentTransform() const OVERRIDE { return m_localToParentTransform; }
- virtual void calcViewport();
- virtual bool calculateLocalTransform();
+ virtual void calcViewport() OVERRIDE;
+ virtual bool calculateLocalTransform() OVERRIDE;
- virtual void applyViewportClip(PaintInfo&);
- virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent);
+ virtual void applyViewportClip(PaintInfo&) OVERRIDE;
+ virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent) OVERRIDE;
FloatRect m_viewport;
mutable AffineTransform m_localToParentTransform;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp
index c4f5cdb1203..d4a861c3db2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.cpp
@@ -23,8 +23,6 @@
#include "config.h"
#include "core/rendering/svg/SVGInlineFlowBox.h"
-#include "core/dom/DocumentMarkerController.h"
-#include "core/dom/RenderedDocumentMarker.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/SVGInlineTextBox.h"
#include "core/rendering/svg/SVGRenderingContext.h"
@@ -47,22 +45,15 @@ void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo)
}
}
-void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
- RenderObject* boxRenderer = renderer();
- ASSERT(boxRenderer);
-
- SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext);
+ SVGRenderingContext renderingContext(&renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer()));
-
- child->paint(paintInfo, LayoutPoint(), 0, 0);
- }
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->paint(paintInfo, paintOffset, 0, 0);
}
}
@@ -77,66 +68,4 @@ FloatRect SVGInlineFlowBox::calculateBoundaries() const
return childRect;
}
-void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer)
-{
- ASSERT(textRenderer);
-
- Node* node = textRenderer->node();
- if (!node || !node->inDocument())
- return;
-
- RenderStyle* style = textRenderer->style();
- ASSERT(style);
-
- AffineTransform fragmentTransform;
- Document& document = textRenderer->document();
- Vector<DocumentMarker*> markers = document.markers()->markersFor(textRenderer->node());
-
- Vector<DocumentMarker*>::iterator markerEnd = markers.end();
- for (Vector<DocumentMarker*>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) {
- DocumentMarker* marker = *markerIt;
-
- // SVG is only interessted in the TextMatch marker, for now.
- if (marker->type() != DocumentMarker::TextMatch)
- continue;
-
- FloatRect markerRect;
- for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if (!box->isSVGInlineTextBox())
- continue;
-
- SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
-
- int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0);
- int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len());
-
- if (markerStartPosition >= markerEndPosition)
- continue;
-
- int fragmentStartPosition = 0;
- int fragmentEndPosition = 0;
-
- const Vector<SVGTextFragment>& fragments = textBox->textFragments();
- unsigned textFragmentsSize = fragments.size();
- for (unsigned i = 0; i < textFragmentsSize; ++i) {
- const SVGTextFragment& fragment = fragments.at(i);
-
- fragmentStartPosition = markerStartPosition;
- fragmentEndPosition = markerEndPosition;
- if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
- continue;
-
- FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
- fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
-
- markerRect.unite(fragmentRect);
- }
- }
-
- toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox());
- }
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h
index e76a9ccdafc..0d66044e42b 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineFlowBox.h
@@ -25,26 +25,22 @@
namespace WebCore {
-class RenderSVGInlineText;
-
class SVGInlineFlowBox FINAL : public InlineFlowBox {
public:
- SVGInlineFlowBox(RenderObject* obj)
+ SVGInlineFlowBox(RenderObject& obj)
: InlineFlowBox(obj)
, m_logicalHeight(0)
{
}
- virtual bool isSVGInlineFlowBox() const { return true; }
- virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+ virtual bool isSVGInlineFlowBox() const OVERRIDE { return true; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return m_logicalHeight; }
void setLogicalHeight(float h) { m_logicalHeight = h; }
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
-
- virtual FloatRect calculateBoundaries() const;
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
- static void computeTextMatchMarkerRectForRenderer(RenderSVGInlineText*);
+ virtual FloatRect calculateBoundaries() const OVERRIDE;
private:
float m_logicalHeight;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp
index 6c593827328..a5dc2fc742c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.cpp
@@ -22,11 +22,17 @@
#include "config.h"
#include "core/rendering/svg/SVGInlineTextBox.h"
-#include "core/frame/Frame.h"
+#include "core/dom/DocumentMarkerController.h"
+#include "core/dom/RenderedDocumentMarker.h"
+#include "core/editing/Editor.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/InlineFlowBox.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/PointerEventsHitRules.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderTheme.h"
#include "core/rendering/style/ShadowList.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGResource.h"
@@ -35,7 +41,7 @@
#include "core/rendering/svg/SVGTextRunRenderingContext.h"
#include "platform/FloatConversion.h"
#include "platform/fonts/FontCache.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
using namespace std;
@@ -44,17 +50,16 @@ namespace WebCore {
struct ExpectedSVGInlineTextBoxSize : public InlineTextBox {
float float1;
- uint32_t bitfields : 5;
+ uint32_t bitfields : 1;
void* pointer;
Vector<SVGTextFragment> vector;
};
COMPILE_ASSERT(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize), SVGInlineTextBox_is_not_of_expected_size);
-SVGInlineTextBox::SVGInlineTextBox(RenderObject* object)
+SVGInlineTextBox::SVGInlineTextBox(RenderObject& object)
: InlineTextBox(object)
, m_logicalHeight(0)
- , m_paintingResourceMode(ApplyToDefaultMode)
, m_startsNewTextChunk(false)
, m_paintingResource(0)
{
@@ -84,13 +89,12 @@ int SVGInlineTextBox::offsetForPosition(float, bool) const
int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
{
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- RenderStyle* style = textRenderer->style();
+ RenderStyle* style = textRenderer.style();
ASSERT(style);
TextRun textRun = constructTextRun(style, fragment);
@@ -102,7 +106,7 @@ int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
if (!fragmentTransform.isIdentity())
textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
- return fragment.characterOffset - start() + textRenderer->scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
+ return fragment.characterOffset - start() + textRenderer.scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
float SVGInlineTextBox::positionForOffset(int) const
@@ -119,13 +123,12 @@ FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
FontCachePurgePreventer fontCachePurgePreventer;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = textRenderer->scaledFont();
+ const Font& scaledFont = textRenderer.scaledFont();
const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
FloatPoint textOrigin(fragment.x, fragment.y);
if (scalingFactor != 1)
@@ -149,10 +152,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
if (startPosition >= endPosition)
return LayoutRect();
- RenderText* text = textRenderer();
- ASSERT(text);
-
- RenderStyle* style = text->style();
+ RenderStyle* style = textRenderer().style();
ASSERT(style);
AffineTransform fragmentTransform;
@@ -171,8 +171,7 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
selectionRect.unite(fragmentRect);
}
@@ -180,25 +179,24 @@ LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPositi
return enclosingIntRect(selectionRect);
}
-static inline bool textShouldBePainted(RenderSVGInlineText* textRenderer)
+static inline bool textShouldBePainted(RenderSVGInlineText& textRenderer)
{
// Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
// If the absolute font size on screen is below x=0.5, don't render anything.
- return textRenderer->scaledFont().pixelSize();
+ return textRenderer.scaledFont().fontDescription().computedPixelSize();
}
void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
{
- ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
+ ASSERT(paintInfo.shouldPaintWithinRoot(&renderer()));
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(truncation() == cNoTruncation);
- if (renderer()->style()->visibility() != VISIBLE)
+ if (renderer().style()->visibility() != VISIBLE)
return;
- RenderObject* parentRenderer = parent()->renderer();
- ASSERT(parentRenderer);
- ASSERT(!parentRenderer->document().printing());
+ RenderObject& parentRenderer = parent()->renderer();
+ ASSERT(!parentRenderer.document().printing());
// Determine whether or not we're selected.
bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
@@ -206,25 +204,17 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
if (!hasSelection || paintSelectedTextOnly)
return;
- Color backgroundColor = renderer()->selectionBackgroundColor();
- if (!backgroundColor.isValid() || !backgroundColor.alpha())
+ Color backgroundColor = renderer().selectionBackgroundColor();
+ if (!backgroundColor.alpha())
return;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
if (!textShouldBePainted(textRenderer))
return;
- RenderStyle* style = parentRenderer->style();
+ RenderStyle* style = parentRenderer.style();
ASSERT(style);
- RenderStyle* selectionStyle = style;
- if (hasSelection) {
- selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
- if (!selectionStyle)
- selectionStyle = style;
- }
-
int startPosition, endPosition;
selectionStartEnd(startPosition, endPosition);
@@ -248,41 +238,39 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
paintInfo.context->setFillColor(backgroundColor);
paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor);
-
- m_paintingResourceMode = ApplyToDefaultMode;
}
ASSERT(!m_paintingResource);
}
-void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
- ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
+ ASSERT(paintInfo.shouldPaintWithinRoot(&renderer()));
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(truncation() == cNoTruncation);
- if (renderer()->style()->visibility() != VISIBLE)
+ if (renderer().style()->visibility() != VISIBLE)
return;
// Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
// If we ever need that for SVG, it's very easy to refactor and reuse the code.
- RenderObject* parentRenderer = parent()->renderer();
- ASSERT(parentRenderer);
+ RenderObject& parentRenderer = parent()->renderer();
bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
- bool hasSelection = !parentRenderer->document().printing() && selectionState() != RenderObject::SelectionNone;
+ bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone;
if (!hasSelection && paintSelectedTextOnly)
return;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
if (!textShouldBePainted(textRenderer))
return;
- RenderStyle* style = parentRenderer->style();
+ RenderStyle* style = parentRenderer.style();
ASSERT(style);
+ paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer.scaledFont(), true);
+
const SVGRenderStyle* svgStyle = style->svgStyle();
ASSERT(svgStyle);
@@ -291,7 +279,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
RenderStyle* selectionStyle = style;
if (hasSelection) {
- selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
+ selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION);
if (selectionStyle) {
const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle();
ASSERT(svgSelectionStyle);
@@ -300,11 +288,12 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
hasFill = svgSelectionStyle->hasFill();
if (!hasVisibleStroke)
hasVisibleStroke = svgSelectionStyle->hasVisibleStroke();
- } else
+ } else {
selectionStyle = style;
+ }
}
- if (textRenderer->frame() && textRenderer->frame()->view() && textRenderer->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
+ if (textRenderer.frame() && textRenderer.frame()->view() && textRenderer.frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
hasFill = true;
hasVisibleStroke = false;
}
@@ -315,10 +304,12 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
SVGTextFragment& fragment = m_textFragments.at(i);
ASSERT(!m_paintingResource);
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
+ if (!fragmentTransform.isIdentity()) {
+ stateSaver.save();
paintInfo.context->concatCTM(fragmentTransform);
+ }
// Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations.
unsigned decorations = style->textDecorationsInEffect();
@@ -332,15 +323,15 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
case PT_FILL:
// Fill text
if (hasFill) {
- m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode;
- paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ paintText(paintInfo.context, style, selectionStyle, fragment,
+ ApplyToFillMode | ApplyToTextMode, hasSelection, paintSelectedTextOnly);
}
break;
case PT_STROKE:
// Stroke text
if (hasVisibleStroke) {
- m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
- paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+ paintText(paintInfo.context, style, selectionStyle, fragment,
+ ApplyToStrokeMode | ApplyToTextMode, hasSelection, paintSelectedTextOnly);
}
break;
case PT_MARKERS:
@@ -355,25 +346,29 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
// Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text.
if (decorations & TextDecorationLineThrough)
paintDecoration(paintInfo.context, TextDecorationLineThrough, fragment);
-
- m_paintingResourceMode = ApplyToDefaultMode;
}
+ // finally, paint the outline if any
+ if (style->hasOutline() && parentRenderer.isRenderInline())
+ toRenderInline(parentRenderer).paintOutline(paintInfo, paintOffset);
+
ASSERT(!m_paintingResource);
}
-bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderObject* renderer, RenderStyle* style)
+bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor,
+ RenderObject* renderer, RenderStyle* style, RenderSVGResourceModeFlags resourceMode)
{
+ // Callers must save the context state before calling when scalingFactor is not 1.
ASSERT(scalingFactor);
ASSERT(renderer);
ASSERT(style);
- ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
+ ASSERT(resourceMode != ApplyToDefaultMode);
- Color fallbackColor;
- if (m_paintingResourceMode & ApplyToFillMode)
- m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, fallbackColor);
- else if (m_paintingResourceMode & ApplyToStrokeMode)
- m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, fallbackColor);
+ bool hasFallback = false;
+ if (resourceMode & ApplyToFillMode)
+ m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, hasFallback);
+ else if (resourceMode & ApplyToStrokeMode)
+ m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, hasFallback);
else {
// We're either called for stroking or filling.
ASSERT_NOT_REACHED();
@@ -382,36 +377,32 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float
if (!m_paintingResource)
return false;
- if (!m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode)) {
- if (fallbackColor.isValid()) {
- RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
- fallbackResource->setColor(fallbackColor);
-
- m_paintingResource = fallbackResource;
- m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode);
+ if (!m_paintingResource->applyResource(renderer, style, context, resourceMode)) {
+ if (hasFallback) {
+ m_paintingResource = RenderSVGResource::sharedSolidPaintingResource();
+ m_paintingResource->applyResource(renderer, style, context, resourceMode);
}
}
- if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode)
+ if (scalingFactor != 1 && resourceMode & ApplyToStrokeMode)
context->setStrokeThickness(context->strokeThickness() * scalingFactor);
return true;
}
-void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path)
+void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path,
+ RenderSVGResourceModeFlags resourceMode)
{
ASSERT(m_paintingResource);
- RenderObject* parentRenderer = parent()->renderer();
- ASSERT(parentRenderer);
-
- m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode, path, /*RenderSVGShape*/ 0);
+ m_paintingResource->postApplyResource(&parent()->renderer(), context, resourceMode, path, 0);
m_paintingResource = 0;
}
-bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, TextRun& textRun, RenderStyle* style)
+bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context,
+ float scalingFactor, TextRun& textRun, RenderStyle* style, RenderSVGResourceModeFlags resourceMode)
{
- bool acquiredResource = acquirePaintingResource(context, scalingFactor, parent()->renderer(), style);
+ bool acquiredResource = acquirePaintingResource(context, scalingFactor, &parent()->renderer(), style, resourceMode);
if (!acquiredResource)
return false;
@@ -425,9 +416,10 @@ bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c
return true;
}
-void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun)
+void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context,
+ TextRun& textRun, RenderSVGResourceModeFlags resourceMode)
{
- releasePaintingResource(context, /* path */0);
+ releasePaintingResource(context, 0, resourceMode);
#if ENABLE(SVG_FONTS)
TextRun::RenderingContext* renderingContext = textRun.renderingContext();
@@ -439,10 +431,8 @@ void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*&
TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const
{
ASSERT(style);
- ASSERT(textRenderer());
- RenderText* text = textRenderer();
- ASSERT(text);
+ RenderText* text = &textRenderer();
// FIXME(crbug.com/264211): This should not be necessary but can occur if we
// layout during layout. Remove this when 264211 is fixed.
@@ -523,7 +513,7 @@ static inline float thicknessForDecoration(TextDecoration, const Font& font)
{
// FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
// Compatible with Batik/Opera
- return font.size() / 20.0f;
+ return font.fontDescription().computedSize() / 20.0f;
}
static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowBox* parentBox)
@@ -531,7 +521,7 @@ static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB
// Lookup first render object in parent hierarchy which has text-decoration set.
RenderObject* renderer = 0;
while (parentBox) {
- renderer = parentBox->renderer();
+ renderer = &parentBox->renderer();
if (renderer->style() && renderer->style()->textDecoration() != TextDecorationNone)
break;
@@ -545,7 +535,7 @@ static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB
void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment)
{
- if (textRenderer()->style()->textDecorationsInEffect() == TextDecorationNone)
+ if (textRenderer().style()->textDecorationsInEffect() == TextDecorationNone)
return;
// Find out which render style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours.
@@ -559,24 +549,29 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration
const SVGRenderStyle* svgDecorationStyle = decorationStyle->svgStyle();
ASSERT(svgDecorationStyle);
- bool hasDecorationFill = svgDecorationStyle->hasFill();
- bool hasVisibleDecorationStroke = svgDecorationStyle->hasVisibleStroke();
-
- if (hasDecorationFill) {
- m_paintingResourceMode = ApplyToFillMode;
- paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
- }
-
- if (hasVisibleDecorationStroke) {
- m_paintingResourceMode = ApplyToStrokeMode;
- paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
+ for (int i = 0; i < 3; i++) {
+ switch (svgDecorationStyle->paintOrderType(i)) {
+ case PT_FILL:
+ if (svgDecorationStyle->hasFill())
+ paintDecorationWithStyle(context, decoration, fragment, decorationRenderer, ApplyToFillMode);
+ break;
+ case PT_STROKE:
+ if (svgDecorationStyle->hasVisibleStroke())
+ paintDecorationWithStyle(context, decoration, fragment, decorationRenderer, ApplyToStrokeMode);
+ break;
+ case PT_MARKERS:
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
}
}
-void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer)
+void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration,
+ const SVGTextFragment& fragment, RenderObject* decorationRenderer, RenderSVGResourceModeFlags resourceMode)
{
ASSERT(!m_paintingResource);
- ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
+ ASSERT(resourceMode != ApplyToDefaultMode);
RenderStyle* decorationStyle = decorationRenderer->style();
ASSERT(decorationStyle);
@@ -596,11 +591,12 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe
float width = fragment.width;
const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
- GraphicsContextStateSaver stateSaver(*context);
+ GraphicsContextStateSaver stateSaver(*context, false);
if (scalingFactor != 1) {
+ stateSaver.save();
width *= scalingFactor;
decorationOrigin.scale(scalingFactor, scalingFactor);
- context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+ context->scale(1 / scalingFactor, 1 / scalingFactor);
}
decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness));
@@ -608,19 +604,22 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDe
Path path;
path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness)));
- if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle))
- releasePaintingResource(context, &path);
+ // acquirePaintingResource also modifies state if the scalingFactor is non-identity.
+ // Above we have saved the state for this case.
+ if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle, resourceMode))
+ releasePaintingResource(context, &path, resourceMode);
}
-void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
+void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style,
+ TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition,
+ RenderSVGResourceModeFlags resourceMode)
{
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- const Font& scaledFont = textRenderer->scaledFont();
+ const Font& scaledFont = textRenderer.scaledFont();
const ShadowList* shadowList = style->textShadow();
// Text shadows are disabled when printing. http://crbug.com/258321
@@ -633,28 +632,28 @@ void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
textOrigin.scale(scalingFactor, scalingFactor);
textSize.scale(scalingFactor);
context->save();
- context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+ context->scale(1 / scalingFactor, 1 / scalingFactor);
}
if (hasShadow) {
- DrawLooper drawLooper;
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
for (size_t i = shadowList->shadows().size(); i--; ) {
const ShadowData& shadow = shadowList->shadows()[i];
FloatSize offset(shadow.x(), shadow.y());
- drawLooper.addShadow(offset, shadow.blur(), shadow.color(),
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowRespectsAlpha);
+ drawLooperBuilder->addShadow(offset, shadow.blur(), shadow.color(),
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowRespectsAlpha);
}
- drawLooper.addUnmodifiedContent();
- context->setDrawLooper(drawLooper);
+ drawLooperBuilder->addUnmodifiedContent();
+ context->setDrawLooper(drawLooperBuilder.release());
}
- if (prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style)) {
+ if (prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style, resourceMode)) {
TextRunPaintInfo textRunPaintInfo(textRun);
textRunPaintInfo.from = startPosition;
textRunPaintInfo.to = endPosition;
textRunPaintInfo.bounds = FloatRect(textOrigin, textSize);
scaledFont.drawText(context, textRunPaintInfo, textOrigin);
- restoreGraphicsContextAfterTextPainting(context, textRun);
+ restoreGraphicsContextAfterTextPainting(context, textRun, resourceMode);
}
if (scalingFactor != 1)
@@ -663,7 +662,9 @@ void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyl
context->clearShadow();
}
-void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, RenderStyle* selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
+void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style,
+ RenderStyle* selectionStyle, const SVGTextFragment& fragment,
+ RenderSVGResourceModeFlags resourceMode, bool hasSelection, bool paintSelectedTextOnly)
{
ASSERT(style);
ASSERT(selectionStyle);
@@ -678,40 +679,104 @@ void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, R
// Fast path if there is no selection, just draw the whole chunk part using the regular style
TextRun textRun = constructTextRun(style, fragment);
if (!hasSelection || startPosition >= endPosition) {
- paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length);
+ paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length, resourceMode);
return;
}
// Eventually draw text using regular style until the start position of the selection
if (startPosition > 0 && !paintSelectedTextOnly)
- paintTextWithShadows(context, style, textRun, fragment, 0, startPosition);
+ paintTextWithShadows(context, style, textRun, fragment, 0, startPosition, resourceMode);
// Draw text using selection style from the start to the end position of the selection
- if (style != selectionStyle)
- SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle);
+ if (style != selectionStyle) {
+ StyleDifference diff;
+ diff.setNeedsRepaintObject();
+ SVGResourcesCache::clientStyleChanged(&parent()->renderer(), diff, selectionStyle);
+ }
- TextRun selectionTextRun = constructTextRun(selectionStyle, fragment);
- paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition);
+ paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition, resourceMode);
- if (style != selectionStyle)
- SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style);
+ if (style != selectionStyle) {
+ StyleDifference diff;
+ diff.setNeedsRepaintObject();
+ SVGResourcesCache::clientStyleChanged(&parent()->renderer(), diff, selectionStyle);
+ }
// Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
- paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length);
+ paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length, resourceMode);
+}
+
+void SVGInlineTextBox::paintDocumentMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&, bool)
+{
+ // SVG does not have support for generic document markers (e.g., spellchecking, etc).
+}
+
+void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const FloatPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font)
+{
+ // SVG is only interested in the TextMatch markers.
+ if (marker->type() != DocumentMarker::TextMatch)
+ return;
+
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
+
+ FloatRect markerRect;
+ AffineTransform fragmentTransform;
+ for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextTextBox()) {
+ if (!box->isSVGInlineTextBox())
+ continue;
+
+ SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
+
+ int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0);
+ int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len());
+
+ if (markerStartPosition >= markerEndPosition)
+ continue;
+
+ const Vector<SVGTextFragment>& fragments = textBox->textFragments();
+ unsigned textFragmentsSize = fragments.size();
+ for (unsigned i = 0; i < textFragmentsSize; ++i) {
+ const SVGTextFragment& fragment = fragments.at(i);
+
+ int fragmentStartPosition = markerStartPosition;
+ int fragmentEndPosition = markerEndPosition;
+ if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
+ continue;
+
+ FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
+ fragment.buildFragmentTransform(fragmentTransform);
+
+ // Draw the marker highlight.
+ if (renderer().frame()->editor().markedTextMatchesAreHighlighted()) {
+ Color color = marker->activeMatch() ?
+ RenderTheme::theme().platformActiveTextSearchHighlightColor() :
+ RenderTheme::theme().platformInactiveTextSearchHighlightColor();
+ GraphicsContextStateSaver stateSaver(*context);
+ if (!fragmentTransform.isIdentity())
+ context->concatCTM(fragmentTransform);
+ context->setFillColor(color);
+ context->fillRect(fragmentRect, color);
+ }
+
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ markerRect.unite(fragmentRect);
+ }
+ }
+
+ toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsoluteQuad(markerRect).enclosingBoundingBox());
}
FloatRect SVGInlineTextBox::calculateBoundaries() const
{
FloatRect textRect;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->textRenderer());
- float scalingFactor = textRenderer->scalingFactor();
+ float scalingFactor = textRenderer.scalingFactor();
ASSERT(scalingFactor);
- float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor;
+ float baseline = textRenderer.scaledFont().fontMetrics().floatAscent() / scalingFactor;
AffineTransform fragmentTransform;
unsigned textFragmentsSize = m_textFragments.size();
@@ -719,8 +784,7 @@ FloatRect SVGInlineTextBox::calculateBoundaries() const
const SVGTextFragment& fragment = m_textFragments.at(i);
FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
fragment.buildFragmentTransform(fragmentTransform);
- if (!fragmentTransform.isIdentity())
- fragmentRect = fragmentTransform.mapRect(fragmentRect);
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
textRect.unite(fragmentRect);
}
@@ -733,18 +797,18 @@ bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
// FIXME: integrate with InlineTextBox::nodeAtPoint better.
ASSERT(!isLineBreak());
- PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, renderer()->style()->pointerEvents());
- bool isVisible = renderer()->style()->visibility() == VISIBLE;
+ PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, renderer().style()->pointerEvents());
+ bool isVisible = renderer().style()->visibility() == VISIBLE;
if (isVisible || !hitRules.requireVisible) {
if (hitRules.canHitBoundingBox
- || (hitRules.canHitStroke && (renderer()->style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
- || (hitRules.canHitFill && (renderer()->style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
+ || (hitRules.canHitStroke && (renderer().style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
+ || (hitRules.canHitFill && (renderer().style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
FloatPoint boxOrigin(x(), y());
boxOrigin.moveBy(accumulatedOffset);
FloatRect rect(boxOrigin, size());
if (locationInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+ renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+ if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect))
return true;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h
index ccec860b863..2a5cb1bcd0e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGInlineTextBox.h
@@ -23,38 +23,38 @@
#define SVGInlineTextBox_h
#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/svg/RenderSVGResource.h"
#include "core/rendering/svg/SVGTextLayoutEngine.h"
namespace WebCore {
class RenderSVGResource;
-class SVGRootInlineBox;
class SVGInlineTextBox FINAL : public InlineTextBox {
public:
- SVGInlineTextBox(RenderObject*);
+ SVGInlineTextBox(RenderObject&);
- virtual bool isSVGInlineTextBox() const { return true; }
+ virtual bool isSVGInlineTextBox() const OVERRIDE { return true; }
- virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return m_logicalHeight; }
void setLogicalHeight(float height) { m_logicalHeight = height; }
- virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
- virtual float positionForOffset(int offset) const;
+ virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const OVERRIDE;
+ virtual float positionForOffset(int offset) const OVERRIDE;
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual LayoutRect localSelectionRect(int startPosition, int endPosition);
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+ virtual LayoutRect localSelectionRect(int startPosition, int endPosition) OVERRIDE;
bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const;
- virtual FloatRect calculateBoundaries() const;
+ virtual FloatRect calculateBoundaries() const OVERRIDE;
void clearTextFragments() { m_textFragments.clear(); }
Vector<SVGTextFragment>& textFragments() { return m_textFragments; }
const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; }
- virtual void dirtyLineBoxes() OVERRIDE FINAL;
+ virtual void dirtyLineBoxes() OVERRIDE;
bool startsNewTextChunk() const { return m_startsNewTextChunk; }
void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; }
@@ -65,23 +65,30 @@ public:
private:
TextRun constructTextRun(RenderStyle*, const SVGTextFragment&) const;
- bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderObject*, RenderStyle*);
- void releasePaintingResource(GraphicsContext*&, const Path*);
+ bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderObject*,
+ RenderStyle*, RenderSVGResourceModeFlags);
+ void releasePaintingResource(GraphicsContext*&, const Path*, RenderSVGResourceModeFlags);
- bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&, RenderStyle*);
- void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&);
+ bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&,
+ RenderStyle*, RenderSVGResourceModeFlags);
+ void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&, RenderSVGResourceModeFlags);
void paintDecoration(GraphicsContext*, TextDecoration, const SVGTextFragment&);
- void paintDecorationWithStyle(GraphicsContext*, TextDecoration, const SVGTextFragment&, RenderObject* decorationRenderer);
- void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition);
- void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly);
+ void paintDecorationWithStyle(GraphicsContext*, TextDecoration, const SVGTextFragment&,
+ RenderObject* decorationRenderer, RenderSVGResourceModeFlags);
+ void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&,
+ int startPosition, int endPosition, RenderSVGResourceModeFlags);
+ void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&,
+ RenderSVGResourceModeFlags, bool hasSelection, bool paintSelectedTextOnly);
+
+ virtual void paintDocumentMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&, bool) OVERRIDE FINAL;
+ virtual void paintTextMatchMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&) OVERRIDE FINAL;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
private:
float m_logicalHeight;
- unsigned m_paintingResourceMode : 4;
- unsigned m_startsNewTextChunk : 1;
+ bool m_startsNewTextChunk : 1;
RenderSVGResource* m_paintingResource;
Vector<SVGTextFragment> m_textFragments;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h
index aebd83b3e1a..1b31b98b87f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGMarkerData.h
@@ -26,8 +26,6 @@
namespace WebCore {
-class RenderSVGResourceMarker;
-
enum SVGMarkerType {
StartMarker,
MidMarker,
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp
index f42f6410e57..5a18ba50295 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGPathData.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/svg/SVGPathData.h"
-#include "SVGNames.h"
+#include "core/SVGNames.h"
#include "core/svg/SVGCircleElement.h"
#include "core/svg/SVGEllipseElement.h"
#include "core/svg/SVGLineElement.h"
@@ -34,14 +34,16 @@
namespace WebCore {
+using namespace SVGNames;
+
static void updatePathFromCircleElement(SVGElement* element, Path& path)
{
SVGCircleElement* circle = toSVGCircleElement(element);
SVGLengthContext lengthContext(element);
- float r = circle->rCurrentValue().value(lengthContext);
+ float r = circle->r()->currentValue()->value(lengthContext);
if (r > 0)
- path.addEllipse(FloatRect(circle->cxCurrentValue().value(lengthContext) - r, circle->cyCurrentValue().value(lengthContext) - r, r * 2, r * 2));
+ path.addEllipse(FloatRect(circle->cx()->currentValue()->value(lengthContext) - r, circle->cy()->currentValue()->value(lengthContext) - r, r * 2, r * 2));
}
static void updatePathFromEllipseElement(SVGElement* element, Path& path)
@@ -49,13 +51,16 @@ static void updatePathFromEllipseElement(SVGElement* element, Path& path)
SVGEllipseElement* ellipse = toSVGEllipseElement(element);
SVGLengthContext lengthContext(element);
- float rx = ellipse->rxCurrentValue().value(lengthContext);
- if (rx <= 0)
+ float rx = ellipse->rx()->currentValue()->value(lengthContext);
+ if (rx < 0)
+ return;
+ float ry = ellipse->ry()->currentValue()->value(lengthContext);
+ if (ry < 0)
return;
- float ry = ellipse->ryCurrentValue().value(lengthContext);
- if (ry <= 0)
+ if (!rx && !ry)
return;
- path.addEllipse(FloatRect(ellipse->cxCurrentValue().value(lengthContext) - rx, ellipse->cyCurrentValue().value(lengthContext) - ry, rx * 2, ry * 2));
+
+ path.addEllipse(FloatRect(ellipse->cx()->currentValue()->value(lengthContext) - rx, ellipse->cy()->currentValue()->value(lengthContext) - ry, rx * 2, ry * 2));
}
static void updatePathFromLineElement(SVGElement* element, Path& path)
@@ -63,8 +68,8 @@ static void updatePathFromLineElement(SVGElement* element, Path& path)
SVGLineElement* line = toSVGLineElement(element);
SVGLengthContext lengthContext(element);
- path.moveTo(FloatPoint(line->x1CurrentValue().value(lengthContext), line->y1CurrentValue().value(lengthContext)));
- path.addLineTo(FloatPoint(line->x2CurrentValue().value(lengthContext), line->y2CurrentValue().value(lengthContext)));
+ path.moveTo(FloatPoint(line->x1()->currentValue()->value(lengthContext), line->y1()->currentValue()->value(lengthContext)));
+ path.addLineTo(FloatPoint(line->x2()->currentValue()->value(lengthContext), line->y2()->currentValue()->value(lengthContext)));
}
static void updatePathFromPathElement(SVGElement* element, Path& path)
@@ -72,32 +77,26 @@ static void updatePathFromPathElement(SVGElement* element, Path& path)
buildPathFromByteStream(toSVGPathElement(element)->pathByteStream(), path);
}
-static void updatePathFromPolygonElement(SVGElement* element, Path& path)
+static void updatePathFromPolylineElement(SVGElement* element, Path& path)
{
- SVGPointList& points = toSVGPolygonElement(element)->pointsCurrentValue();
- if (points.isEmpty())
+ RefPtr<SVGPointList> points = toSVGPolyElement(element)->points()->currentValue();
+ if (points->isEmpty())
return;
- path.moveTo(points.first());
-
- unsigned size = points.size();
- for (unsigned i = 1; i < size; ++i)
- path.addLineTo(points.at(i));
+ SVGPointList::ConstIterator it = points->begin();
+ SVGPointList::ConstIterator itEnd = points->end();
+ ASSERT(it != itEnd);
+ path.moveTo(it->value());
+ ++it;
- path.closeSubpath();
+ for (; it != itEnd; ++it)
+ path.addLineTo(it->value());
}
-static void updatePathFromPolylineElement(SVGElement* element, Path& path)
+static void updatePathFromPolygonElement(SVGElement* element, Path& path)
{
- SVGPointList& points = toSVGPolylineElement(element)->pointsCurrentValue();
- if (points.isEmpty())
- return;
-
- path.moveTo(points.first());
-
- unsigned size = points.size();
- for (unsigned i = 1; i < size; ++i)
- path.addLineTo(points.at(i));
+ updatePathFromPolylineElement(element, path);
+ path.closeSubpath();
}
static void updatePathFromRectElement(SVGElement* element, Path& path)
@@ -105,19 +104,21 @@ static void updatePathFromRectElement(SVGElement* element, Path& path)
SVGRectElement* rect = toSVGRectElement(element);
SVGLengthContext lengthContext(element);
- float width = rect->widthCurrentValue().value(lengthContext);
- if (width <= 0)
+ float width = rect->width()->currentValue()->value(lengthContext);
+ if (width < 0)
+ return;
+ float height = rect->height()->currentValue()->value(lengthContext);
+ if (height < 0)
return;
- float height = rect->heightCurrentValue().value(lengthContext);
- if (height <= 0)
+ if (!width && !height)
return;
- float x = rect->xCurrentValue().value(lengthContext);
- float y = rect->yCurrentValue().value(lengthContext);
- bool hasRx = rect->rxCurrentValue().value(lengthContext) > 0;
- bool hasRy = rect->ryCurrentValue().value(lengthContext) > 0;
+ float x = rect->x()->currentValue()->value(lengthContext);
+ float y = rect->y()->currentValue()->value(lengthContext);
+ float rx = rect->rx()->currentValue()->value(lengthContext);
+ float ry = rect->ry()->currentValue()->value(lengthContext);
+ bool hasRx = rx > 0;
+ bool hasRy = ry > 0;
if (hasRx || hasRy) {
- float rx = rect->rxCurrentValue().value(lengthContext);
- float ry = rect->ryCurrentValue().value(lengthContext);
if (!hasRx)
rx = ry;
else if (!hasRy)
@@ -139,13 +140,13 @@ void updatePathFromGraphicsElement(SVGElement* element, Path& path)
static HashMap<StringImpl*, PathUpdateFunction>* map = 0;
if (!map) {
map = new HashMap<StringImpl*, PathUpdateFunction>;
- map->set(SVGNames::circleTag.localName().impl(), updatePathFromCircleElement);
- map->set(SVGNames::ellipseTag.localName().impl(), updatePathFromEllipseElement);
- map->set(SVGNames::lineTag.localName().impl(), updatePathFromLineElement);
- map->set(SVGNames::pathTag.localName().impl(), updatePathFromPathElement);
- map->set(SVGNames::polygonTag.localName().impl(), updatePathFromPolygonElement);
- map->set(SVGNames::polylineTag.localName().impl(), updatePathFromPolylineElement);
- map->set(SVGNames::rectTag.localName().impl(), updatePathFromRectElement);
+ map->set(circleTag.localName().impl(), updatePathFromCircleElement);
+ map->set(ellipseTag.localName().impl(), updatePathFromEllipseElement);
+ map->set(lineTag.localName().impl(), updatePathFromLineElement);
+ map->set(pathTag.localName().impl(), updatePathFromPathElement);
+ map->set(polygonTag.localName().impl(), updatePathFromPolygonElement);
+ map->set(polylineTag.localName().impl(), updatePathFromPolylineElement);
+ map->set(rectTag.localName().impl(), updatePathFromRectElement);
}
if (PathUpdateFunction pathUpdateFunction = map->get(element->localName().impl()))
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp
index cfc4a641f7f..56c9e2cffdd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.cpp
@@ -23,9 +23,9 @@
*/
#include "config.h"
-
#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderGeometryMap.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/SubtreeLayoutScope.h"
@@ -51,8 +51,8 @@ LayoutRect SVGRenderSupport::clippedOverflowRectForRepaint(const RenderObject* o
// Pass our local paint rect to computeRectForRepaint() which will
// map to parent coords and recurse up the parent chain.
- FloatRect repaintRect = object->repaintRectInLocalCoordinates();
- object->computeFloatRectForRepaint(repaintContainer, repaintRect);
+ FloatRect repaintRect = object->paintInvalidationRectInLocalCoordinates();
+ object->computeFloatRectForPaintInvalidation(repaintContainer, repaintRect);
return enclosingLayoutRect(repaintRect);
}
@@ -60,9 +60,9 @@ void SVGRenderSupport::computeFloatRectForRepaint(const RenderObject* object, co
{
repaintRect.inflate(object->style()->outlineWidth());
- // Translate to coords in our parent renderer, and then call computeFloatRectForRepaint() on our parent.
+ // Translate to coords in our parent renderer, and then call computeFloatRectForPaintInvalidation() on our parent.
repaintRect = object->localToParentTransform().mapRect(repaintRect);
- object->parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+ object->parent()->computeFloatRectForPaintInvalidation(repaintContainer, repaintRect, fixed);
}
void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
@@ -100,18 +100,24 @@ const RenderObject* SVGRenderSupport::pushMappingToContainer(const RenderObject*
return parent;
}
-bool SVGRenderSupport::checkForSVGRepaintDuringLayout(RenderObject* object)
+bool SVGRenderSupport::parentTransformDidChange(RenderObject* object)
{
- if (!object->checkForRepaintDuringLayout())
- return false;
// When a parent container is transformed in SVG, all children will be painted automatically
// so we are able to skip redundant repaint checks.
RenderObject* parent = object->parent();
return !(parent && parent->isSVGContainer() && toRenderSVGContainer(parent)->didTransformToRootUpdate());
}
+bool SVGRenderSupport::checkForSVGRepaintDuringLayout(RenderObject* object)
+{
+ if (!object->checkForPaintInvalidationDuringLayout())
+ return false;
+
+ return parentTransformDidChange(object);
+}
+
// 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)
+inline void SVGRenderSupport::updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
{
bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
if (!otherValid)
@@ -135,18 +141,14 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* contain
// When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes
// the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound
// the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also.
- for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) {
+ for (RenderObject* current = container->slowFirstChild(); current; current = current->nextSibling()) {
if (current->isSVGHiddenContainer())
continue;
const AffineTransform& transform = current->localToParentTransform();
- if (transform.isIdentity()) {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
- strokeBoundingBox.unite(current->repaintRectInLocalCoordinates());
- } else {
- updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
- strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
- }
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current,
+ transform.mapRect(current->objectBoundingBox()));
+ strokeBoundingBox.unite(transform.mapRect(current->paintInvalidationRectInLocalCoordinates()));
}
repaintBoundingBox = strokeBoundingBox;
@@ -154,9 +156,6 @@ void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* contain
bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo)
{
- if (localTransform.isIdentity())
- return localRepaintRect.intersects(paintInfo.rect);
-
return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect);
}
@@ -170,17 +169,17 @@ const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* st
return toRenderSVGRoot(start);
}
-static inline void invalidateResourcesOfChildren(RenderObject* start)
+inline void SVGRenderSupport::invalidateResourcesOfChildren(RenderObject* start)
{
ASSERT(!start->needsLayout());
if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start))
resources->removeClientFromCache(start, false);
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling())
+ for (RenderObject* child = start->slowFirstChild(); child; child = child->nextSibling())
invalidateResourcesOfChildren(child);
}
-static inline bool layoutSizeOfNearestViewportChanged(const RenderObject* start)
+inline bool SVGRenderSupport::layoutSizeOfNearestViewportChanged(const RenderObject* start)
{
while (start && !start->isSVGRoot() && !start->isSVGViewportContainer())
start = start->parent();
@@ -212,7 +211,7 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
bool transformChanged = transformToRootChanged(start);
HashSet<RenderObject*> notlayoutedObjects;
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = start->slowFirstChild(); child; child = child->nextSibling()) {
bool needsLayout = selfNeedsLayout;
bool childEverHadLayout = child->everHadLayout();
@@ -228,9 +227,9 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
if (element->hasRelativeLengths()) {
// When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
- if (child->isSVGShape())
+ if (child->isSVGShape()) {
toRenderSVGShape(child)->setNeedsShapeUpdate();
- else if (child->isSVGText()) {
+ } else if (child->isSVGText()) {
toRenderSVGText(child)->setNeedsTextMetricsUpdate();
toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
}
@@ -240,7 +239,7 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
}
}
- SubtreeLayoutScope layoutScope(child);
+ SubtreeLayoutScope layoutScope(*child);
// Resource containers are nasty: they can invalidate clients outside the current SubtreeLayoutScope.
// Since they only care about viewport size changes (to resolve their relative lengths), we trigger
// their invalidation directly from SVGSVGElement::svgAttributeChange() or at a higher
@@ -257,9 +256,10 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
// We could handle this in the individual objects, but for now it's easier to have
// parent containers call repaint(). (RenderBlock::layout* has similar logic.)
if (!childEverHadLayout && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
- child->repaint();
- } else if (layoutSizeChanged)
+ child->paintInvalidationForWholeRenderer();
+ } else if (layoutSizeChanged) {
notlayoutedObjects.add(child);
+ }
}
if (!layoutSizeChanged) {
@@ -284,23 +284,16 @@ void SVGRenderSupport::layoutResourcesIfNeeded(const RenderObject* object)
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 StyleResolver::adjustRenderStyle
- ASSERT(object->style()->overflowX() != OSCROLL);
-
// RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size.
- ASSERT(!object->isRoot());
+ ASSERT(!object->isDocumentElement());
- return object->style()->overflowX() == OHIDDEN;
+ return object->style()->overflowX() == OHIDDEN || object->style()->overflowX() == OSCROLL;
}
-void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* object, FloatRect& repaintRect)
+void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* renderer, FloatRect& repaintRect)
{
- ASSERT(object);
+ ASSERT(renderer);
- RenderObject* renderer = const_cast<RenderObject*>(object);
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
if (!resources)
return;
@@ -357,21 +350,22 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const
ASSERT(svgStyle);
SVGLengthContext lengthContext(toSVGElement(object->node()));
- context->setStrokeThickness(svgStyle->strokeWidth().value(lengthContext));
+ context->setStrokeThickness(svgStyle->strokeWidth()->value(lengthContext));
context->setLineCap(svgStyle->capStyle());
context->setLineJoin(svgStyle->joinStyle());
context->setMiterLimit(svgStyle->strokeMiterLimit());
- const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
- if (dashes.isEmpty())
+ RefPtr<SVGLengthList> dashes = svgStyle->strokeDashArray();
+ if (dashes->isEmpty())
return;
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ SVGLengthList::ConstIterator it = dashes->begin();
+ SVGLengthList::ConstIterator itEnd = dashes->end();
+ for (; it != itEnd; ++it)
+ dashArray.append(it->value(lengthContext));
- context->setLineDash(dashArray, svgStyle->strokeDashOffset().value(lengthContext));
+ context->setLineDash(dashArray, svgStyle->strokeDashOffset()->value(lengthContext));
}
void SVGRenderSupport::applyStrokeStyleToStrokeData(StrokeData* strokeData, const RenderStyle* style, const RenderObject* object)
@@ -386,29 +380,28 @@ void SVGRenderSupport::applyStrokeStyleToStrokeData(StrokeData* strokeData, cons
ASSERT(svgStyle);
SVGLengthContext lengthContext(toSVGElement(object->node()));
- strokeData->setThickness(svgStyle->strokeWidth().value(lengthContext));
+ strokeData->setThickness(svgStyle->strokeWidth()->value(lengthContext));
strokeData->setLineCap(svgStyle->capStyle());
strokeData->setLineJoin(svgStyle->joinStyle());
strokeData->setMiterLimit(svgStyle->strokeMiterLimit());
- const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
- if (dashes.isEmpty())
+ RefPtr<SVGLengthList> dashes = svgStyle->strokeDashArray();
+ if (dashes->isEmpty())
return;
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ size_t length = dashes->length();
+ for (size_t i = 0; i < length; ++i)
+ dashArray.append(dashes->at(i)->value(lengthContext));
- strokeData->setLineDash(dashArray, svgStyle->strokeDashOffset().value(lengthContext));
+ strokeData->setLineDash(dashArray, svgStyle->strokeDashOffset()->value(lengthContext));
}
-bool SVGRenderSupport::isEmptySVGInlineText(const RenderObject* object)
+bool SVGRenderSupport::isRenderableTextNode(const RenderObject* object)
{
- // RenderSVGInlineText performs whitespace filtering in order to support xml:space
- // (http://www.w3.org/TR/SVG/struct.html#LangSpaceAttrs), and can end up with an empty string
- // even when its original constructor argument is non-empty.
- return object->isSVGInlineText() && toRenderSVGInlineText(object)->hasEmptyText();
+ ASSERT(object->isText());
+ // <br> is marked as text, but is not handled by the SVG rendering code-path.
+ return object->isSVGInlineText() && !toRenderSVGInlineText(object)->hasEmptyText();
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h
index 4265f64c780..087dcfbbd44 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderSupport.h
@@ -24,23 +24,22 @@
#ifndef SVGRenderSupport_h
#define SVGRenderSupport_h
-#include "core/rendering/PaintInfo.h"
-
namespace WebCore {
+class AffineTransform;
class FloatPoint;
class FloatRect;
-class ImageBuffer;
+class GraphicsContext;
class LayoutRect;
-class RenderBoxModelObject;
+struct PaintInfo;
class RenderGeometryMap;
class RenderLayerModelObject;
class RenderObject;
class RenderStyle;
class RenderSVGRoot;
+class StrokeData;
class TransformState;
-// SVGRendererSupport is a helper class sharing code between all SVG renderers.
class SVGRenderSupport {
public:
// Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Container
@@ -62,8 +61,11 @@ public:
static bool pointInClippingArea(RenderObject*, const FloatPoint&);
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&);
+ static bool parentTransformDidChange(RenderObject*);
+
// Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations
static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer);
static void computeFloatRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed);
@@ -81,13 +83,14 @@ public:
// FIXME: These methods do not belong here.
static const RenderSVGRoot* findTreeRootObject(const RenderObject*);
- // Helper method for determining whether an RenderSVGInlineText object has zero length text.
- static bool isEmptySVGInlineText(const RenderObject*);
+ // Helper method for determining if a RenderObject marked as text (isText()== true)
+ // can/will be rendered as part of a <text>.
+ static bool isRenderableTextNode(const RenderObject*);
private:
- // This class is not constructable.
- SVGRenderSupport();
- ~SVGRenderSupport();
+ static void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox);
+ static void invalidateResourcesOfChildren(RenderObject* start);
+ static bool layoutSizeOfNearestViewportChanged(const RenderObject* start);
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
index b92e9b99833..15726cb9c37 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
@@ -30,7 +30,6 @@
#include "core/rendering/svg/SVGRenderTreeAsText.h"
-#include "SVGNames.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderTreeAsText.h"
#include "core/rendering/svg/RenderSVGGradientStop.h"
@@ -64,6 +63,7 @@
#include "core/svg/SVGRadialGradientElement.h"
#include "core/svg/SVGRectElement.h"
#include "core/svg/SVGStopElement.h"
+#include "platform/graphics/DashArray.h"
#include "platform/graphics/GraphicsTypes.h"
#include <math.h>
@@ -154,15 +154,35 @@ static TextStream& operator<<(TextStream& ts, const WindRule rule)
return ts;
}
+namespace {
+
+template<typename Enum>
+String SVGEnumerationToString(Enum value)
+{
+ const SVGEnumerationStringEntries& entries = getStaticStringEntries<Enum>();
+
+ SVGEnumerationStringEntries::const_iterator it = entries.begin();
+ SVGEnumerationStringEntries::const_iterator itEnd = entries.end();
+ for (; it != itEnd; ++it) {
+ if (value == it->first)
+ return it->second;
+ }
+
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+}
+
static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType)
{
- ts << SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::toString(unitType);
+ ts << SVGEnumerationToString<SVGUnitTypes::SVGUnitType>(unitType);
return ts;
}
static TextStream& operator<<(TextStream& ts, const SVGMarkerUnitsType& markerUnit)
{
- ts << SVGPropertyTraits<SVGMarkerUnitsType>::toString(markerUnit);
+ ts << SVGEnumerationToString<SVGMarkerUnitsType>(markerUnit);
return ts;
}
@@ -221,7 +241,7 @@ static TextStream& operator<<(TextStream& ts, LineJoin style)
static TextStream& operator<<(TextStream& ts, const SVGSpreadMethodType& type)
{
- ts << SVGPropertyTraits<SVGSpreadMethodType>::toString(type).upper();
+ ts << SVGEnumerationToString<SVGSpreadMethodType>(type).upper();
return ts;
}
@@ -260,21 +280,22 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object);
ASSERT(shape.element());
- Color fallbackColor;
- if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
+ bool hasFallback;
+ if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), hasFallback)) {
TextStreamSeparator s(" ");
ts << " [stroke={" << s;
writeSVGPaintingResource(ts, strokePaintingResource);
SVGLengthContext lengthContext(shape.element());
- double dashOffset = svgStyle->strokeDashOffset().value(lengthContext);
- double strokeWidth = svgStyle->strokeWidth().value(lengthContext);
- const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
+ double dashOffset = svgStyle->strokeDashOffset()->value(lengthContext);
+ double strokeWidth = svgStyle->strokeWidth()->value(lengthContext);
+ RefPtr<SVGLengthList> dashes = svgStyle->strokeDashArray();
DashArray dashArray;
- const Vector<SVGLength>::const_iterator end = dashes.end();
- for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
- dashArray.append((*it).value(lengthContext));
+ SVGLengthList::ConstIterator it = dashes->begin();
+ SVGLengthList::ConstIterator itEnd = dashes->end();
+ for (; it != itEnd; ++it)
+ dashArray.append(it->value(lengthContext));
writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f);
writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0);
@@ -288,7 +309,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
ts << "}]";
}
- if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
+ if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), hasFallback)) {
TextStreamSeparator s(" ");
ts << " [fill={" << s;
writeSVGPaintingResource(ts, fillPaintingResource);
@@ -317,37 +338,38 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
writePositionAndStyle(ts, shape);
SVGElement* svgElement = shape.element();
+ ASSERT(svgElement);
SVGLengthContext lengthContext(svgElement);
- if (svgElement->hasTagName(SVGNames::rectTag)) {
- SVGRectElement* element = toSVGRectElement(svgElement);
- writeNameValuePair(ts, "x", element->xCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "y", element->yCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "width", element->widthCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "height", element->heightCurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::lineTag)) {
- SVGLineElement* element = toSVGLineElement(svgElement);
- writeNameValuePair(ts, "x1", element->x1CurrentValue().value(lengthContext));
- writeNameValuePair(ts, "y1", element->y1CurrentValue().value(lengthContext));
- writeNameValuePair(ts, "x2", element->x2CurrentValue().value(lengthContext));
- writeNameValuePair(ts, "y2", element->y2CurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::ellipseTag)) {
- SVGEllipseElement* element = toSVGEllipseElement(svgElement);
- writeNameValuePair(ts, "cx", element->cxCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "cy", element->cyCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "rx", element->rxCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "ry", element->ryCurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::circleTag)) {
- SVGCircleElement* element = toSVGCircleElement(svgElement);
- writeNameValuePair(ts, "cx", element->cxCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "cy", element->cyCurrentValue().value(lengthContext));
- writeNameValuePair(ts, "r", element->rCurrentValue().value(lengthContext));
- } else if (svgElement->hasTagName(SVGNames::polygonTag) || svgElement->hasTagName(SVGNames::polylineTag)) {
- writeNameAndQuotedValue(ts, "points", toSVGPolyElement(svgElement)->pointsCurrentValue().valueAsString());
- } else if (svgElement->hasTagName(SVGNames::pathTag)) {
+ if (isSVGRectElement(*svgElement)) {
+ SVGRectElement& element = toSVGRectElement(*svgElement);
+ writeNameValuePair(ts, "x", element.x()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "y", element.y()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "width", element.width()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "height", element.height()->currentValue()->value(lengthContext));
+ } else if (isSVGLineElement(*svgElement)) {
+ SVGLineElement& element = toSVGLineElement(*svgElement);
+ writeNameValuePair(ts, "x1", element.x1()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "y1", element.y1()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "x2", element.x2()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "y2", element.y2()->currentValue()->value(lengthContext));
+ } else if (isSVGEllipseElement(*svgElement)) {
+ SVGEllipseElement& element = toSVGEllipseElement(*svgElement);
+ writeNameValuePair(ts, "cx", element.cx()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "cy", element.cy()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "rx", element.rx()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "ry", element.ry()->currentValue()->value(lengthContext));
+ } else if (isSVGCircleElement(*svgElement)) {
+ SVGCircleElement& element = toSVGCircleElement(*svgElement);
+ writeNameValuePair(ts, "cx", element.cx()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "cy", element.cy()->currentValue()->value(lengthContext));
+ writeNameValuePair(ts, "r", element.r()->currentValue()->value(lengthContext));
+ } else if (isSVGPolyElement(*svgElement)) {
+ writeNameAndQuotedValue(ts, "points", toSVGPolyElement(*svgElement).points()->currentValue()->valueAsString());
+ } else if (isSVGPathElement(*svgElement)) {
String pathString;
// FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests.
- buildStringFromByteStream(toSVGPathElement(svgElement)->pathByteStream(), pathString, NormalizedParsing);
+ buildStringFromByteStream(toSVGPathElement(*svgElement).pathByteStream(), pathString, NormalizedParsing);
writeNameAndQuotedValue(ts, "data", pathString);
} else
ASSERT_NOT_REACHED();
@@ -380,11 +402,10 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
if (fragments.isEmpty())
return;
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- const SVGRenderStyle* svgStyle = textRenderer->style()->svgStyle();
- String text = textBox->textRenderer()->text();
+ const SVGRenderStyle* svgStyle = textRenderer.style()->svgStyle();
+ String text = textBox->textRenderer().text();
unsigned fragmentsSize = fragments.size();
for (unsigned i = 0; i < fragmentsSize; ++i) {
@@ -452,7 +473,7 @@ static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int
static void writeChildren(TextStream& ts, const RenderObject& object, int indent)
{
- for (RenderObject* child = object.firstChild(); child; child = child->nextSibling())
+ for (RenderObject* child = object.slowFirstChild(); child; child = child->nextSibling())
write(ts, *child, indent + 1);
}
@@ -490,7 +511,8 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
ts << "\n";
// Creating a placeholder filter which is passed to the builder.
FloatRect dummyRect;
- RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true);
+ IntRect dummyIntRect;
+ RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyIntRect, dummyRect, dummyRect, true);
if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) {
if (FilterEffect* lastEffect = builder->lastEffect())
lastEffect->externalRepresentation(ts, indent + 1);
@@ -614,7 +636,7 @@ void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int
if (!style)
return;
- ts << " [offset=" << stopElement->offsetCurrentValue() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n";
+ ts << " [offset=" << stopElement->offset()->currentValue()->value() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n";
}
void writeResources(TextStream& ts, const RenderObject& object, int indent)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h
index 055c587df57..63f26442a6d 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderTreeAsText.h
@@ -31,10 +31,6 @@
namespace WebCore {
class Color;
-class FloatRect;
-class FloatSize;
-class Node;
-class RenderImage;
class RenderObject;
class RenderSVGGradientStop;
class RenderSVGImage;
@@ -43,7 +39,6 @@ class RenderSVGShape;
class RenderSVGRoot;
class RenderSVGText;
class AffineTransform;
-class SVGUnitTypes;
// functions used by the main RenderTreeAsText code
void write(TextStream&, const RenderSVGShape&, int indent);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp
index 55545097c0f..23766e3a505 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.cpp
@@ -26,9 +26,10 @@
#include "core/rendering/svg/SVGRenderingContext.h"
-#include "core/frame/Frame.h"
+#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
-#include "core/page/Page.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/Settings.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/svg/RenderSVGImage.h"
#include "core/rendering/svg/RenderSVGResource.h"
@@ -113,23 +114,28 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
// Setup transparency layers before setting up SVG resources!
bool isRenderingMask = isRenderingMaskImage(m_object);
- float opacity = isRenderingMask ? 1 : style->opacity();
- blink::WebBlendMode blendMode = isRenderingMask ? blink::WebBlendModeNormal : style->blendMode();
- if (opacity < 1 || blendMode != blink::WebBlendModeNormal) {
- FloatRect repaintRect = m_object->repaintRectInLocalCoordinates();
-
- if (opacity < 1 || blendMode != blink::WebBlendModeNormal) {
- m_paintInfo->context->clip(repaintRect);
- if (blendMode != blink::WebBlendModeNormal) {
- if (!(m_renderingFlags & RestoreGraphicsContext)) {
- m_paintInfo->context->save();
- m_renderingFlags |= RestoreGraphicsContext;
- }
- m_paintInfo->context->setCompositeOperation(CompositeSourceOver, blendMode);
+ // RenderLayer takes care of root opacity.
+ float opacity = (object->isSVGRoot() || isRenderingMask) ? 1 : style->opacity();
+ bool hasBlendMode = style->hasBlendMode() && !isRenderingMask;
+
+ if (opacity < 1 || hasBlendMode || style->hasIsolation()) {
+ FloatRect repaintRect = m_object->paintInvalidationRectInLocalCoordinates();
+ m_paintInfo->context->clip(repaintRect);
+
+ if (hasBlendMode) {
+ if (!(m_renderingFlags & RestoreGraphicsContext)) {
+ m_paintInfo->context->save();
+ m_renderingFlags |= RestoreGraphicsContext;
}
- m_paintInfo->context->beginTransparencyLayer(opacity);
- m_renderingFlags |= EndOpacityLayer;
+ m_paintInfo->context->setCompositeOperation(CompositeSourceOver, style->blendMode());
}
+
+ m_paintInfo->context->beginTransparencyLayer(opacity);
+
+ if (hasBlendMode)
+ m_paintInfo->context->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
+
+ m_renderingFlags |= EndOpacityLayer;
}
ClipPathOperation* clipPathOperation = style->clipPath();
@@ -197,20 +203,23 @@ float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObje
ASSERT(renderer);
AffineTransform ctm;
- calculateTransformationToOutermostCoordinateSystem(renderer, ctm);
+ // FIXME: calculateDeviceSpaceTransformation() queries layer compositing state - which is not
+ // supported during layout. Hence, the result may not include all CSS transforms.
+ calculateDeviceSpaceTransformation(renderer, ctm);
return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
}
-void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
+void SVGRenderingContext::calculateDeviceSpaceTransformation(const RenderObject* renderer, AffineTransform& absoluteTransform)
{
- ASSERT(renderer);
- absoluteTransform = currentContentTransformation();
+ // FIXME: trying to compute a device space transform at record time is wrong. All clients
+ // should be updated to avoid relying on this information, and the method should be removed.
- float deviceScaleFactor = 1;
- if (Page* page = renderer->document().page())
- deviceScaleFactor = page->deviceScaleFactor();
+ ASSERT(renderer);
+ // We're about to possibly clear renderer, so save the deviceScaleFactor now.
+ float deviceScaleFactor = renderer->document().frameHost()->deviceScaleFactor();
// Walk up the render tree, accumulating SVG transforms.
+ absoluteTransform = currentContentTransformation();
while (renderer) {
absoluteTransform = renderer->localToParentTransform() * absoluteTransform;
if (renderer->isSVGRoot())
@@ -220,23 +229,22 @@ void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(con
// Continue walking up the layer tree, accumulating CSS transforms.
RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
- while (layer) {
- if (TransformationMatrix* layerTransform = layer->transform())
- absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;
-
+ while (layer && layer->isAllowedToQueryCompositingState()) {
// We can stop at compositing layers, to match the backing resolution.
// FIXME: should we be computing the transform to the nearest composited layer,
// or the nearest composited layer that does not paint into its ancestor?
// I think this is the nearest composited ancestor since we will inherit its
// transforms in the composited layer tree.
- if (layer->hasCompositedLayerMapping())
+ if (layer->compositingState() != NotComposited)
break;
+ if (TransformationMatrix* layerTransform = layer->transform())
+ absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;
+
layer = layer->parent();
}
- if (deviceScaleFactor != 1)
- absoluteTransform.scale(deviceScaleFactor);
+ absoluteTransform.scale(deviceScaleFactor);
}
void SVGRenderingContext::renderSubtree(GraphicsContext* context, RenderObject* item, const AffineTransform& subtreeContentTransformation)
@@ -278,7 +286,7 @@ bool SVGRenderingContext::bufferForeground(OwnPtr<ImageBuffer>& imageBuffer)
// Invalidate an existing buffer if the scale is not correct.
if (imageBuffer) {
- AffineTransform transform = m_paintInfo->context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
+ AffineTransform transform = m_paintInfo->context->getCTM();
IntSize expandedBoundingBox = expandedIntSize(boundingBox.size());
IntSize bufferSize(static_cast<int>(ceil(expandedBoundingBox.width() * transform.xScale())), static_cast<int>(ceil(expandedBoundingBox.height() * transform.yScale())));
if (bufferSize != imageBuffer->size())
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h
index 742e0a09997..3fcda0ae099 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRenderingContext.h
@@ -79,7 +79,7 @@ public:
static void renderSubtree(GraphicsContext*, RenderObject*, const AffineTransform&);
static float calculateScreenFontSizeScalingFactor(const RenderObject*);
- static void calculateTransformationToOutermostCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
+ static void calculateDeviceSpaceTransformation(const RenderObject*, AffineTransform& absoluteTransform);
static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
static void clear2DRotation(AffineTransform&);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp
index 5c42dbcef69..dcb5113bff7 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/svg/SVGResources.h"
-#include "SVGNames.h"
+#include "core/SVGNames.h"
#include "core/rendering/style/SVGRenderStyle.h"
#include "core/rendering/svg/RenderSVGResourceClipper.h"
#include "core/rendering/svg/RenderSVGResourceFilter.h"
@@ -38,6 +38,8 @@
namespace WebCore {
+using namespace SVGNames;
+
SVGResources::SVGResources()
: m_linkedResource(0)
{
@@ -49,39 +51,45 @@ static HashSet<AtomicString>& clipperFilterMaskerTags()
if (s_tagList.isEmpty()) {
// "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement
// "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement
- s_tagList.add(SVGNames::aTag.localName());
- s_tagList.add(SVGNames::circleTag.localName());
- s_tagList.add(SVGNames::ellipseTag.localName());
- s_tagList.add(SVGNames::glyphTag.localName());
- s_tagList.add(SVGNames::gTag.localName());
- s_tagList.add(SVGNames::imageTag.localName());
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::markerTag.localName());
- s_tagList.add(SVGNames::maskTag.localName());
- s_tagList.add(SVGNames::missing_glyphTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
- s_tagList.add(SVGNames::rectTag.localName());
- s_tagList.add(SVGNames::svgTag.localName());
- s_tagList.add(SVGNames::textTag.localName());
- s_tagList.add(SVGNames::useTag.localName());
+ s_tagList.add(aTag.localName());
+ s_tagList.add(circleTag.localName());
+ s_tagList.add(ellipseTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(glyphTag.localName());
+#endif
+ s_tagList.add(gTag.localName());
+ s_tagList.add(imageTag.localName());
+ s_tagList.add(lineTag.localName());
+ s_tagList.add(markerTag.localName());
+ s_tagList.add(maskTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(missing_glyphTag.localName());
+#endif
+ s_tagList.add(pathTag.localName());
+ s_tagList.add(polygonTag.localName());
+ s_tagList.add(polylineTag.localName());
+ s_tagList.add(rectTag.localName());
+ s_tagList.add(svgTag.localName());
+ s_tagList.add(textTag.localName());
+ s_tagList.add(useTag.localName());
// Not listed in the definitions is the clipPath element, the SVG spec says though:
// The "clipPath" element or any of its children can specify property "clip-path".
// So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail.
// (Already mailed SVG WG, waiting for a solution)
- s_tagList.add(SVGNames::clipPathTag.localName());
+ s_tagList.add(clipPathTag.localName());
// Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed.
// (Already mailed SVG WG, waiting for a solution)
- s_tagList.add(SVGNames::altGlyphTag.localName());
- s_tagList.add(SVGNames::textPathTag.localName());
- s_tagList.add(SVGNames::tspanTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(altGlyphTag.localName());
+#endif
+ s_tagList.add(textPathTag.localName());
+ s_tagList.add(tspanTag.localName());
// Not listed in the definitions is the foreignObject element, but clip-path
// is a supported attribute.
- s_tagList.add(SVGNames::foreignObjectTag.localName());
+ s_tagList.add(foreignObjectTag.localName());
// Elements that we ignore, as it doesn't make any sense.
// defs, pattern, switch (FIXME: Mail SVG WG about these)
@@ -91,34 +99,36 @@ static HashSet<AtomicString>& clipperFilterMaskerTags()
return s_tagList;
}
-static HashSet<AtomicString>& markerTags()
+bool SVGResources::supportsMarkers(const SVGElement& element)
{
DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
+ s_tagList.add(lineTag.localName());
+ s_tagList.add(pathTag.localName());
+ s_tagList.add(polygonTag.localName());
+ s_tagList.add(polylineTag.localName());
}
- return s_tagList;
+ return s_tagList.contains(element.localName());
}
static HashSet<AtomicString>& fillAndStrokeTags()
{
DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::altGlyphTag.localName());
- s_tagList.add(SVGNames::circleTag.localName());
- s_tagList.add(SVGNames::ellipseTag.localName());
- s_tagList.add(SVGNames::lineTag.localName());
- s_tagList.add(SVGNames::pathTag.localName());
- s_tagList.add(SVGNames::polygonTag.localName());
- s_tagList.add(SVGNames::polylineTag.localName());
- s_tagList.add(SVGNames::rectTag.localName());
- s_tagList.add(SVGNames::textTag.localName());
- s_tagList.add(SVGNames::textPathTag.localName());
- s_tagList.add(SVGNames::tspanTag.localName());
+#if ENABLE(SVG_FONTS)
+ s_tagList.add(altGlyphTag.localName());
+#endif
+ s_tagList.add(circleTag.localName());
+ s_tagList.add(ellipseTag.localName());
+ s_tagList.add(lineTag.localName());
+ s_tagList.add(pathTag.localName());
+ s_tagList.add(polygonTag.localName());
+ s_tagList.add(polylineTag.localName());
+ s_tagList.add(rectTag.localName());
+ s_tagList.add(textTag.localName());
+ s_tagList.add(textPathTag.localName());
+ s_tagList.add(tspanTag.localName());
}
return s_tagList;
@@ -128,37 +138,52 @@ static HashSet<AtomicString>& chainableResourceTags()
{
DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
if (s_tagList.isEmpty()) {
- s_tagList.add(SVGNames::linearGradientTag.localName());
- s_tagList.add(SVGNames::filterTag.localName());
- s_tagList.add(SVGNames::patternTag.localName());
- s_tagList.add(SVGNames::radialGradientTag.localName());
+ s_tagList.add(linearGradientTag.localName());
+ s_tagList.add(filterTag.localName());
+ s_tagList.add(patternTag.localName());
+ s_tagList.add(radialGradientTag.localName());
}
return s_tagList;
}
-static inline String targetReferenceFromResource(SVGElement* element)
+static inline AtomicString targetReferenceFromResource(SVGElement& element)
{
String target;
- if (element->hasTagName(SVGNames::patternTag))
- target = toSVGPatternElement(element)->hrefCurrentValue();
- else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
- target = toSVGGradientElement(element)->hrefCurrentValue();
- else if (element->hasTagName(SVGNames::filterTag))
- target = toSVGFilterElement(element)->hrefCurrentValue();
+ if (isSVGPatternElement(element))
+ target = toSVGPatternElement(element).href()->currentValue()->value();
+ else if (isSVGGradientElement(element))
+ target = toSVGGradientElement(element).href()->currentValue()->value();
+ else if (isSVGFilterElement(element))
+ target = toSVGFilterElement(element).href()->currentValue()->value();
else
ASSERT_NOT_REACHED();
- return SVGURIReference::fragmentIdentifierFromIRIString(target, element->document());
+ return SVGURIReference::fragmentIdentifierFromIRIString(target, element.treeScope());
+}
+
+static inline bool svgPaintTypeHasURL(SVGPaint::SVGPaintType paintType)
+{
+ switch (paintType) {
+ case SVGPaint::SVG_PAINTTYPE_URI_NONE:
+ case SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR:
+ case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR:
+ case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR:
+ case SVGPaint::SVG_PAINTTYPE_URI:
+ return true;
+ default:
+ break;
+ }
+ return false;
}
-static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document& document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
+static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(TreeScope& treeScope, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
{
- if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)
+ if (!svgPaintTypeHasURL(paintType))
return 0;
- id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document);
- RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id);
+ id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, treeScope);
+ RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(treeScope, id);
if (!container) {
hasPendingResource = true;
return 0;
@@ -171,10 +196,10 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document&
return container;
}
-static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element)
+static inline void registerPendingResource(SVGDocumentExtensions& extensions, const AtomicString& id, SVGElement* element)
{
ASSERT(element);
- extensions->addPendingResource(id, element);
+ extensions.addPendingResource(id, element);
}
bool SVGResources::hasResourceData() const
@@ -206,10 +231,9 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
if (!element)
return nullptr;
- Document& document = object->document();
+ TreeScope& treeScope = element->treeScope();
- SVGDocumentExtensions* extensions = document.accessSVGExtensions();
- ASSERT(extensions);
+ SVGDocumentExtensions& extensions = object->document().accessSVGExtensions();
const AtomicString& tagName = element->localName();
if (tagName.isNull())
@@ -218,35 +242,35 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
OwnPtr<SVGResources> resources;
if (clipperFilterMaskerTags().contains(tagName)) {
if (style->hasClipper()) {
- AtomicString id(style->clipperResource());
- if (!ensureResources(resources)->setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
+ AtomicString id = style->clipperResource();
+ if (!ensureResources(resources)->setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(treeScope, id)))
registerPendingResource(extensions, id, element);
}
if (style->hasFilter()) {
- AtomicString id(style->filterResource());
- if (!ensureResources(resources)->setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
+ AtomicString id = style->filterResource();
+ if (!ensureResources(resources)->setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(treeScope, id)))
registerPendingResource(extensions, id, element);
}
if (style->hasMasker()) {
- AtomicString id(style->maskerResource());
- if (!ensureResources(resources)->setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id)))
+ AtomicString id = style->maskerResource();
+ if (!ensureResources(resources)->setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(treeScope, id)))
registerPendingResource(extensions, id, element);
}
}
- if (markerTags().contains(tagName) && style->hasMarkers()) {
- AtomicString markerStartId(style->markerStartResource());
- if (!ensureResources(resources)->setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId)))
+ if (style->hasMarkers() && supportsMarkers(*element)) {
+ const AtomicString& markerStartId = style->markerStartResource();
+ if (!ensureResources(resources)->setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(treeScope, markerStartId)))
registerPendingResource(extensions, markerStartId, element);
- AtomicString markerMidId(style->markerMidResource());
- if (!ensureResources(resources)->setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId)))
+ const AtomicString& markerMidId = style->markerMidResource();
+ if (!ensureResources(resources)->setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(treeScope, markerMidId)))
registerPendingResource(extensions, markerMidId, element);
- AtomicString markerEndId(style->markerEndResource());
- if (!ensureResources(resources)->setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId)))
+ const AtomicString& markerEndId = style->markerEndResource();
+ if (!ensureResources(resources)->setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(treeScope, style->markerEndResource())))
registerPendingResource(extensions, markerEndId, element);
}
@@ -254,7 +278,7 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
if (style->hasFill()) {
bool hasPendingResource = false;
AtomicString id;
- RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(document, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource);
+ RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(treeScope, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource);
if (!ensureResources(resources)->setFill(resource) && hasPendingResource) {
registerPendingResource(extensions, id, element);
}
@@ -263,7 +287,7 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
if (style->hasStroke()) {
bool hasPendingResource = false;
AtomicString id;
- RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(document, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource);
+ RenderSVGResourceContainer* resource = paintingResourceFromSVGPaint(treeScope, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource);
if (!ensureResources(resources)->setStroke(resource) && hasPendingResource) {
registerPendingResource(extensions, id, element);
}
@@ -271,8 +295,8 @@ PassOwnPtr<SVGResources> SVGResources::buildResources(const RenderObject* object
}
if (chainableResourceTags().contains(tagName)) {
- AtomicString id(targetReferenceFromResource(element));
- if (!ensureResources(resources)->setLinkedResource(getRenderSVGResourceContainerById(document, id)))
+ AtomicString id = targetReferenceFromResource(*element);
+ if (!ensureResources(resources)->setLinkedResource(getRenderSVGResourceContainerById(treeScope, id)))
registerPendingResource(extensions, id, element);
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h
index 8eb10adcb4e..41cdf2569d8 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResources.h
@@ -20,6 +20,7 @@
#ifndef SVGResources_h
#define SVGResources_h
+#include "wtf/FastAllocBase.h"
#include "wtf/HashSet.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
@@ -27,13 +28,13 @@
namespace WebCore {
-class Document;
class RenderObject;
class RenderSVGResourceClipper;
class RenderSVGResourceContainer;
class RenderSVGResourceFilter;
class RenderSVGResourceMarker;
class RenderSVGResourceMasker;
+class SVGElement;
class SVGRenderStyle;
// Holds a set of resources associated with a RenderObject
@@ -45,6 +46,8 @@ public:
static PassOwnPtr<SVGResources> buildResources(const RenderObject*, const SVGRenderStyle*);
void layoutIfNeeded();
+ static bool supportsMarkers(const SVGElement&);
+
// Ordinary resources
RenderSVGResourceClipper* clipper() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->clipper : 0; }
RenderSVGResourceMarker* markerStart() const { return m_markerData ? m_markerData->markerStart : 0; }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp
index 7a8ed18b4d8..b8ba7101ded 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "core/rendering/svg/SVGResourcesCache.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/rendering/svg/RenderSVGResourceContainer.h"
#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCycleSolver.h"
@@ -51,7 +51,7 @@ void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const
return;
// Put object in cache.
- SVGResources* resources = m_cache.set(object, newResources.release()).iterator->value.get();
+ SVGResources* resources = m_cache.set(object, newResources.release()).storedValue->value.get();
// Run cycle-detection _afterwards_, so self-references can be caught as well.
SVGResourcesCycleSolver solver(object, resources);
@@ -85,10 +85,8 @@ static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObje
{
Document& document = renderer->document();
- SVGDocumentExtensions* extensions = document.accessSVGExtensions();
- ASSERT(extensions);
-
- SVGResourcesCache* cache = extensions->resourcesCache();
+ SVGDocumentExtensions& extensions = document.accessSVGExtensions();
+ SVGResourcesCache* cache = extensions.resourcesCache();
ASSERT(cache);
return cache;
@@ -124,11 +122,11 @@ void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifferen
ASSERT(renderer->node());
ASSERT(renderer->node()->isSVGElement());
- if (diff == StyleDifferenceEqual || !renderer->parent())
+ if (diff.hasNoChange() || !renderer->parent())
return;
// In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint.
- if (renderer->isSVGResourceFilterPrimitive() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrColorChange))
+ if (renderer->isSVGResourceFilterPrimitive() && !diff.needsLayout())
return;
// Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a renderer.
@@ -194,9 +192,9 @@ void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
// Mark users of destroyed resources as pending resolution based on the id of the old resource.
Element* resourceElement = resource->element();
Element* clientElement = toElement(it->key->node());
- SVGDocumentExtensions* extensions = clientElement->document().accessSVGExtensions();
+ SVGDocumentExtensions& extensions = clientElement->document().accessSVGExtensions();
- extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
+ extensions.addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h
index ff5e9f903af..7bf878e7237 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCache.h
@@ -20,7 +20,8 @@
#ifndef SVGResourcesCache_h
#define SVGResourcesCache_h
-#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/style/StyleDifference.h"
+#include "wtf/FastAllocBase.h"
#include "wtf/HashMap.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
index efa1b933394..ae7e954fb04 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
@@ -47,117 +47,83 @@ SVGResourcesCycleSolver::~SVGResourcesCycleSolver()
{
}
-bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) const
-{
- ASSERT(renderer);
-
- // First operate on the resources of the given renderer.
- // <marker id="a"> <path marker-start="url(#b)"/> ...
- // <marker id="b" marker-start="url(#a)"/>
- if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) {
- HashSet<RenderSVGResourceContainer*> resourceSet;
- resources->buildSetOfResources(resourceSet);
-
- // Walk all resources and check wheter they reference any resource contained in the resources set.
- HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) {
- if (m_allResources.contains(*it))
- return true;
- }
- }
+struct ActiveFrame {
+ typedef SVGResourcesCycleSolver::ResourceSet ResourceSet;
- // Then operate on the child resources of the given renderer.
- // <marker id="a"> <path marker-start="url(#b)"/> ...
- // <marker id="b"> <path marker-start="url(#a)"/> ...
- for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
- SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child);
- if (!childResources)
- continue;
+ ActiveFrame(ResourceSet& activeSet, RenderSVGResourceContainer* resource)
+ : m_activeSet(activeSet)
+ , m_resource(resource)
+ {
+ m_activeSet.add(m_resource);
+ }
+ ~ActiveFrame()
+ {
+ m_activeSet.remove(m_resource);
+ }
- // A child of the given 'resource' contains resources.
- HashSet<RenderSVGResourceContainer*> childSet;
- childResources->buildSetOfResources(childSet);
+ ResourceSet& m_activeSet;
+ RenderSVGResourceContainer* m_resource;
+};
- // Walk all child resources and check wheter they reference any resource contained in the resources set.
- HashSet<RenderSVGResourceContainer*>::iterator end = childSet.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = childSet.begin(); it != end; ++it) {
- if (m_allResources.contains(*it))
- return true;
+bool SVGResourcesCycleSolver::resourceContainsCycles(RenderSVGResourceContainer* resource)
+{
+ // If we've traversed this sub-graph before and no cycles were observed, then
+ // reuse that result.
+ if (m_dagCache.contains(resource))
+ return false;
+
+ ActiveFrame frame(m_activeResources, resource);
+
+ RenderObject* node = resource;
+ while (node) {
+ // Skip subtrees which are themselves resources. (They will be
+ // processed - if needed - when they are actually referenced.)
+ if (node != resource && node->isSVGResourceContainer()) {
+ node = node->nextInPreOrderAfterChildren(resource);
+ continue;
}
-
- // Walk children recursively, stop immediately if we found a cycle
- if (resourceContainsCycles(child))
- return true;
+ if (SVGResources* nodeResources = SVGResourcesCache::cachedResourcesForRenderObject(node)) {
+ // Fetch all the resources referenced by |node|.
+ ResourceSet nodeSet;
+ nodeResources->buildSetOfResources(nodeSet);
+
+ // Iterate resources referenced by |node|.
+ ResourceSet::iterator end = nodeSet.end();
+ for (ResourceSet::iterator it = nodeSet.begin(); it != end; ++it) {
+ if (m_activeResources.contains(*it) || resourceContainsCycles(*it))
+ return true;
+ }
+ }
+ node = node->nextInPreOrder(resource);
}
+ // No cycles found in (or from) this resource. Add it to the "DAG cache".
+ m_dagCache.add(resource);
return false;
}
void SVGResourcesCycleSolver::resolveCycles()
{
- ASSERT(m_allResources.isEmpty());
-
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nBefore cycle detection:\n");
- m_resources->dump(m_renderer);
-#endif
-
- // Stash all resources into a HashSet for the ease of traversing.
- HashSet<RenderSVGResourceContainer*> localResources;
- m_resources->buildSetOfResources(localResources);
- ASSERT(!localResources.isEmpty());
-
- // Add all parent resource containers to the HashSet.
- HashSet<RenderSVGResourceContainer*> parentResources;
- RenderObject* parent = m_renderer->parent();
- while (parent) {
- if (parent->isSVGResourceContainer())
- parentResources.add(toRenderSVGResourceContainer(parent));
- parent = parent->parent();
- }
+ ASSERT(m_activeResources.isEmpty());
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n");
- {
- fprintf(stderr, "Local resources:\n");
- HashSet<RenderSVGResourceContainer*>::iterator end = localResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
-
- fprintf(stderr, "Parent resources:\n");
- end = parentResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
- }
-#endif
-
- // Build combined set of local and parent resources.
- m_allResources = localResources;
- HashSet<RenderSVGResourceContainer*>::iterator end = parentResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
- m_allResources.add(*it);
-
- // If we're a resource, add ourselves to the HashSet.
+ // If the starting RenderObject is a resource container itself, then add it
+ // to the active set (to break direct self-references.)
if (m_renderer->isSVGResourceContainer())
- m_allResources.add(toRenderSVGResourceContainer(m_renderer));
+ m_activeResources.add(toRenderSVGResourceContainer(m_renderer));
- ASSERT(!m_allResources.isEmpty());
+ ResourceSet localResources;
+ m_resources->buildSetOfResources(localResources);
- // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
- // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it.
- end = localResources.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) {
- RenderSVGResourceContainer* resource = *it;
- if (parentResources.contains(resource) || resourceContainsCycles(resource))
- breakCycle(resource);
+ // This performs a depth-first search for a back-edge in all the
+ // (potentially disjoint) graphs formed by the resources referenced by
+ // |m_renderer|.
+ ResourceSet::iterator end = localResources.end();
+ for (ResourceSet::iterator it = localResources.begin(); it != end; ++it) {
+ if (m_activeResources.contains(*it) || resourceContainsCycles(*it))
+ breakCycle(*it);
}
-#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nAfter cycle detection:\n");
- m_resources->dump(m_renderer);
-#endif
-
- m_allResources.clear();
+ m_activeResources.clear();
}
void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer* resourceLeadingToCycle)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h
index cadaa5a311e..aadd9f6fa54 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGResourcesCycleSolver.h
@@ -37,13 +37,17 @@ public:
void resolveCycles();
+ typedef HashSet<RenderSVGResourceContainer*> ResourceSet;
+
private:
- bool resourceContainsCycles(RenderObject*) const;
+ bool resourceContainsCycles(RenderSVGResourceContainer*);
void breakCycle(RenderSVGResourceContainer*);
RenderObject* m_renderer;
SVGResources* m_resources;
- HashSet<RenderSVGResourceContainer*> m_allResources;
+
+ ResourceSet m_activeResources;
+ ResourceSet m_dagCache;
};
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp
index ec9a953d1b3..4cd80101e37 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.cpp
@@ -24,7 +24,6 @@
#include "config.h"
#include "core/rendering/svg/SVGRootInlineBox.h"
-#include "SVGNames.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGText.h"
#include "core/rendering/svg/SVGInlineFlowBox.h"
@@ -33,15 +32,12 @@
namespace WebCore {
-void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
- RenderObject* boxRenderer = renderer();
- ASSERT(boxRenderer);
-
- bool isPrinting = renderer()->document().printing();
+ bool isPrinting = renderer().document().printing();
bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
PaintInfo childPaintInfo(paintInfo);
@@ -54,35 +50,29 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
}
}
- SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext);
+ SVGRenderingContext renderingContext(&renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
if (renderingContext.isRenderingPrepared()) {
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
- if (child->isSVGInlineTextBox())
- SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer()));
-
- child->paint(paintInfo, LayoutPoint(), 0, 0);
- }
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->paint(paintInfo, paintOffset, 0, 0);
}
}
-void SVGRootInlineBox::markDirty(bool dirty)
+void SVGRootInlineBox::markDirty()
{
- if (dirty)
- for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
- child->markDirty(true);
- RootInlineBox::markDirty(dirty);
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+ child->markDirty();
+ RootInlineBox::markDirty();
}
void SVGRootInlineBox::computePerCharacterLayoutInformation()
{
- RenderSVGText* textRoot = toRenderSVGText(block());
- ASSERT(textRoot);
+ RenderSVGText& textRoot = toRenderSVGText(block());
- Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes();
+ Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot.layoutAttributes();
if (layoutAttributes.isEmpty())
return;
- if (textRoot->needsReordering())
+ if (textRoot.needsReordering())
reorderValueLists(layoutAttributes);
// Perform SVG text layout phase two (see SVGTextLayoutEngine for details).
@@ -103,24 +93,23 @@ void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGText
{
for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
if (child->isSVGInlineTextBox()) {
- ASSERT(child->renderer());
- ASSERT(child->renderer()->isSVGInlineText());
+ ASSERT(child->renderer().isSVGInlineText());
characterLayout.layoutInlineTextBox(toSVGInlineTextBox(child));
} else {
// Skip generated content.
- Node* node = child->renderer()->node();
+ Node* node = child->renderer().node();
if (!node)
continue;
SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
- bool isTextPath = node->hasTagName(SVGNames::textPathTag);
+ bool isTextPath = isSVGTextPathElement(*node);
if (isTextPath) {
// Build text chunks for all <textPath> children, using the line layout algorithm.
// This is needeed as text-anchor is just an additional startOffset for text paths.
SVGTextLayoutEngine lineLayout(characterLayout.layoutAttributes());
layoutCharactersInTextBoxes(flowBox, lineLayout);
- characterLayout.beginTextPathLayout(child->renderer(), lineLayout);
+ characterLayout.beginTextPathLayout(&child->renderer(), lineLayout);
}
layoutCharactersInTextBoxes(flowBox, characterLayout);
@@ -136,8 +125,7 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
FloatRect boxRect;
if (child->isSVGInlineTextBox()) {
- ASSERT(child->renderer());
- ASSERT(child->renderer()->isSVGInlineText());
+ ASSERT(child->renderer().isSVGInlineText());
SVGInlineTextBox* textBox = toSVGInlineTextBox(child);
boxRect = textBox->calculateBoundaries();
@@ -147,7 +135,7 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
textBox->setLogicalHeight(boxRect.height());
} else {
// Skip generated content.
- if (!child->renderer()->node())
+ if (!child->renderer().node())
continue;
SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
@@ -166,18 +154,17 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe
void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect)
{
- RenderBlockFlow* parentBlock = block();
- ASSERT(parentBlock);
+ RenderBlockFlow& parentBlock = block();
// Finally, assign the root block position, now that all content is laid out.
LayoutRect boundingRect = enclosingLayoutRect(childRect);
- parentBlock->setLocation(boundingRect.location());
- parentBlock->setSize(boundingRect.size());
+ parentBlock.setLocation(boundingRect.location());
+ parentBlock.setSize(boundingRect.size());
// Position all children relative to the parent block.
for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
// Skip generated content.
- if (!child->renderer()->node())
+ if (!child->renderer().node())
continue;
child->adjustPosition(-childRect.x(), -childRect.y());
}
@@ -221,21 +208,11 @@ static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAtt
SVGCharacterDataMap::iterator itLast = lastAttributes->characterDataMap().find(lastPosition + 1);
bool firstPresent = itFirst != firstAttributes->characterDataMap().end();
bool lastPresent = itLast != lastAttributes->characterDataMap().end();
- if (!firstPresent && !lastPresent)
+ // We only want to perform the swap if both inline boxes are absolutely
+ // positioned.
+ if (!firstPresent || !lastPresent)
return;
-
- if (firstPresent && lastPresent) {
- std::swap(itFirst->value, itLast->value);
- return;
- }
-
- if (firstPresent && !lastPresent) {
- lastAttributes->characterDataMap().set(lastPosition + 1, itFirst->value);
- return;
- }
-
- // !firstPresent && lastPresent
- firstAttributes->characterDataMap().set(firstPosition + 1, itLast->value);
+ std::swap(itFirst->value, itLast->value);
}
static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext,
@@ -282,12 +259,12 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve
// Reordering is only necessary for BiDi text that is _absolutely_ positioned.
if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
- RenderSVGInlineText* firstContext = toRenderSVGInlineText(firstTextBox->textRenderer());
- RenderSVGInlineText* lastContext = toRenderSVGInlineText(lastTextBox->textRenderer());
+ RenderSVGInlineText& firstContext = toRenderSVGInlineText(firstTextBox->textRenderer());
+ RenderSVGInlineText& lastContext = toRenderSVGInlineText(lastTextBox->textRenderer());
SVGTextLayoutAttributes* firstAttributes = 0;
SVGTextLayoutAttributes* lastAttributes = 0;
- findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes);
+ findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes);
swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start());
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h
index efbe2f6b79b..862c9b24a4e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGRootInlineBox.h
@@ -29,24 +29,22 @@
namespace WebCore {
-class SVGInlineTextBox;
-
class SVGRootInlineBox FINAL : public RootInlineBox {
public:
- SVGRootInlineBox(RenderBlockFlow* block)
+ SVGRootInlineBox(RenderBlockFlow& block)
: RootInlineBox(block)
, m_logicalHeight(0)
{
}
- virtual bool isSVGRootInlineBox() const OVERRIDE FINAL { return true; }
+ virtual bool isSVGRootInlineBox() const OVERRIDE { return true; }
- virtual float virtualLogicalHeight() const OVERRIDE FINAL { return m_logicalHeight; }
+ virtual float virtualLogicalHeight() const OVERRIDE { return m_logicalHeight; }
void setLogicalHeight(float height) { m_logicalHeight = height; }
- virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE FINAL;
+ virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
- virtual void markDirty(bool dirty = true) OVERRIDE FINAL;
+ virtual void markDirty() OVERRIDE;
void computePerCharacterLayoutInformation();
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
index d26d868fff1..488fbd4bddd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
@@ -91,10 +91,9 @@ void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxe
SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
ASSERT(textBox);
- RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(textRenderer);
+ RenderSVGInlineText& textRenderer = toRenderSVGInlineText(textBox->textRenderer());
- const RenderStyle* style = textRenderer->style();
+ const RenderStyle* style = toRenderSVGInlineText(textBox->textRenderer()).style();
ASSERT(style);
const SVGRenderStyle* svgStyle = style->svgStyle();
@@ -125,11 +124,14 @@ void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxe
// Handle 'lengthAdjust' property.
float desiredTextLength = 0;
- if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textRenderer->parent())) {
+ if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textRenderer.parent())) {
SVGLengthContext lengthContext(textContentElement);
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+ if (textContentElement->textLengthIsSpecifiedByUser())
+ desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
+ else
+ desiredTextLength = 0;
- switch (textContentElement->lengthAdjustCurrentValue()) {
+ switch (textContentElement->lengthAdjust()->currentValue()->enumValue()) {
case SVGLengthAdjustUnknown:
break;
case SVGLengthAdjustSpacing:
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
index 7c65a7e55e6..cbf018dc87a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -23,6 +23,7 @@
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGTextMetricsBuilder.h"
#include "core/svg/SVGTextPositioningElement.h"
namespace WebCore {
@@ -53,7 +54,7 @@ void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render
buildCharacterDataMap(textRoot);
}
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
+ SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
}
bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText* textRoot)
@@ -72,14 +73,14 @@ bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSV
return false;
buildCharacterDataMap(textRoot);
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
+ SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
return true;
}
void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text)
{
ASSERT(text);
- m_metricsBuilder.measureTextRenderer(text);
+ SVGTextMetricsBuilder::measureTextRenderer(text);
}
static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, UChar& lastCharacter)
@@ -104,7 +105,7 @@ void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject
{
ASSERT(!start->isSVGText() || m_textPositions.isEmpty());
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = start->slowFirstChild(); child; child = child->nextSibling()) {
if (child->isSVGInlineText()) {
processRenderSVGInlineText(toRenderSVGInlineText(child), m_textLength, lastCharacter);
continue;
@@ -163,43 +164,43 @@ void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRo
static inline void updateCharacterData(unsigned i, float& lastRotation, SVGCharacterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xList, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList* dyList, const SVGNumberList* rotateList)
{
if (xList)
- data.x = xList->at(i).value(lengthContext);
+ data.x = xList->at(i)->value(lengthContext);
if (yList)
- data.y = yList->at(i).value(lengthContext);
+ data.y = yList->at(i)->value(lengthContext);
if (dxList)
- data.dx = dxList->at(i).value(lengthContext);
+ data.dx = dxList->at(i)->value(lengthContext);
if (dyList)
- data.dy = dyList->at(i).value(lengthContext);
+ data.dy = dyList->at(i)->value(lengthContext);
if (rotateList) {
- data.rotate = rotateList->at(i).value();
+ data.rotate = rotateList->at(i)->value();
lastRotation = data.rotate;
}
}
void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& position)
{
- const SVGLengthList& xList = position.element->xCurrentValue();
- const SVGLengthList& yList = position.element->yCurrentValue();
- const SVGLengthList& dxList = position.element->dxCurrentValue();
- const SVGLengthList& dyList = position.element->dyCurrentValue();
- const SVGNumberList& rotateList = position.element->rotateCurrentValue();
-
- unsigned xListSize = xList.size();
- unsigned yListSize = yList.size();
- unsigned dxListSize = dxList.size();
- unsigned dyListSize = dyList.size();
- unsigned rotateListSize = rotateList.size();
+ RefPtr<SVGLengthList> xList = position.element->x()->currentValue();
+ RefPtr<SVGLengthList> yList = position.element->y()->currentValue();
+ RefPtr<SVGLengthList> dxList = position.element->dx()->currentValue();
+ RefPtr<SVGLengthList> dyList = position.element->dy()->currentValue();
+ RefPtr<SVGNumberList> rotateList = position.element->rotate()->currentValue();
+
+ unsigned xListSize = xList->length();
+ unsigned yListSize = yList->length();
+ unsigned dxListSize = dxList->length();
+ unsigned dyListSize = dyList->length();
+ unsigned rotateListSize = rotateList->length();
if (!xListSize && !yListSize && !dxListSize && !dyListSize && !rotateListSize)
return;
float lastRotation = SVGTextLayoutAttributes::emptyValue();
SVGLengthContext lengthContext(position.element);
for (unsigned i = 0; i < position.length; ++i) {
- const SVGLengthList* xListPtr = i < xListSize ? &xList : 0;
- const SVGLengthList* yListPtr = i < yListSize ? &yList : 0;
- const SVGLengthList* dxListPtr = i < dxListSize ? &dxList : 0;
- const SVGLengthList* dyListPtr = i < dyListSize ? &dyList : 0;
- const SVGNumberList* rotateListPtr = i < rotateListSize ? &rotateList : 0;
+ const SVGLengthList* xListPtr = i < xListSize ? xList.get() : 0;
+ const SVGLengthList* yListPtr = i < yListSize ? yList.get() : 0;
+ const SVGLengthList* dxListPtr = i < dxListSize ? dxList.get() : 0;
+ const SVGLengthList* dyListPtr = i < dyListSize ? dyList.get() : 0;
+ const SVGNumberList* rotateListPtr = i < rotateListSize ? rotateList.get() : 0;
if (!xListPtr && !yListPtr && !dxListPtr && !dyListPtr && !rotateListPtr)
break;
@@ -218,7 +219,7 @@ void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& po
if (lastRotation == SVGTextLayoutAttributes::emptyValue())
return;
- for (unsigned i = rotateList.size(); i < position.length; ++i) {
+ for (unsigned i = rotateList->length(); i < position.length; ++i) {
SVGCharacterDataMap::iterator it = m_characterDataMap.find(position.start + i + 1);
if (it == m_characterDataMap.end()) {
SVGCharacterData data;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
index d92c125f47f..82d2d064660 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
@@ -20,7 +20,7 @@
#ifndef SVGTextLayoutAttributesBuilder_h
#define SVGTextLayoutAttributesBuilder_h
-#include "core/rendering/svg/SVGTextMetricsBuilder.h"
+#include "core/rendering/svg/SVGTextLayoutAttributes.h"
#include "wtf/Vector.h"
namespace WebCore {
@@ -73,7 +73,6 @@ private:
unsigned m_textLength;
Vector<TextPosition> m_textPositions;
SVGCharacterDataMap m_characterDataMap;
- SVGTextMetricsBuilder m_metricsBuilder;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
index 0ade353f4a7..fc5dc792329 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
@@ -47,6 +47,7 @@ SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layou
, m_dy(0)
, m_isVerticalText(false)
, m_inPathLayout(false)
+ , m_textPathCalculator(0)
, m_textPathLength(0)
, m_textPathCurrentOffset(0)
, m_textPathSpacing(0)
@@ -148,7 +149,7 @@ bool SVGTextLayoutEngine::parentDefinesTextLength(RenderObject* parent) const
while (currentParent) {
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(currentParent)) {
SVGLengthContext lengthContext(textContentElement);
- if (textContentElement->lengthAdjustCurrentValue() == SVGLengthAdjustSpacing && textContentElement->specifiedTextLength().value(lengthContext) > 0)
+ if (textContentElement->lengthAdjust()->currentValue()->enumValue() == SVGLengthAdjustSpacing && textContentElement->textLengthIsSpecifiedByUser())
return true;
}
@@ -169,11 +170,12 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
m_inPathLayout = true;
RenderSVGTextPath* textPath = toRenderSVGTextPath(object);
- m_textPath = textPath->layoutPath();
- if (m_textPath.isEmpty())
+ Path path = textPath->layoutPath();
+ if (path.isEmpty())
return;
+ m_textPathCalculator = new Path::PositionCalculator(path);
m_textPathStartOffset = textPath->startOffset();
- m_textPathLength = m_textPath.length();
+ m_textPathLength = path.length();
if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1)
m_textPathStartOffset *= m_textPathLength;
@@ -206,8 +208,11 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) {
SVGLengthContext lengthContext(textContentElement);
- lengthAdjust = textContentElement->lengthAdjustCurrentValue();
- desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+ lengthAdjust = textContentElement->lengthAdjust()->currentValue()->enumValue();
+ if (textContentElement->textLengthIsSpecifiedByUser())
+ desiredTextLength = textContentElement->textLength()->currentValue()->value(lengthContext);
+ else
+ desiredTextLength = 0;
}
if (!desiredTextLength)
@@ -222,7 +227,8 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
void SVGTextLayoutEngine::endTextPathLayout()
{
m_inPathLayout = false;
- m_textPath = Path();
+ delete m_textPathCalculator;
+ m_textPathCalculator = 0;
m_textPathLength = 0;
m_textPathStartOffset = 0;
m_textPathCurrentOffset = 0;
@@ -234,18 +240,17 @@ void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox)
{
ASSERT(textBox);
- RenderSVGInlineText* text = toRenderSVGInlineText(textBox->textRenderer());
- ASSERT(text);
- ASSERT(text->parent());
- ASSERT(text->parent()->node());
- ASSERT(text->parent()->node()->isSVGElement());
+ RenderSVGInlineText& text = toRenderSVGInlineText(textBox->textRenderer());
+ ASSERT(text.parent());
+ ASSERT(text.parent()->node());
+ ASSERT(text.parent()->node()->isSVGElement());
- const RenderStyle* style = text->style();
+ const RenderStyle* style = text.style();
ASSERT(style);
textBox->clearTextFragments();
m_isVerticalText = style->svgStyle()->isVerticalWritingMode();
- layoutTextOnLineOrPath(textBox, text, style);
+ layoutTextOnLineOrPath(textBox, &text, style);
if (m_inPathLayout) {
m_pathLayoutBoxes.append(textBox);
@@ -421,7 +426,7 @@ void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& vis
void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, RenderSVGInlineText* text, const RenderStyle* style)
{
- if (m_inPathLayout && m_textPath.isEmpty())
+ if (m_inPathLayout && !m_textPathCalculator)
return;
SVGElement* lengthContext = toSVGElement(text->parent()->node());
@@ -440,7 +445,7 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
const Font& font = style->font();
- SVGTextLayoutEngineSpacing spacingLayout(font);
+ SVGTextLayoutEngineSpacing spacingLayout(font, style->effectiveZoom());
SVGTextLayoutEngineBaseline baselineLayout(font);
bool didStartTextFragment = false;
@@ -505,8 +510,8 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
// Calculate SVG Fonts kerning, if needed.
float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, visualMetrics.glyph());
- // Calculate CSS 'kerning', 'letter-spacing' and 'word-spacing' for next character, if needed.
- float spacing = spacingLayout.calculateCSSKerningAndSpacing(svgStyle, lengthContext, currentCharacter);
+ // Calculate CSS 'letter-spacing' and 'word-spacing' for next character, if needed.
+ float spacing = spacingLayout.calculateCSSSpacing(currentCharacter);
float textPathOffset = 0;
if (m_inPathLayout) {
@@ -552,14 +557,11 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
if (textPathOffset > m_textPathLength)
break;
- bool ok = false;
- FloatPoint point = m_textPath.pointAtLength(textPathOffset, ok);
- ASSERT(ok);
-
+ FloatPoint point;
+ bool ok = m_textPathCalculator->pointAndNormalAtLength(textPathOffset, point, angle);
+ ASSERT_UNUSED(ok, ok);
x = point.x();
y = point.y();
- angle = m_textPath.normalAngleAtLength(textPathOffset, ok);
- ASSERT(ok);
// For vertical text on path, the actual angle has to be rotated 90 degrees anti-clockwise, not the orientation angle!
if (m_isVerticalText)
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h
index 3ae5fa09087..b3c91a445b2 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngine.h
@@ -32,9 +32,7 @@ namespace WebCore {
class RenderObject;
class RenderStyle;
class RenderSVGInlineText;
-class SVGElement;
class SVGInlineTextBox;
-class SVGRenderStyle;
// SVGTextLayoutEngine performs the second layout phase for SVG text.
//
@@ -96,7 +94,7 @@ private:
bool m_inPathLayout;
// Text on path layout
- Path m_textPath;
+ Path::PositionCalculator* m_textPathCalculator;
float m_textPathLength;
float m_textPathStartOffset;
float m_textPathCurrentOffset;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
index 3825b4b1220..95c3beb137c 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
@@ -38,12 +38,12 @@ SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font)
float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const
{
if (style->baselineShift() == BS_LENGTH) {
- SVGLength baselineShiftValueLength = style->baselineShiftValue();
- if (baselineShiftValueLength.unitType() == LengthTypePercentage)
- return baselineShiftValueLength.valueAsPercentage() * m_font.pixelSize();
+ RefPtr<SVGLength> baselineShiftValueLength = style->baselineShiftValue();
+ if (baselineShiftValueLength->unitType() == LengthTypePercentage)
+ return baselineShiftValueLength->valueAsPercentage() * m_font.fontDescription().computedPixelSize();
SVGLengthContext lengthContext(contextElement);
- return baselineShiftValueLength.value(lengthContext);
+ return baselineShiftValueLength->value(lengthContext);
}
switch (style->baselineShift()) {
@@ -160,7 +160,7 @@ float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVertica
case GO_AUTO: {
// Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
// Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
- unsigned int unicodeRange = findCharUnicodeRange(character);
+ unsigned unicodeRange = findCharUnicodeRange(character);
if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)
return 90;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
index 6f68e475f1e..e93bb48b41a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
@@ -21,8 +21,8 @@
#include "core/rendering/svg/SVGTextLayoutEngineSpacing.h"
-#include "core/rendering/style/SVGRenderStyle.h"
#include "core/svg/SVGLengthContext.h"
+#include "platform/fonts/Character.h"
#include "platform/fonts/Font.h"
#if ENABLE(SVG_FONTS)
@@ -33,18 +33,23 @@
namespace WebCore {
-SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font)
+SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font, float effectiveZoom)
: m_font(font)
, m_lastCharacter(0)
+ , m_effectiveZoom(effectiveZoom)
+#if ENABLE(SVG_FONTS)
+ , m_lastGlyph(0)
+#endif
{
+ ASSERT(m_effectiveZoom);
}
-float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph)
+float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, Glyph currentGlyph)
{
#if ENABLE(SVG_FONTS)
const SimpleFontData* fontData = m_font.primaryFont();
if (!fontData->isSVGFont()) {
- m_lastGlyph.isValid = false;
+ m_lastGlyph = 0;
return 0;
}
@@ -58,50 +63,44 @@ float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const
SVGFontElement* svgFont = svgFontFace->associatedFontElement();
if (!svgFont) {
- m_lastGlyph.isValid = false;
+ m_lastGlyph = 0;
return 0;
}
float kerning = 0;
- if (m_lastGlyph.isValid) {
+ if (m_lastGlyph) {
if (isVerticalText)
- kerning = svgFont->verticalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
+ kerning = svgFont->verticalKerningForPairOfGlyphs(m_lastGlyph, currentGlyph);
else
- kerning = svgFont->horizontalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
+ kerning = svgFont->horizontalKerningForPairOfGlyphs(m_lastGlyph, currentGlyph);
+
+ kerning *= m_font.fontDescription().computedSize() / m_font.fontMetrics().unitsPerEm();
}
m_lastGlyph = currentGlyph;
- m_lastGlyph.isValid = true;
- kerning *= m_font.size() / m_font.fontMetrics().unitsPerEm();
return kerning;
#else
- return false;
+ return 0;
#endif
}
-float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderStyle* style, SVGElement* contextElement, UChar currentCharacter)
+float SVGTextLayoutEngineSpacing::calculateCSSSpacing(UChar currentCharacter)
{
- float kerning = 0;
- SVGLength kerningLength = style->kerning();
- if (kerningLength.unitType() == LengthTypePercentage)
- kerning = kerningLength.valueAsPercentage() * m_font.pixelSize();
- else {
- SVGLengthContext lengthContext(contextElement);
- kerning = kerningLength.value(lengthContext);
- }
-
UChar lastCharacter = m_lastCharacter;
m_lastCharacter = currentCharacter;
- if (!kerning && !m_font.letterSpacing() && !m_font.wordSpacing())
+ if (!m_font.fontDescription().letterSpacing() && !m_font.fontDescription().wordSpacing())
return 0;
- float spacing = m_font.letterSpacing() + kerning;
- if (currentCharacter && lastCharacter && m_font.wordSpacing()) {
- if (Font::treatAsSpace(currentCharacter) && !Font::treatAsSpace(lastCharacter))
- spacing += m_font.wordSpacing();
+ float spacing = m_font.fontDescription().letterSpacing();
+ if (currentCharacter && lastCharacter && m_font.fontDescription().wordSpacing()) {
+ if (Character::treatAsSpace(currentCharacter) && !Character::treatAsSpace(lastCharacter))
+ spacing += m_font.fontDescription().wordSpacing();
}
+ if (m_effectiveZoom != 1)
+ spacing = spacing / m_effectiveZoom;
+
return spacing;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
index 5cc8bec5533..8618e246dd4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
@@ -25,24 +25,23 @@
namespace WebCore {
class Font;
-class SVGRenderStyle;
-class SVGElement;
-// Helper class used by SVGTextLayoutEngine to handle 'kerning' / 'letter-spacing' and 'word-spacing'.
+// Helper class used by SVGTextLayoutEngine to handle 'letter-spacing' and 'word-spacing'.
class SVGTextLayoutEngineSpacing {
WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineSpacing);
public:
- SVGTextLayoutEngineSpacing(const Font&);
+ SVGTextLayoutEngineSpacing(const Font&, float effectiveZoom);
- float calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph);
- float calculateCSSKerningAndSpacing(const SVGRenderStyle*, SVGElement* lengthContext, UChar currentCharacter);
+ float calculateSVGKerning(bool isVerticalText, Glyph currentGlyph);
+ float calculateCSSSpacing(UChar currentCharacter);
private:
const Font& m_font;
UChar m_lastCharacter;
+ float m_effectiveZoom;
#if ENABLE(SVG_FONTS)
- SVGTextMetrics::Glyph m_lastGlyph;
+ Glyph m_lastGlyph;
#endif
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp
index 26c82dbec27..3ab52797f77 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.cpp
@@ -30,6 +30,7 @@ SVGTextMetrics::SVGTextMetrics()
: m_width(0)
, m_height(0)
, m_length(0)
+ , m_glyph(0)
{
}
@@ -37,6 +38,7 @@ SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType)
: m_width(0)
, m_height(0)
, m_length(1)
+ , m_glyph(0)
{
}
@@ -51,18 +53,21 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun&
int length = 0;
// Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
- m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor;
+ m_width = scaledFont.width(run, length, m_glyph) / scalingFactor;
m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;
- m_glyph.unicodeString = run.is8Bit() ? String(run.characters8(), length) : String(run.characters16(), length);
- m_glyph.isValid = true;
-
ASSERT(length >= 0);
m_length = static_cast<unsigned>(length);
}
TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned position, unsigned length)
{
+ ASSERT(text->style());
+ return constructTextRun(text, position, length, text->style()->direction());
+}
+
+TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned position, unsigned length, TextDirection textDirection)
+{
RenderStyle* style = text->style();
ASSERT(style);
@@ -71,7 +76,7 @@ TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned pos
, 0 // xPos, only relevant with allowTabs=true
, 0 // padding, only relevant for justified text, not relevant for SVG
, TextRun::AllowTrailingExpansion
- , style->direction()
+ , textDirection
, isOverride(style->unicodeBidi()) /* directionalOverride */);
if (length) {
@@ -95,13 +100,19 @@ TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, unsigned pos
return run;
}
+SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length, TextDirection textDirection)
+{
+ ASSERT(text);
+ return SVGTextMetrics(text, constructTextRun(text, position, length, textDirection));
+}
+
SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length)
{
ASSERT(text);
return SVGTextMetrics(text, constructTextRun(text, position, length));
}
-SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, const String& glyphName)
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, Glyph glyphNameGlyphId)
{
ASSERT(text);
@@ -111,11 +122,7 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, uns
m_width = width / scalingFactor;
m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor;
- if (needsContext) {
- m_glyph.isValid = true;
- m_glyph.unicodeString = text->substring(position, length);
- m_glyph.name = glyphName;
- }
+ m_glyph = needsContext ? glyphNameGlyphId : 0;
m_length = length;
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h
index 362933997ed..3c04901e2cf 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetrics.h
@@ -20,12 +20,13 @@
#ifndef SVGTextMetrics_h
#define SVGTextMetrics_h
+#include "platform/fonts/Glyph.h"
+#include "platform/text/TextDirection.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
class RenderSVGInlineText;
-class SVGTextLayoutAttributes;
class TextRun;
class SVGTextMetrics {
@@ -36,12 +37,16 @@ public:
SVGTextMetrics();
SVGTextMetrics(MetricsType);
- SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, const String& glyphName);
+ SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, Glyph glyphNameGlyphId);
+ // FIXME: Migrate away from these to the two below.
static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length);
static TextRun constructTextRun(RenderSVGInlineText*, unsigned position, unsigned length);
- bool isEmpty() const { return !m_width && !m_height && !m_glyph.isValid && m_length == 1; }
+ static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length, TextDirection);
+ static TextRun constructTextRun(RenderSVGInlineText*, unsigned position, unsigned length, TextDirection);
+
+ bool isEmpty() const { return !m_width && !m_height && m_length <= 1; }
float width() const { return m_width; }
void setWidth(float width) { m_width = width; }
@@ -49,19 +54,8 @@ public:
float height() const { return m_height; }
unsigned length() const { return m_length; }
- struct Glyph {
- Glyph()
- : isValid(false)
- {
- }
-
- bool isValid;
- String name;
- String unicodeString;
- };
-
// Only useful when measuring individual characters, to lookup ligatures.
- const Glyph& glyph() const { return m_glyph; }
+ Glyph glyph() const { return m_glyph; }
private:
SVGTextMetrics(RenderSVGInlineText*, const TextRun&);
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
index 46a27979e9d..eaaa9361d19 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
@@ -21,186 +21,238 @@
#include "core/rendering/svg/SVGTextMetricsBuilder.h"
+#include "core/rendering/svg/RenderSVGInline.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGTextMetrics.h"
+#include "platform/fonts/GlyphBuffer.h"
+#include "platform/fonts/WidthIterator.h"
+#include "platform/text/BidiCharacterRun.h"
+#include "platform/text/BidiResolver.h"
+#include "platform/text/TextDirection.h"
+#include "platform/text/TextPath.h"
+#include "platform/text/TextRun.h"
+#include "platform/text/TextRunIterator.h"
+#include "wtf/Vector.h"
namespace WebCore {
-SVGTextMetricsBuilder::SVGTextMetricsBuilder()
- : m_text(0)
- , m_run(static_cast<const UChar*>(0), 0)
- , m_textPosition(0)
+class SVGTextMetricsCalculator {
+public:
+ SVGTextMetricsCalculator(RenderSVGInlineText*);
+ ~SVGTextMetricsCalculator();
+
+ SVGTextMetrics computeMetricsForCharacter(unsigned textPosition);
+ unsigned textLength() const { return static_cast<unsigned>(m_run.charactersLength()); }
+
+ bool characterStartsSurrogatePair(unsigned textPosition) const
+ {
+ return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength() && U16_IS_TRAIL(m_run[textPosition + 1]);
+ }
+ bool characterIsWhiteSpace(unsigned textPosition) const
+ {
+ return m_run[textPosition] == ' ';
+ }
+
+private:
+ void setupBidiRuns();
+ SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition);
+ SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition);
+
+ RenderSVGInlineText* m_text;
+ BidiCharacterRun* m_bidiRun;
+ TextRun m_run;
+ BidiResolver<TextRunIterator, BidiCharacterRun> m_bidiResolver;
+ bool m_isComplexText;
+ float m_totalWidth;
+ TextDirection m_textDirection;
+
+ // Simple text only.
+ OwnPtr<WidthIterator> m_simpleWidthIterator;
+};
+
+SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text)
+ : m_text(text)
+ , m_bidiRun(0)
+ , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength()))
, m_isComplexText(false)
, m_totalWidth(0)
{
+ const Font& scaledFont = text->scaledFont();
+ CodePath codePath = scaledFont.codePath(m_run);
+ m_isComplexText = codePath == ComplexPath;
+ m_run.setCharacterScanForCodePath(!m_isComplexText);
+
+ if (!m_isComplexText)
+ m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
+ else
+ setupBidiRuns();
}
-inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const
+SVGTextMetricsCalculator::~SVGTextMetricsCalculator()
{
- return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]);
+ if (m_bidiRun)
+ m_bidiResolver.runs().deleteRuns();
}
-bool SVGTextMetricsBuilder::advance()
+void SVGTextMetricsCalculator::setupBidiRuns()
{
- m_textPosition += m_currentMetrics.length();
- if (int(m_textPosition) >= m_run.charactersLength())
- return false;
-
- if (m_isComplexText)
- advanceComplexText();
- else
- advanceSimpleText();
+ RenderStyle* style = m_text->style();
+ m_textDirection = style->direction();
+ if (isOverride(style->unicodeBidi()))
+ return;
- return m_currentMetrics.length() > 0;
+ BidiStatus status(LTR, false);
+ status.last = status.lastStrong = WTF::Unicode::OtherNeutral;
+ m_bidiResolver.setStatus(status);
+ m_bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&m_run, 0));
+ const bool hardLineBreak = false;
+ const bool reorderRuns = false;
+ m_bidiResolver.createBidiRunsForLine(TextRunIterator(&m_run, m_run.length()), NoVisualOverride, hardLineBreak, reorderRuns);
+ BidiRunList<BidiCharacterRun>& bidiRuns = m_bidiResolver.runs();
+ m_bidiRun = bidiRuns.firstRun();
}
-void SVGTextMetricsBuilder::advanceSimpleText()
+SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsigned textPosition)
{
GlyphBuffer glyphBuffer;
- unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1, &glyphBuffer);
- if (!metricsLength) {
- m_currentMetrics = SVGTextMetrics();
- return;
- }
+ unsigned metricsLength = m_simpleWidthIterator->advance(textPosition + 1, &glyphBuffer);
+ if (!metricsLength)
+ return SVGTextMetrics();
float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth;
m_totalWidth = m_simpleWidthIterator->runWidthSoFar();
-#if ENABLE(SVG_FONTS)
- m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName());
-#else
- m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, emptyString());
-#endif
+ Glyph glyphId = glyphBuffer.glyphAt(0);
+ return SVGTextMetrics(m_text, textPosition, metricsLength, currentWidth, glyphId);
}
-void SVGTextMetricsBuilder::advanceComplexText()
+SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsigned textPosition)
{
- unsigned metricsLength = currentCharacterStartsSurrogatePair() ? 2 : 1;
- m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosition, metricsLength);
- m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, m_textPosition + metricsLength);
- ASSERT(m_currentMetrics.length() == metricsLength);
+ unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1;
+ SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textPosition, metricsLength, m_textDirection);
+ ASSERT(metrics.length() == metricsLength);
+ unsigned startPosition = m_bidiRun ? m_bidiRun->start() : 0;
+ ASSERT(startPosition <= textPosition);
+ SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, startPosition, textPosition - startPosition + metricsLength, m_textDirection);
// Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken
// when rendering the glyph "in context" (with it's surrounding characters) it changes due to shaping.
// So whenever currentWidth != currentMetrics.width(), we are processing a text run whose length is
// not equal to the sum of the individual lengths of the glyphs, when measuring them isolated.
- float currentWidth = m_complexStartToCurrentMetrics.width() - m_totalWidth;
- if (currentWidth != m_currentMetrics.width())
- m_currentMetrics.setWidth(currentWidth);
+ float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth;
+ if (currentWidth != metrics.width())
+ metrics.setWidth(currentWidth);
- m_totalWidth = m_complexStartToCurrentMetrics.width();
+ m_totalWidth = complexStartToCurrentMetrics.width();
+ return metrics;
}
-void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlineText* text)
+SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned textPosition)
{
- m_text = text;
- m_textPosition = 0;
- m_currentMetrics = SVGTextMetrics();
- m_complexStartToCurrentMetrics = SVGTextMetrics();
- m_totalWidth = 0;
-
- const Font& scaledFont = text->scaledFont();
- m_run = SVGTextMetrics::constructTextRun(text, 0, text->textLength());
- m_isComplexText = scaledFont.codePath(m_run) == Font::Complex;
+ if (m_bidiRun) {
+ if (textPosition >= static_cast<unsigned>(m_bidiRun->stop())) {
+ m_bidiRun = m_bidiRun->next();
+ // New BiDi run means new reference position for measurements, so reset |m_totalWidth|.
+ m_totalWidth = 0;
+ }
+ ASSERT(m_bidiRun);
+ ASSERT(static_cast<int>(textPosition) < m_bidiRun->stop());
+ m_textDirection = m_bidiRun->direction();
+ }
if (m_isComplexText)
- m_simpleWidthIterator.clear();
- else
- m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
+ return computeMetricsForCharacterComplex(textPosition);
+
+ return computeMetricsForCharacterSimple(textPosition);
}
struct MeasureTextData {
MeasureTextData(SVGCharacterDataMap* characterDataMap)
: allCharactersMap(characterDataMap)
- , hasLastCharacter(false)
- , lastCharacter(0)
- , processRenderer(false)
+ , lastCharacterWasWhiteSpace(true)
, valueListPosition(0)
- , skippedCharacters(0)
{
}
SVGCharacterDataMap* allCharactersMap;
- bool hasLastCharacter;
- UChar lastCharacter;
- bool processRenderer;
+ bool lastCharacterWasWhiteSpace;
unsigned valueListPosition;
- unsigned skippedCharacters;
};
-void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data)
+static void measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data, bool processRenderer)
{
ASSERT(text);
SVGTextLayoutAttributes* attributes = text->layoutAttributes();
Vector<SVGTextMetrics>* textMetricsValues = &attributes->textMetricsValues();
- if (data->processRenderer) {
+ if (processRenderer) {
if (data->allCharactersMap)
attributes->clear();
else
textMetricsValues->clear();
}
- initializeMeasurementWithTextRenderer(text);
+ SVGTextMetricsCalculator calculator(text);
bool preserveWhiteSpace = text->style()->whiteSpace() == PRE;
- int surrogatePairCharacters = 0;
-
- while (advance()) {
- UChar currentCharacter = m_run[m_textPosition];
- if (currentCharacter == ' ' && !preserveWhiteSpace && (!data->hasLastCharacter || data->lastCharacter == ' ')) {
- if (data->processRenderer)
+ unsigned surrogatePairCharacters = 0;
+ unsigned skippedCharacters = 0;
+ unsigned textPosition = 0;
+ unsigned textLength = calculator.textLength();
+
+ SVGTextMetrics currentMetrics;
+ for (; textPosition < textLength; textPosition += currentMetrics.length()) {
+ currentMetrics = calculator.computeMetricsForCharacter(textPosition);
+ if (!currentMetrics.length())
+ break;
+
+ bool characterIsWhiteSpace = calculator.characterIsWhiteSpace(textPosition);
+ if (characterIsWhiteSpace && !preserveWhiteSpace && data->lastCharacterWasWhiteSpace) {
+ if (processRenderer)
textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));
if (data->allCharactersMap)
- data->skippedCharacters += m_currentMetrics.length();
+ skippedCharacters += currentMetrics.length();
continue;
}
- if (data->processRenderer) {
+ if (processRenderer) {
if (data->allCharactersMap) {
- const SVGCharacterDataMap::const_iterator it = data->allCharactersMap->find(data->valueListPosition + m_textPosition - data->skippedCharacters - surrogatePairCharacters + 1);
+ const SVGCharacterDataMap::const_iterator it = data->allCharactersMap->find(data->valueListPosition + textPosition - skippedCharacters - surrogatePairCharacters + 1);
if (it != data->allCharactersMap->end())
- attributes->characterDataMap().set(m_textPosition + 1, it->value);
+ attributes->characterDataMap().set(textPosition + 1, it->value);
}
- textMetricsValues->append(m_currentMetrics);
+ textMetricsValues->append(currentMetrics);
}
- if (data->allCharactersMap && currentCharacterStartsSurrogatePair())
+ if (data->allCharactersMap && calculator.characterStartsSurrogatePair(textPosition))
surrogatePairCharacters++;
- data->hasLastCharacter = true;
- data->lastCharacter = currentCharacter;
+ data->lastCharacterWasWhiteSpace = characterIsWhiteSpace;
}
if (!data->allCharactersMap)
return;
- data->valueListPosition += m_textPosition - data->skippedCharacters;
- data->skippedCharacters = 0;
+ data->valueListPosition += textPosition - skippedCharacters;
}
-void SVGTextMetricsBuilder::walkTree(RenderObject* start, RenderSVGInlineText* stopAtLeaf, MeasureTextData* data)
+static void walkTree(RenderSVGText* start, RenderSVGInlineText* stopAtLeaf, MeasureTextData* data)
{
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ RenderObject* child = start->firstChild();
+ while (child) {
if (child->isSVGInlineText()) {
RenderSVGInlineText* text = toRenderSVGInlineText(child);
- if (stopAtLeaf && stopAtLeaf != text) {
- data->processRenderer = false;
- measureTextRenderer(text, data);
+ measureTextRenderer(text, data, !stopAtLeaf || stopAtLeaf == text);
+ if (stopAtLeaf && stopAtLeaf == text)
+ return;
+ } else if (child->isSVGInline()) {
+ // Visit children of text content elements.
+ if (RenderObject* inlineChild = toRenderSVGInline(child)->firstChild()) {
+ child = inlineChild;
continue;
}
-
- data->processRenderer = true;
- measureTextRenderer(text, data);
- if (stopAtLeaf)
- return;
-
- continue;
}
-
- if (!child->isSVGInline())
- continue;
-
- walkTree(child, stopAtLeaf, data);
+ child = child->nextInPreOrderAfterChildren(start);
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h
index 076b052283a..bf0c5c77095 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextMetricsBuilder.h
@@ -21,48 +21,18 @@
#define SVGTextMetricsBuilder_h
#include "core/rendering/svg/SVGTextLayoutAttributes.h"
-#include "core/rendering/svg/SVGTextMetrics.h"
-#include "platform/fonts/WidthIterator.h"
-#include "platform/text/TextRun.h"
-#include "wtf/Vector.h"
namespace WebCore {
-class RenderObject;
class RenderSVGInlineText;
class RenderSVGText;
-struct MeasureTextData;
-class SVGTextMetricsBuilder {
- WTF_MAKE_NONCOPYABLE(SVGTextMetricsBuilder);
-public:
- SVGTextMetricsBuilder();
- void measureTextRenderer(RenderSVGInlineText*);
- void buildMetricsAndLayoutAttributes(RenderSVGText*, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
+namespace SVGTextMetricsBuilder {
-private:
- bool advance();
- void advanceSimpleText();
- void advanceComplexText();
- bool currentCharacterStartsSurrogatePair() const;
+void measureTextRenderer(RenderSVGInlineText*);
+void buildMetricsAndLayoutAttributes(RenderSVGText*, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
- void initializeMeasurementWithTextRenderer(RenderSVGInlineText*);
- void walkTree(RenderObject*, RenderSVGInlineText* stopAtLeaf, MeasureTextData*);
- void measureTextRenderer(RenderSVGInlineText*, MeasureTextData*);
-
- RenderSVGInlineText* m_text;
- TextRun m_run;
- unsigned m_textPosition;
- bool m_isComplexText;
- SVGTextMetrics m_currentMetrics;
- float m_totalWidth;
-
- // Simple text only.
- OwnPtr<WidthIterator> m_simpleWidthIterator;
-
- // Complex text only.
- SVGTextMetrics m_complexStartToCurrentMetrics;
-};
+} // namespace SVGTextMetricsBuilder
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp
index 4bf2a3c3da7..f5ead0d4366 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.cpp
@@ -90,7 +90,7 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox)
for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnLine()) {
if (child->isInlineFlowBox()) {
// Skip generated content.
- if (!child->renderer()->node())
+ if (!child->renderer().node())
continue;
collectTextBoxesInFlowBox(toInlineFlowBox(child));
@@ -112,8 +112,7 @@ bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra
// Loop over all text boxes
for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBoxPosition) {
queryData->textBox = m_textBoxes.at(textBoxPosition);
- queryData->textRenderer = toRenderSVGInlineText(queryData->textBox->textRenderer());
- ASSERT(queryData->textRenderer);
+ queryData->textRenderer = &toRenderSVGInlineText(queryData->textBox->textRenderer());
ASSERT(queryData->textRenderer->style());
ASSERT(queryData->textRenderer->style()->svgStyle());
@@ -142,7 +141,9 @@ bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData,
startPosition -= queryData->processedCharacters;
endPosition -= queryData->processedCharacters;
- if (startPosition >= endPosition || startPosition < 0 || endPosition < 0)
+ startPosition = max(0, startPosition);
+
+ if (startPosition >= endPosition)
return false;
modifyStartEndPositionsRespectingLigatures(queryData, startPosition, endPosition);
@@ -215,15 +216,11 @@ void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i
return;
if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) {
- if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) {
+ if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset))
startPosition = lastPositionOffset;
- alterStartPosition = false;
- }
- if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) {
+ if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset))
endPosition = positionOffset;
- alterEndPosition = false;
- }
}
}
@@ -480,8 +477,6 @@ static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const
AffineTransform fragmentTransform;
fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
- if (fragmentTransform.isIdentity())
- return;
extent = fragmentTransform.mapRect(extent);
}
@@ -499,10 +494,10 @@ bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragm
return true;
}
-SVGRect SVGTextQuery::extentOfCharacter(unsigned position) const
+FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const
{
if (m_textBoxes.isEmpty())
- return SVGRect();
+ return FloatRect();
ExtentOfCharacterData data(position);
executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback);
@@ -540,7 +535,7 @@ bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT
return false;
}
-int SVGTextQuery::characterNumberAtPosition(const SVGPoint& position) const
+int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
{
if (m_textBoxes.isEmpty())
return -1;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h
index 652d751af70..a5601f74d30 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextQuery.h
@@ -21,8 +21,8 @@
#define SVGTextQuery_h
#include "core/rendering/svg/SVGTextFragment.h"
-#include "core/svg/SVGPoint.h"
-#include "core/svg/SVGRect.h"
+#include "platform/geometry/FloatPoint.h"
+#include "platform/geometry/FloatRect.h"
#include "wtf/Vector.h"
namespace WebCore {
@@ -41,8 +41,8 @@ public:
FloatPoint startPositionOfCharacter(unsigned position) const;
FloatPoint endPositionOfCharacter(unsigned position) const;
float rotationOfCharacter(unsigned position) const;
- SVGRect extentOfCharacter(unsigned position) const;
- int characterNumberAtPosition(const SVGPoint&) const;
+ FloatRect extentOfCharacter(unsigned position) const;
+ int characterNumberAtPosition(const FloatPoint&) const;
// Public helper struct. Private classes in SVGTextQuery inherit from it.
struct Data;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
index c48c91e2486..7765117cd28 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
@@ -23,7 +23,6 @@
#if ENABLE(SVG_FONTS)
#include "core/rendering/svg/SVGTextRunRenderingContext.h"
-#include "SVGNames.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/svg/RenderSVGInlineText.h"
#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
@@ -46,6 +45,10 @@ static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const Simp
RefPtr<CustomFontData> customFontData = fontData->customFontData();
const SVGFontData* svgFontData = static_cast<const SVGFontData*>(customFontData.get());
+ // FIXME crbug.com/359380 : The current editing impl references the font after the svg font nodes are removed.
+ if (svgFontData->shouldSkipDrawing())
+ return 0;
+
fontFace = svgFontData->svgFontFaceElement();
ASSERT(fontFace);
@@ -73,12 +76,12 @@ static inline RenderSVGResource* activePaintingResourceFromRun(const TextRun& ru
return 0;
}
-float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, String& glyphName) const
+float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, Glyph& glyphId) const
{
WidthIterator it(&font, run);
GlyphBuffer glyphBuffer;
charsConsumed += it.advance(run.length(), &glyphBuffer);
- glyphName = it.lastGlyphName();
+ glyphId = !glyphBuffer.isEmpty() ? glyphBuffer.glyphAt(0) : 0;
return it.runWidthSoFar();
}
@@ -119,14 +122,17 @@ void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const T
glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
+ unsigned short resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
+ // From a resource perspective this ought to be treated as "text mode".
+ resourceMode |= ApplyToTextMode;
+
FloatPoint currentPoint = point;
- RenderSVGResourceMode resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
for (int i = 0; i < numGlyphs; ++i) {
Glyph glyph = glyphBuffer.glyphAt(from + i);
if (!glyph)
continue;
- float advance = glyphBuffer.advanceAt(from + i);
+ float advance = glyphBuffer.advanceAt(from + i).width();
SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
ASSERT(!svgGlyph.isPartOfLigature);
ASSERT(svgGlyph.tableEntry == glyph);
@@ -198,7 +204,7 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co
RenderObject* parentRenderObject = renderObject->isText() ? renderObject->parent() : renderObject;
ASSERT(parentRenderObject);
if (Element* parentRenderObjectElement = toElement(parentRenderObject->node())) {
- if (parentRenderObjectElement->hasTagName(SVGNames::altGlyphTag))
+ if (isSVGAltGlyphElement(*parentRenderObjectElement))
glyphData.fontData = primaryFont;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h
index e71eca2ca29..382c51feb50 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/svg/SVGTextRunRenderingContext.h
@@ -29,7 +29,7 @@ namespace WebCore {
class RenderObject;
class RenderSVGResource;
-class SVGTextRunRenderingContext : public TextRun::RenderingContext {
+class SVGTextRunRenderingContext FINAL : public TextRun::RenderingContext {
public:
static PassRefPtr<SVGTextRunRenderingContext> create(RenderObject* renderer)
{
@@ -42,9 +42,13 @@ public:
RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; }
void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; }
- virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength);
- virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
- virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, String& glyphName) const;
+ virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) OVERRIDE;
+ virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const OVERRIDE;
+ virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, Glyph& glyphId) const OVERRIDE;
+#else
+ virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) OVERRIDE { return 0; }
+ virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const OVERRIDE { }
+ virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, Glyph& glyphId) const OVERRIDE { return 0; }
#endif
private: