summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering')
-rw-r--r--Source/WebCore/rendering/ColumnInfo.h2
-rw-r--r--Source/WebCore/rendering/EllipsisBox.cpp2
-rw-r--r--Source/WebCore/rendering/EllipsisBox.h2
-rw-r--r--Source/WebCore/rendering/FilterEffectRenderer.cpp40
-rw-r--r--Source/WebCore/rendering/FilterEffectRenderer.h4
-rw-r--r--Source/WebCore/rendering/FlowThreadController.cpp38
-rw-r--r--Source/WebCore/rendering/FlowThreadController.h3
-rw-r--r--Source/WebCore/rendering/HitTestRequest.h11
-rw-r--r--Source/WebCore/rendering/HitTestResult.cpp66
-rw-r--r--Source/WebCore/rendering/HitTestResult.h41
-rw-r--r--Source/WebCore/rendering/HitTestingTransformState.cpp1
-rw-r--r--Source/WebCore/rendering/InlineBox.cpp4
-rw-r--r--Source/WebCore/rendering/InlineBox.h2
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.cpp15
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.h2
-rw-r--r--Source/WebCore/rendering/InlineTextBox.cpp8
-rw-r--r--Source/WebCore/rendering/InlineTextBox.h2
-rw-r--r--Source/WebCore/rendering/LayoutRepainter.h2
-rw-r--r--Source/WebCore/rendering/LayoutState.cpp21
-rw-r--r--Source/WebCore/rendering/LayoutState.h1
-rw-r--r--Source/WebCore/rendering/LayoutTypes.h126
-rw-r--r--Source/WebCore/rendering/LayoutTypesInlineMethods.h153
-rw-r--r--Source/WebCore/rendering/PaintInfo.h2
-rwxr-xr-xSource/WebCore/rendering/RenderBlock.cpp184
-rw-r--r--Source/WebCore/rendering/RenderBlock.h45
-rwxr-xr-xSource/WebCore/rendering/RenderBlockLineLayout.cpp118
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp494
-rw-r--r--Source/WebCore/rendering/RenderBox.h66
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.cpp91
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h11
-rw-r--r--Source/WebCore/rendering/RenderCounter.cpp64
-rw-r--r--Source/WebCore/rendering/RenderCounter.h1
-rw-r--r--Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp4
-rw-r--r--Source/WebCore/rendering/RenderDialog.cpp69
-rw-r--r--Source/WebCore/rendering/RenderDialog.h55
-rw-r--r--Source/WebCore/rendering/RenderEmbeddedObject.cpp6
-rw-r--r--Source/WebCore/rendering/RenderEmbeddedObject.h2
-rw-r--r--Source/WebCore/rendering/RenderFlowThread.cpp165
-rw-r--r--Source/WebCore/rendering/RenderFlowThread.h21
-rw-r--r--Source/WebCore/rendering/RenderFlowThreadContainer.cpp47
-rw-r--r--Source/WebCore/rendering/RenderFlowThreadContainer.h52
-rw-r--r--Source/WebCore/rendering/RenderFrameBase.cpp31
-rw-r--r--Source/WebCore/rendering/RenderFrameBase.h1
-rw-r--r--Source/WebCore/rendering/RenderFrameSet.cpp4
-rw-r--r--Source/WebCore/rendering/RenderFrameSet.h2
-rw-r--r--Source/WebCore/rendering/RenderGeometryMap.h6
-rw-r--r--Source/WebCore/rendering/RenderImage.cpp8
-rw-r--r--Source/WebCore/rendering/RenderImage.h2
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp10
-rw-r--r--Source/WebCore/rendering/RenderInline.h8
-rw-r--r--Source/WebCore/rendering/RenderInputSpeech.h10
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp264
-rw-r--r--Source/WebCore/rendering/RenderLayer.h48
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp208
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.h11
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp38
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.h4
-rw-r--r--Source/WebCore/rendering/RenderLayerFilterInfo.h1
-rw-r--r--Source/WebCore/rendering/RenderLineBoxList.cpp12
-rw-r--r--Source/WebCore/rendering/RenderLineBoxList.h4
-rw-r--r--Source/WebCore/rendering/RenderListBox.cpp12
-rw-r--r--Source/WebCore/rendering/RenderListBox.h6
-rw-r--r--Source/WebCore/rendering/RenderMediaControls.h8
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.cpp19
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.h6
-rw-r--r--Source/WebCore/rendering/RenderMenuList.cpp2
-rw-r--r--Source/WebCore/rendering/RenderMeter.h4
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnBlock.cpp16
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnFlowThread.h2
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnSet.cpp225
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnSet.h42
-rw-r--r--Source/WebCore/rendering/RenderNamedFlowThread.cpp112
-rw-r--r--Source/WebCore/rendering/RenderNamedFlowThread.h5
-rwxr-xr-xSource/WebCore/rendering/RenderObject.cpp45
-rw-r--r--Source/WebCore/rendering/RenderObject.h37
-rw-r--r--Source/WebCore/rendering/RenderObjectChildList.cpp86
-rw-r--r--Source/WebCore/rendering/RenderQuote.cpp6
-rw-r--r--Source/WebCore/rendering/RenderQuote.h5
-rw-r--r--Source/WebCore/rendering/RenderRegion.cpp95
-rw-r--r--Source/WebCore/rendering/RenderRegion.h40
-rw-r--r--Source/WebCore/rendering/RenderRegionSet.cpp21
-rw-r--r--Source/WebCore/rendering/RenderRegionSet.h4
-rw-r--r--Source/WebCore/rendering/RenderScrollbar.h2
-rw-r--r--Source/WebCore/rendering/RenderScrollbarPart.cpp8
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp58
-rw-r--r--Source/WebCore/rendering/RenderTable.h5
-rw-r--r--Source/WebCore/rendering/RenderTableCaption.cpp7
-rw-r--r--Source/WebCore/rendering/RenderTableCaption.h1
-rw-r--r--Source/WebCore/rendering/RenderTableCell.cpp12
-rw-r--r--Source/WebCore/rendering/RenderTableCell.h4
-rw-r--r--Source/WebCore/rendering/RenderTableRow.cpp19
-rw-r--r--Source/WebCore/rendering/RenderTableRow.h6
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp26
-rw-r--r--Source/WebCore/rendering/RenderTableSection.h4
-rw-r--r--Source/WebCore/rendering/RenderText.cpp2
-rw-r--r--Source/WebCore/rendering/RenderText.h9
-rw-r--r--Source/WebCore/rendering/RenderTextControl.cpp30
-rw-r--r--Source/WebCore/rendering/RenderTextControl.h2
-rw-r--r--Source/WebCore/rendering/RenderTextControlMultiLine.cpp6
-rw-r--r--Source/WebCore/rendering/RenderTextControlMultiLine.h2
-rw-r--r--Source/WebCore/rendering/RenderTextControlSingleLine.cpp8
-rw-r--r--Source/WebCore/rendering/RenderTextControlSingleLine.h2
-rw-r--r--Source/WebCore/rendering/RenderTheme.cpp23
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.h1
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.mm5
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.cpp21
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.h4
-rw-r--r--Source/WebCore/rendering/RenderThemeWin.cpp1
-rw-r--r--Source/WebCore/rendering/RenderTreeAsText.cpp64
-rw-r--r--Source/WebCore/rendering/RenderView.cpp25
-rw-r--r--Source/WebCore/rendering/RenderView.h22
-rw-r--r--Source/WebCore/rendering/RenderWidget.cpp4
-rw-r--r--Source/WebCore/rendering/RenderWidget.h2
-rw-r--r--Source/WebCore/rendering/RenderingAllInOne.cpp1
-rw-r--r--Source/WebCore/rendering/RootInlineBox.cpp8
-rw-r--r--Source/WebCore/rendering/RootInlineBox.h2
-rw-r--r--Source/WebCore/rendering/TextAutosizer.h2
-rw-r--r--Source/WebCore/rendering/WrapShapeInfo.cpp144
-rw-r--r--Source/WebCore/rendering/WrapShapeInfo.h107
-rw-r--r--Source/WebCore/rendering/break_lines.cpp27
-rw-r--r--Source/WebCore/rendering/break_lines.h13
-rw-r--r--Source/WebCore/rendering/style/BasicShapes.cpp93
-rw-r--r--Source/WebCore/rendering/style/BasicShapes.h (renamed from Source/WebCore/rendering/style/WrapShapes.h)88
-rw-r--r--Source/WebCore/rendering/style/CounterDirectives.cpp11
-rw-r--r--Source/WebCore/rendering/style/CounterDirectives.h69
-rw-r--r--Source/WebCore/rendering/style/DataRef.h8
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.cpp53
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.h45
-rw-r--r--Source/WebCore/rendering/style/RenderStyleConstants.h6
-rw-r--r--Source/WebCore/rendering/style/ShadowData.cpp2
-rw-r--r--Source/WebCore/rendering/style/ShadowData.h1
-rw-r--r--Source/WebCore/rendering/style/StyleDashboardRegion.h2
-rw-r--r--Source/WebCore/rendering/style/StyleRareInheritedData.cpp10
-rw-r--r--Source/WebCore/rendering/style/StyleRareInheritedData.h2
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp8
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.h10
-rw-r--r--Source/WebCore/rendering/style/WrapShapes.cpp55
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.h6
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.cpp2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMarker.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.cpp10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.cpp6
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.cpp8
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderingContext.cpp21
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderingContext.h1
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetrics.cpp2
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp4
152 files changed, 3132 insertions, 1613 deletions
diff --git a/Source/WebCore/rendering/ColumnInfo.h b/Source/WebCore/rendering/ColumnInfo.h
index 553564c53..dc2584d8e 100644
--- a/Source/WebCore/rendering/ColumnInfo.h
+++ b/Source/WebCore/rendering/ColumnInfo.h
@@ -26,7 +26,7 @@
#ifndef ColumnInfo_h
#define ColumnInfo_h
-#include "LayoutTypes.h"
+#include "LayoutTypesInlineMethods.h"
#include <wtf/Vector.h>
namespace WebCore {
diff --git a/Source/WebCore/rendering/EllipsisBox.cpp b/Source/WebCore/rendering/EllipsisBox.cpp
index c25673d93..902df2b0a 100644
--- a/Source/WebCore/rendering/EllipsisBox.cpp
+++ b/Source/WebCore/rendering/EllipsisBox.cpp
@@ -121,7 +121,7 @@ void EllipsisBox::paintSelection(GraphicsContext* context, const LayoutPoint& pa
context->drawHighlightForText(font, RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), roundedIntPoint(LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + top)), h, c, style->colorSpace());
}
-bool EllipsisBox::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint&, const LayoutPoint&, LayoutUnit, LayoutUnit)
+bool EllipsisBox::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, LayoutUnit, LayoutUnit)
{
return false;
}
diff --git a/Source/WebCore/rendering/EllipsisBox.h b/Source/WebCore/rendering/EllipsisBox.h
index c759a397e..699767847 100644
--- a/Source/WebCore/rendering/EllipsisBox.h
+++ b/Source/WebCore/rendering/EllipsisBox.h
@@ -40,7 +40,7 @@ public:
}
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, 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();
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.cpp b/Source/WebCore/rendering/FilterEffectRenderer.cpp
index 6d411995d..78ed248ff 100644
--- a/Source/WebCore/rendering/FilterEffectRenderer.cpp
+++ b/Source/WebCore/rendering/FilterEffectRenderer.cpp
@@ -29,6 +29,7 @@
#include "FilterEffectRenderer.h"
+#include "ColorSpace.h"
#include "Document.h"
#include "FEColorMatrix.h"
#include "FEComponentTransfer.h"
@@ -45,6 +46,7 @@
#include "CustomFilterGlobalContext.h"
#include "CustomFilterProgram.h"
#include "CustomFilterOperation.h"
+#include "CustomFilterValidatedProgram.h"
#include "FECustomFilter.h"
#include "RenderView.h"
#include "Settings.h"
@@ -89,6 +91,26 @@ static bool isCSSCustomFilterEnabled(Document* document)
Settings* settings = document->settings();
return settings && settings->isCSSCustomFilterEnabled() && settings->webGLEnabled();
}
+
+static PassRefPtr<FECustomFilter> createCustomFilterEffect(Filter* filter, Document* document, CustomFilterOperation* operation)
+{
+ if (!isCSSCustomFilterEnabled(document))
+ return 0;
+
+ RefPtr<CustomFilterProgram> program = operation->program();
+ if (!program->isLoaded())
+ return 0;
+
+ CustomFilterGlobalContext* globalContext = document->renderView()->customFilterGlobalContext();
+ globalContext->prepareContextIfNeeded(document->view()->hostWindow());
+ RefPtr<CustomFilterValidatedProgram> validatedProgram = globalContext->getValidatedProgram(program->programInfo());
+ if (!validatedProgram->isInitialized())
+ return 0;
+
+ return FECustomFilter::create(filter, globalContext, validatedProgram, operation->parameters(),
+ operation->meshRows(), operation->meshColumns(),
+ operation->meshBoxType(), operation->meshType());
+}
#endif
FilterEffectRenderer::FilterEffectRenderer()
@@ -322,23 +344,12 @@ bool FilterEffectRenderer::build(Document* document, const FilterOperations& ope
dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1);
break;
}
-#if ENABLE(CSS_SHADERS)
+#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
case FilterOperation::CUSTOM: {
-#if ENABLE(WEBGL)
- if (!isCSSCustomFilterEnabled(document))
- continue;
-
CustomFilterOperation* customFilterOperation = static_cast<CustomFilterOperation*>(filterOperation);
- RefPtr<CustomFilterProgram> program = customFilterOperation->program();
- if (program->isLoaded()) {
- CustomFilterGlobalContext* globalContext = document->renderView()->customFilterGlobalContext();
- globalContext->prepareContextIfNeeded(document->view()->hostWindow());
- effect = FECustomFilter::create(this, globalContext, program, customFilterOperation->parameters(),
- customFilterOperation->meshRows(), customFilterOperation->meshColumns(),
- customFilterOperation->meshBoxType(), customFilterOperation->meshType());
+ effect = createCustomFilterEffect(this, document, customFilterOperation);
+ if (effect)
m_hasCustomShaderFilter = true;
- }
-#endif
break;
}
#endif
@@ -349,6 +360,7 @@ bool FilterEffectRenderer::build(Document* document, const FilterOperations& ope
if (effect) {
// Unlike SVG, filters applied here should not clip to their primitive subregions.
effect->setClipsToBounds(false);
+ effect->setColorSpace(ColorSpaceDeviceRGB);
if (filterOperation->getOperationType() != FilterOperation::REFERENCE) {
effect->inputEffects().append(previousEffect);
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.h b/Source/WebCore/rendering/FilterEffectRenderer.h
index 0db987b3c..bc53cdc14 100644
--- a/Source/WebCore/rendering/FilterEffectRenderer.h
+++ b/Source/WebCore/rendering/FilterEffectRenderer.h
@@ -32,8 +32,10 @@
#include "FilterEffect.h"
#include "FilterOperations.h"
#include "FloatRect.h"
+#include "FractionalLayoutRect.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
+#include "LayoutTypesInlineMethods.h"
#include "SVGFilterBuilder.h"
#include "SourceGraphic.h"
@@ -111,7 +113,7 @@ public:
bool hasFilterThatMovesPixels() const { return m_hasFilterThatMovesPixels; }
LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);
-#if ENABLE(CSS_SHADERS)
+#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
bool hasCustomShaderFilter() const { return m_hasCustomShaderFilter; }
#endif
private:
diff --git a/Source/WebCore/rendering/FlowThreadController.cpp b/Source/WebCore/rendering/FlowThreadController.cpp
index 476c924b8..9edd0aa7e 100644
--- a/Source/WebCore/rendering/FlowThreadController.cpp
+++ b/Source/WebCore/rendering/FlowThreadController.cpp
@@ -31,12 +31,11 @@
#include "FlowThreadController.h"
+#include "NamedFlowCollection.h"
#include "RenderFlowThread.h"
-#include "RenderFlowThreadContainer.h"
#include "RenderNamedFlowThread.h"
#include "StyleInheritedData.h"
#include "WebKitNamedFlow.h"
-#include "WebKitNamedFlowCollection.h"
#include <wtf/text/AtomicString.h>
namespace WebCore {
@@ -49,7 +48,6 @@ PassOwnPtr<FlowThreadController> FlowThreadController::create(RenderView* view)
FlowThreadController::FlowThreadController(RenderView* view)
: m_view(view)
, m_currentRenderFlowThread(0)
- , m_flowThreadContainer(0)
, m_isRenderNamedFlowThreadOrderDirty(false)
{
}
@@ -60,11 +58,6 @@ FlowThreadController::~FlowThreadController()
RenderNamedFlowThread* FlowThreadController::ensureRenderFlowThreadWithName(const AtomicString& name)
{
- if (!m_flowThreadContainer) {
- m_flowThreadContainer = new (m_view->renderArena()) RenderFlowThreadContainer(m_view->document());
- m_flowThreadContainer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
- m_view->addChild(m_flowThreadContainer);
- }
if (!m_renderNamedFlowThreadList)
m_renderNamedFlowThreadList = adoptPtr(new RenderNamedFlowThreadList());
else {
@@ -75,7 +68,7 @@ RenderNamedFlowThread* FlowThreadController::ensureRenderFlowThreadWithName(cons
}
}
- WebKitNamedFlowCollection* namedFlows = m_view->document()->namedFlows();
+ 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));
@@ -84,8 +77,8 @@ RenderNamedFlowThread* FlowThreadController::ensureRenderFlowThreadWithName(cons
flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
m_renderNamedFlowThreadList->add(flowRenderer);
- // Keep the flow renderer as a child of RenderFlowThreadContainer.
- m_flowThreadContainer->addChild(flowRenderer);
+ // Keep the flow renderer as a child of RenderView.
+ m_view->addChild(flowRenderer);
setIsRenderNamedFlowThreadOrderDirty(true);
@@ -105,6 +98,23 @@ void FlowThreadController::layoutRenderNamedFlowThreads()
{
ASSERT(m_renderNamedFlowThreadList);
+ // 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;
@@ -146,10 +156,4 @@ void FlowThreadController::unregisterNamedFlowContentNode(Node* contentNode)
m_mapNamedFlowContentNodes.remove(contentNode);
}
-void FlowThreadController::removeFlowThread(RenderNamedFlowThread* flowThread)
-{
- m_renderNamedFlowThreadList->remove(flowThread);
- setIsRenderNamedFlowThreadOrderDirty(true);
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/rendering/FlowThreadController.h b/Source/WebCore/rendering/FlowThreadController.h
index 58edb2cf1..0aef61130 100644
--- a/Source/WebCore/rendering/FlowThreadController.h
+++ b/Source/WebCore/rendering/FlowThreadController.h
@@ -37,7 +37,6 @@
namespace WebCore {
class RenderFlowThread;
-class RenderFlowThreadContainer;
class RenderNamedFlowThread;
typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
@@ -66,7 +65,6 @@ public:
void registerNamedFlowContentNode(Node*, RenderNamedFlowThread*);
void unregisterNamedFlowContentNode(Node*);
- void removeFlowThread(RenderNamedFlowThread*);
protected:
FlowThreadController(RenderView*);
@@ -74,7 +72,6 @@ protected:
private:
RenderView* m_view;
RenderFlowThread* m_currentRenderFlowThread;
- RenderFlowThreadContainer* m_flowThreadContainer;
bool m_isRenderNamedFlowThreadOrderDirty;
OwnPtr<RenderNamedFlowThreadList> m_renderNamedFlowThreadList;
// maps a content node to its render flow thread.
diff --git a/Source/WebCore/rendering/HitTestRequest.h b/Source/WebCore/rendering/HitTestRequest.h
index e6a5231bb..1900900f1 100644
--- a/Source/WebCore/rendering/HitTestRequest.h
+++ b/Source/WebCore/rendering/HitTestRequest.h
@@ -34,7 +34,12 @@ public:
Release = 1 << 4,
IgnoreClipping = 1 << 5,
SVGClipContent = 1 << 6,
- TouchEvent = 1 << 7
+ TouchEvent = 1 << 7,
+ AllowShadowContent = 1 << 8,
+ AllowChildFrameContent = 1 << 9,
+ // FIXME: Get rid of the two options below if possible.
+ ChildFrameHitTest = 1 << 10,
+ TestChildFrameScrollBars = 1 << 11
};
typedef unsigned HitTestRequestType;
@@ -52,6 +57,10 @@ public:
bool svgClipContent() const { return m_requestType & SVGClipContent; }
bool touchEvent() const { return m_requestType & TouchEvent; }
bool mouseEvent() const { return !touchEvent(); }
+ bool allowsShadowContent() const { return m_requestType & AllowShadowContent; }
+ bool allowsChildFrameContent() const { return m_requestType & AllowChildFrameContent; }
+ bool isChildFrameHitTest() const { return m_requestType & ChildFrameHitTest; }
+ bool shouldTestChildFrameScrollBars() const { return m_requestType & TestChildFrameScrollBars; }
// Convenience functions
bool touchMove() const { return move() && touchEvent(); }
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp
index 0745763d1..8063c812e 100644
--- a/Source/WebCore/rendering/HitTestResult.cpp
+++ b/Source/WebCore/rendering/HitTestResult.cpp
@@ -48,14 +48,14 @@ namespace WebCore {
using namespace HTMLNames;
-HitTestPoint::HitTestPoint()
+HitTestLocation::HitTestLocation()
: m_region(0)
, m_isRectBased(false)
, m_isRectilinear(true)
{
}
-HitTestPoint::HitTestPoint(const LayoutPoint& point)
+HitTestLocation::HitTestLocation(const LayoutPoint& point)
: m_point(point)
, m_boundingBox(rectForPoint(point, 0, 0, 0, 0))
, m_transformedPoint(point)
@@ -66,7 +66,7 @@ HitTestPoint::HitTestPoint(const LayoutPoint& point)
{
}
-HitTestPoint::HitTestPoint(const FloatPoint& point)
+HitTestLocation::HitTestLocation(const FloatPoint& point)
: m_point(flooredLayoutPoint(point))
, m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0))
, m_transformedPoint(point)
@@ -77,7 +77,7 @@ HitTestPoint::HitTestPoint(const FloatPoint& point)
{
}
-HitTestPoint::HitTestPoint(const FloatPoint& point, const FloatQuad& quad)
+HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
: m_transformedPoint(point)
, m_transformedRect(quad)
, m_region(0)
@@ -88,7 +88,7 @@ HitTestPoint::HitTestPoint(const FloatPoint& point, const FloatQuad& quad)
m_isRectilinear = quad.isRectilinear();
}
-HitTestPoint::HitTestPoint(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+HitTestLocation::HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
: m_point(centerPoint)
, m_boundingBox(rectForPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding))
, m_transformedPoint(centerPoint)
@@ -99,19 +99,19 @@ HitTestPoint::HitTestPoint(const LayoutPoint& centerPoint, unsigned topPadding,
m_transformedRect = FloatQuad(m_boundingBox);
}
-HitTestPoint::HitTestPoint(const HitTestPoint& other, const LayoutSize& offset, RenderRegion* region)
+HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset, RenderRegion* region)
: m_point(other.m_point)
, m_boundingBox(other.m_boundingBox)
, m_transformedPoint(other.m_transformedPoint)
, m_transformedRect(other.m_transformedRect)
- , m_region(region)
+ , m_region(region ? region : other.m_region)
, m_isRectBased(other.m_isRectBased)
, m_isRectilinear(other.m_isRectilinear)
{
move(offset);
}
-HitTestPoint::HitTestPoint(const HitTestPoint& other)
+HitTestLocation::HitTestLocation(const HitTestLocation& other)
: m_point(other.m_point)
, m_boundingBox(other.m_boundingBox)
, m_transformedPoint(other.m_transformedPoint)
@@ -122,11 +122,11 @@ HitTestPoint::HitTestPoint(const HitTestPoint& other)
{
}
-HitTestPoint::~HitTestPoint()
+HitTestLocation::~HitTestLocation()
{
}
-HitTestPoint& HitTestPoint::operator=(const HitTestPoint& other)
+HitTestLocation& HitTestLocation::operator=(const HitTestLocation& other)
{
m_point = other.m_point;
m_boundingBox = other.m_boundingBox;
@@ -139,7 +139,7 @@ HitTestPoint& HitTestPoint::operator=(const HitTestPoint& other)
return *this;
}
-void HitTestPoint::move(const LayoutSize& offset)
+void HitTestLocation::move(const LayoutSize& offset)
{
m_point.move(offset);
m_transformedPoint.move(offset);
@@ -148,7 +148,7 @@ void HitTestPoint::move(const LayoutSize& offset)
}
template<typename RectType>
-bool HitTestPoint::intersectsRect(const RectType& rect) const
+bool HitTestLocation::intersectsRect(const RectType& rect) const
{
// FIXME: When the hit test is not rect based we should use rect.contains(m_point).
// That does change some corner case tests though.
@@ -169,17 +169,17 @@ bool HitTestPoint::intersectsRect(const RectType& rect) const
return m_transformedRect.intersectsRect(rect);
}
-bool HitTestPoint::intersects(const LayoutRect& rect) const
+bool HitTestLocation::intersects(const LayoutRect& rect) const
{
return intersectsRect(rect);
}
-bool HitTestPoint::intersects(const FloatRect& rect) const
+bool HitTestLocation::intersects(const FloatRect& rect) const
{
return intersectsRect(rect);
}
-IntRect HitTestPoint::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+IntRect HitTestLocation::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
{
IntPoint actualPoint(flooredIntPoint(point));
actualPoint -= IntSize(leftPadding, topPadding);
@@ -192,41 +192,36 @@ IntRect HitTestPoint::rectForPoint(const LayoutPoint& point, unsigned topPadding
return IntRect(actualPoint, actualPadding);
}
-HitTestResult::HitTestResult() : HitTestPoint()
+HitTestResult::HitTestResult() : HitTestLocation()
, m_isOverWidget(false)
- , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
{
}
-HitTestResult::HitTestResult(const LayoutPoint& point) : HitTestPoint(point)
+HitTestResult::HitTestResult(const LayoutPoint& point) : HitTestLocation(point)
, m_isOverWidget(false)
- , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
{
}
-HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy allowShadowContent)
- : HitTestPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding)
+HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+ : HitTestLocation(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding)
, m_isOverWidget(false)
- , m_shadowContentFilterPolicy(allowShadowContent)
{
}
-HitTestResult::HitTestResult(const HitTestPoint& other, ShadowContentFilterPolicy allowShadowContent)
- : HitTestPoint(other)
+HitTestResult::HitTestResult(const HitTestLocation& other)
+ : HitTestLocation(other)
, m_isOverWidget(false)
- , m_shadowContentFilterPolicy(allowShadowContent)
{
}
HitTestResult::HitTestResult(const HitTestResult& other)
- : HitTestPoint(other)
+ : HitTestLocation(other)
, m_innerNode(other.innerNode())
, m_innerNonSharedNode(other.innerNonSharedNode())
, m_localPoint(other.localPoint())
, m_innerURLElement(other.URLElement())
, m_scrollbar(other.scrollbar())
, m_isOverWidget(other.isOverWidget())
- , m_shadowContentFilterPolicy(other.shadowContentFilterPolicy())
{
// Only copy the NodeSet in case of rect hit test.
m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
@@ -238,7 +233,7 @@ HitTestResult::~HitTestResult()
HitTestResult& HitTestResult::operator=(const HitTestResult& other)
{
- HitTestPoint::operator=(other);
+ HitTestLocation::operator=(other);
m_innerNode = other.innerNode();
m_innerNonSharedNode = other.innerNonSharedNode();
m_localPoint = other.localPoint();
@@ -248,7 +243,6 @@ HitTestResult& HitTestResult::operator=(const HitTestResult& other)
// Only copy the NodeSet in case of rect hit test.
m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
- m_shadowContentFilterPolicy = other.shadowContentFilterPolicy();
return *this;
}
@@ -674,7 +668,7 @@ bool HitTestResult::isContentEditable() const
return m_innerNonSharedNode->rendererIsEditable();
}
-bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestPoint& pointInContainer, const LayoutRect& rect)
+bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestRequest& request, const HitTestLocation& locationInContainer, const LayoutRect& rect)
{
// If it is not a rect-based hit test, this method has to be no-op.
// Return false, so the hit test stops.
@@ -685,12 +679,12 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestPoint&
if (!node)
return true;
- if (m_shadowContentFilterPolicy == DoNotAllowShadowContent)
+ if (!request.allowsShadowContent())
node = node->shadowAncestorNode();
mutableRectBasedTestResult().add(node);
- bool regionFilled = rect.contains(pointInContainer.boundingBox());
+ bool regionFilled = rect.contains(locationInContainer.boundingBox());
// FIXME: This code (incorrectly) attempts to correct for culled inline nodes. See https://bugs.webkit.org/show_bug.cgi?id=85849.
if (node->renderer()->isInline() && !regionFilled) {
for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) {
@@ -709,7 +703,7 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestPoint&
return !regionFilled;
}
-bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestPoint& pointInContainer, const FloatRect& rect)
+bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestRequest& request, const HitTestLocation& locationInContainer, const FloatRect& rect)
{
// If it is not a rect-based hit test, this method has to be no-op.
// Return false, so the hit test stops.
@@ -720,12 +714,12 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestPoint&
if (!node)
return true;
- if (m_shadowContentFilterPolicy == DoNotAllowShadowContent)
+ if (!request.allowsShadowContent())
node = node->shadowAncestorNode();
mutableRectBasedTestResult().add(node);
- bool regionFilled = rect.contains(pointInContainer.boundingBox());
+ bool regionFilled = rect.contains(locationInContainer.boundingBox());
// FIXME: This code (incorrectly) attempts to correct for culled inline nodes. See https://bugs.webkit.org/show_bug.cgi?id=85849.
if (node->renderer()->isInline() && !regionFilled) {
for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) {
@@ -784,7 +778,7 @@ Vector<String> HitTestResult::dictationAlternatives() const
if (!m_innerNonSharedNode)
return Vector<String>();
- DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(hitTestPoint().point(), DocumentMarker::DictationAlternatives);
+ DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(hitTestLocation().point(), DocumentMarker::DictationAlternatives);
if (!marker)
return Vector<String>();
diff --git a/Source/WebCore/rendering/HitTestResult.h b/Source/WebCore/rendering/HitTestResult.h
index 9d16bf042..bac96a2b1 100644
--- a/Source/WebCore/rendering/HitTestResult.h
+++ b/Source/WebCore/rendering/HitTestResult.h
@@ -25,7 +25,7 @@
#include "FloatQuad.h"
#include "FloatRect.h"
#include "HitTestRequest.h"
-#include "LayoutTypes.h"
+#include "LayoutTypesInlineMethods.h"
#include "TextDirection.h"
#include <wtf/Forward.h>
#include <wtf/ListHashSet.h>
@@ -45,22 +45,20 @@ class Node;
class RenderRegion;
class Scrollbar;
-enum ShadowContentFilterPolicy { DoNotAllowShadowContent, AllowShadowContent };
-
-class HitTestPoint {
+class HitTestLocation {
public:
- HitTestPoint();
- HitTestPoint(const LayoutPoint&);
- HitTestPoint(const FloatPoint&);
- HitTestPoint(const FloatPoint&, const FloatQuad&);
+ HitTestLocation();
+ HitTestLocation(const LayoutPoint&);
+ HitTestLocation(const FloatPoint&);
+ HitTestLocation(const FloatPoint&, const FloatQuad&);
// Pass non-zero padding values to perform a rect-based hit test.
- HitTestPoint(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
- // Make a copy the HitTestPoint in a new region by applying given offset to internal point and area.
- HitTestPoint(const HitTestPoint&, const LayoutSize& offset, RenderRegion*);
- HitTestPoint(const HitTestPoint&);
- ~HitTestPoint();
- HitTestPoint& operator=(const HitTestPoint&);
+ 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&);
+ ~HitTestLocation();
+ HitTestLocation& operator=(const HitTestLocation&);
LayoutPoint point() const { return m_point; }
IntPoint roundedPoint() const { return roundedIntPoint(m_point); }
@@ -102,15 +100,15 @@ private:
bool m_isRectilinear;
};
-class HitTestResult : public HitTestPoint {
+class HitTestResult : public HitTestLocation {
public:
typedef ListHashSet<RefPtr<Node> > NodeSet;
HitTestResult();
HitTestResult(const LayoutPoint&);
// Pass non-negative padding values to perform a rect-based hit test.
- HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy);
- HitTestResult(const HitTestPoint&, ShadowContentFilterPolicy);
+ HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+ HitTestResult(const HitTestLocation&);
HitTestResult(const HitTestResult&);
~HitTestResult();
HitTestResult& operator=(const HitTestResult&);
@@ -124,8 +122,7 @@ public:
void setToNonShadowAncestor();
- const HitTestPoint& hitTestPoint() const { return *this; }
- ShadowContentFilterPolicy shadowContentFilterPolicy() const { return m_shadowContentFilterPolicy; }
+ const HitTestLocation& hitTestLocation() const { return *this; }
void setInnerNode(Node*);
void setInnerNonSharedNode(Node*);
@@ -166,8 +163,8 @@ public:
// Returns true if it is rect-based hit test and needs to continue until the rect is fully
// enclosed by the boundaries of a node.
- bool addNodeToRectBasedTestResult(Node*, const HitTestPoint& pointInContainer, const LayoutRect& = LayoutRect());
- bool addNodeToRectBasedTestResult(Node*, const HitTestPoint& pointInContainer, const FloatRect&);
+ bool addNodeToRectBasedTestResult(Node*, const HitTestRequest&, const HitTestLocation& pointInContainer, const LayoutRect& = LayoutRect());
+ bool addNodeToRectBasedTestResult(Node*, const HitTestRequest&, const HitTestLocation& pointInContainer, const FloatRect&);
void append(const HitTestResult&);
// If m_rectBasedTestResult is 0 then set it to a new NodeSet. Return *m_rectBasedTestResult. Lazy allocation makes
@@ -194,8 +191,6 @@ private:
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).
- ShadowContentFilterPolicy m_shadowContentFilterPolicy;
-
mutable OwnPtr<NodeSet> m_rectBasedTestResult;
};
diff --git a/Source/WebCore/rendering/HitTestingTransformState.cpp b/Source/WebCore/rendering/HitTestingTransformState.cpp
index 6d9cc7629..6d6c33e91 100644
--- a/Source/WebCore/rendering/HitTestingTransformState.cpp
+++ b/Source/WebCore/rendering/HitTestingTransformState.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "HitTestingTransformState.h"
+#include "FractionalLayoutRect.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
diff --git a/Source/WebCore/rendering/InlineBox.cpp b/Source/WebCore/rendering/InlineBox.cpp
index be3c9c7cf..01742e5bf 100644
--- a/Source/WebCore/rendering/InlineBox.cpp
+++ b/Source/WebCore/rendering/InlineBox.cpp
@@ -243,12 +243,12 @@ void InlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, Layo
}
}
-bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
+bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
{
// Hit test all phases of replaced elements atomically, as though the replaced element established its
// own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
// specification.)
- return renderer()->hitTest(request, result, pointInContainer, accumulatedOffset);
+ return renderer()->hitTest(request, result, locationInContainer, accumulatedOffset);
}
const RootInlineBox* InlineBox::root() const
diff --git a/Source/WebCore/rendering/InlineBox.h b/Source/WebCore/rendering/InlineBox.h
index 0edab2c33..d8f7e3c17 100644
--- a/Source/WebCore/rendering/InlineBox.h
+++ b/Source/WebCore/rendering/InlineBox.h
@@ -95,7 +95,7 @@ public:
}
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
// Overloaded new operator.
void* operator new(size_t, RenderArena*);
diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp
index 126db27f9..9ad0fcfa1 100644
--- a/Source/WebCore/rendering/InlineFlowBox.cpp
+++ b/Source/WebCore/rendering/InlineFlowBox.cpp
@@ -36,6 +36,7 @@
#include "RenderRubyRun.h"
#include "RenderRubyText.h"
#include "RenderTableCell.h"
+#include "RenderView.h"
#include "RootInlineBox.h"
#include "Text.h"
@@ -971,18 +972,18 @@ void InlineFlowBox::setOverflowFromLogicalRects(const LayoutRect& logicalLayoutO
setVisualOverflow(visualOverflow, lineTop, lineBottom);
}
-bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
flipForWritingMode(overflowRect);
overflowRect.moveBy(accumulatedOffset);
- if (!pointInContainer.intersects(overflowRect))
+ if (!locationInContainer.intersects(overflowRect))
return false;
// Check children first.
for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
- if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, pointInContainer, accumulatedOffset, lineTop, lineBottom)) {
- renderer()->updateHitTestResult(result, pointInContainer.point() - toLayoutSize(accumulatedOffset));
+ if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
+ renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
return true;
}
}
@@ -1010,9 +1011,9 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
flipForWritingMode(rect);
rect.moveBy(accumulatedOffset);
- if (visibleToHitTesting() && pointInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, flipForWritingMode(pointInContainer.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(), pointInContainer, rect))
+ if (visibleToHitTesting() && 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))
return true;
}
diff --git a/Source/WebCore/rendering/InlineFlowBox.h b/Source/WebCore/rendering/InlineFlowBox.h
index 32839f15f..5a34f6c65 100644
--- a/Source/WebCore/rendering/InlineFlowBox.h
+++ b/Source/WebCore/rendering/InlineFlowBox.h
@@ -116,7 +116,7 @@ public:
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 bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, 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;
diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp
index 7d63031da..5bc3b7652 100644
--- a/Source/WebCore/rendering/InlineTextBox.cpp
+++ b/Source/WebCore/rendering/InlineTextBox.cpp
@@ -349,7 +349,7 @@ bool InlineTextBox::isLineBreak() const
return renderer()->isBR() || (renderer()->style()->preserveNewline() && len() == 1 && (*textRenderer()->text())[start()] == '\n');
}
-bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
+bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
{
if (isLineBreak())
return false;
@@ -357,9 +357,9 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, co
FloatPoint boxOrigin = locationIncludingFlipping();
boxOrigin.moveBy(accumulatedOffset);
FloatRect rect(boxOrigin, size());
- if (m_truncation != cFullTruncation && visibleToHitTesting() && pointInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, flipForWritingMode(pointInContainer.point() - toLayoutSize(accumulatedOffset)));
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), pointInContainer, rect))
+ if (m_truncation != cFullTruncation && visibleToHitTesting() && locationInContainer.intersects(rect)) {
+ renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset)));
+ if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
return true;
}
return false;
diff --git a/Source/WebCore/rendering/InlineTextBox.h b/Source/WebCore/rendering/InlineTextBox.h
index a3e7630e6..06ba040fc 100644
--- a/Source/WebCore/rendering/InlineTextBox.h
+++ b/Source/WebCore/rendering/InlineTextBox.h
@@ -115,7 +115,7 @@ public:
protected:
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, 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;
diff --git a/Source/WebCore/rendering/LayoutRepainter.h b/Source/WebCore/rendering/LayoutRepainter.h
index 57400faeb..6f63e82d3 100644
--- a/Source/WebCore/rendering/LayoutRepainter.h
+++ b/Source/WebCore/rendering/LayoutRepainter.h
@@ -26,7 +26,7 @@
#ifndef LayoutRepainter_h
#define LayoutRepainter_h
-#include "LayoutTypes.h"
+#include "LayoutTypesInlineMethods.h"
namespace WebCore {
diff --git a/Source/WebCore/rendering/LayoutState.cpp b/Source/WebCore/rendering/LayoutState.cpp
index 1dff9533e..1e4442f2f 100644
--- a/Source/WebCore/rendering/LayoutState.cpp
+++ b/Source/WebCore/rendering/LayoutState.cpp
@@ -83,7 +83,7 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz
// 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) {
+ 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()),
@@ -109,7 +109,7 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz
m_layoutDelta = m_next->m_layoutDelta;
- m_isPaginated = m_pageLogicalHeight || m_columnInfo;
+ m_isPaginated = m_pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread();
if (lineGrid() && renderer->hasColumns() && renderer->style()->hasInlineColumnAxis())
computeLineGridPaginationOrigin(renderer);
@@ -121,23 +121,6 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz
// FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
-LayoutState::LayoutState(LayoutState* prev, RenderFlowThread* flowThread, bool regionsChanged)
- : m_clipped(false)
- , m_isPaginated(true)
- , m_pageLogicalHeight(1) // Use a fake height here. That value is not important, just needs to be non-zero.
- , m_pageLogicalHeightChanged(regionsChanged)
- , m_columnInfo(0)
- , m_lineGrid(0)
- , m_next(prev)
-#ifndef NDEBUG
- , m_renderer(flowThread)
-#endif
-{
-#ifdef NDEBUG
- UNUSED_PARAM(flowThread);
-#endif
-}
-
LayoutState::LayoutState(RenderObject* root)
: m_clipped(false)
, m_isPaginated(false)
diff --git a/Source/WebCore/rendering/LayoutState.h b/Source/WebCore/rendering/LayoutState.h
index 81d61e9cd..152c80465 100644
--- a/Source/WebCore/rendering/LayoutState.h
+++ b/Source/WebCore/rendering/LayoutState.h
@@ -57,7 +57,6 @@ public:
}
LayoutState(LayoutState*, RenderBox*, const LayoutSize& offset, LayoutUnit pageHeight, bool pageHeightChanged, ColumnInfo*);
- LayoutState(LayoutState*, RenderFlowThread*, bool regionsChanged);
LayoutState(RenderObject*);
void destroy(RenderArena*);
diff --git a/Source/WebCore/rendering/LayoutTypes.h b/Source/WebCore/rendering/LayoutTypes.h
index 51967f8e9..ff7e6c274 100644
--- a/Source/WebCore/rendering/LayoutTypes.h
+++ b/Source/WebCore/rendering/LayoutTypes.h
@@ -36,132 +36,24 @@
#ifndef LayoutTypes_h
#define LayoutTypes_h
-#include "FloatRect.h"
-#include "FractionalLayoutBoxExtent.h"
-#include "FractionalLayoutRect.h"
-#include "FractionalLayoutUnit.h"
-#include "IntRect.h"
-
-#include <wtf/MathExtras.h>
-
namespace WebCore {
-typedef FractionalLayoutUnit LayoutUnit;
+class FractionalLayoutBoxExtent;
+class FractionalLayoutPoint;
+class FractionalLayoutRect;
+class FractionalLayoutSize;
+class FractionalLayoutUnit;
+
+typedef FractionalLayoutBoxExtent LayoutBoxExtent;
typedef FractionalLayoutPoint LayoutPoint;
-typedef FractionalLayoutSize LayoutSize;
typedef FractionalLayoutRect LayoutRect;
-typedef FractionalLayoutBoxExtent LayoutBoxExtent;
+typedef FractionalLayoutSize LayoutSize;
+typedef FractionalLayoutUnit LayoutUnit;
#define MAX_LAYOUT_UNIT LayoutUnit::max()
#define MIN_LAYOUT_UNIT LayoutUnit::min()
#define ZERO_LAYOUT_UNIT LayoutUnit(0)
-inline FractionalLayoutRect enclosingLayoutRect(const FloatRect& rect)
-{
- return enclosingIntRect(rect);
-}
-
-inline LayoutSize roundedLayoutSize(const FloatSize& s)
-{
-#if ENABLE(SUBPIXEL_LAYOUT)
- return FractionalLayoutSize(s);
-#else
- return roundedIntSize(s);
-#endif
-}
-
-inline IntRect pixelSnappedIntRect(LayoutUnit left, LayoutUnit top, LayoutUnit width, LayoutUnit height)
-{
- return IntRect(left.round(), top.round(), snapSizeToPixel(width, left), snapSizeToPixel(height, top));
-}
-
-inline IntRect pixelSnappedIntRectFromEdges(LayoutUnit left, LayoutUnit top, LayoutUnit right, LayoutUnit bottom)
-{
- return IntRect(left.round(), top.round(), snapSizeToPixel(right - left, left), snapSizeToPixel(bottom - top, top));
-}
-
-inline LayoutPoint roundedLayoutPoint(const FloatPoint& p)
-{
-#if ENABLE(SUBPIXEL_LAYOUT)
- return FractionalLayoutPoint(p);
-#else
- return roundedIntPoint(p);
-#endif
-}
-
-inline LayoutPoint flooredLayoutPoint(const FloatPoint& p)
-{
- return flooredFractionalLayoutPoint(p);
-}
-
-inline LayoutPoint flooredLayoutPoint(const FloatSize& s)
-{
- return flooredLayoutPoint(FloatPoint(s));
-}
-
-inline int roundToInt(LayoutUnit value)
-{
- return value.round();
-}
-
-inline int floorToInt(LayoutUnit value)
-{
- return value.floor();
-}
-
-inline LayoutUnit roundedLayoutUnit(float value)
-{
-#if ENABLE(SUBPIXEL_LAYOUT)
- return FractionalLayoutUnit::fromFloatRound(value);
-#else
- return static_cast<int>(lroundf(value));
-#endif
-}
-
-inline LayoutUnit ceiledLayoutUnit(float value)
-{
-#if ENABLE(SUBPIXEL_LAYOUT)
- return FractionalLayoutUnit::fromFloatCeil(value);
-#else
- return ceilf(value);
-#endif
-}
-
-inline LayoutUnit absoluteValue(const LayoutUnit& value)
-{
- return value.abs();
-}
-
-inline LayoutSize toLayoutSize(const LayoutPoint& p)
-{
- return LayoutSize(p.x(), p.y());
-}
-
-inline LayoutPoint toLayoutPoint(const LayoutSize& p)
-{
- return LayoutPoint(p.width(), p.height());
-}
-
-inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator)
-{
- return numerator % denominator;
-}
-
-inline IntSize pixelSnappedIntSize(const FractionalLayoutSize& s, const FractionalLayoutPoint& p)
-{
- return IntSize(snapSizeToPixel(s.width(), p.x()), snapSizeToPixel(s.height(), p.y()));
-}
-
-inline IntRect pixelSnappedIntRect(LayoutPoint location, LayoutSize size)
-{
- return IntRect(roundedIntPoint(location), pixelSnappedIntSize(size, location));
-}
-
-inline bool isIntegerValue(const LayoutUnit value)
-{
- return value.toInt() == value;
-}
-
} // namespace WebCore
#endif // LayoutTypes_h
diff --git a/Source/WebCore/rendering/LayoutTypesInlineMethods.h b/Source/WebCore/rendering/LayoutTypesInlineMethods.h
new file mode 100644
index 000000000..3cb4a0fdb
--- /dev/null
+++ b/Source/WebCore/rendering/LayoutTypesInlineMethods.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011 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 LayoutTypesInlineMethods_h
+#define LayoutTypesInlineMethods_h
+
+#include "FloatRect.h"
+#include "FractionalLayoutBoxExtent.h"
+#include "FractionalLayoutRect.h"
+#include "FractionalLayoutUnit.h"
+#include "IntRect.h"
+#include "LayoutTypes.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+inline FractionalLayoutRect enclosingLayoutRect(const FloatRect& rect)
+{
+ return enclosingIntRect(rect);
+}
+
+inline LayoutSize roundedLayoutSize(const FloatSize& s)
+{
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutSize(s);
+#else
+ return roundedIntSize(s);
+#endif
+}
+
+inline IntRect pixelSnappedIntRect(LayoutUnit left, LayoutUnit top, LayoutUnit width, LayoutUnit height)
+{
+ return IntRect(left.round(), top.round(), snapSizeToPixel(width, left), snapSizeToPixel(height, top));
+}
+
+inline IntRect pixelSnappedIntRectFromEdges(LayoutUnit left, LayoutUnit top, LayoutUnit right, LayoutUnit bottom)
+{
+ return IntRect(left.round(), top.round(), snapSizeToPixel(right - left, left), snapSizeToPixel(bottom - top, top));
+}
+
+inline LayoutPoint roundedLayoutPoint(const FloatPoint& p)
+{
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutPoint(p);
+#else
+ return roundedIntPoint(p);
+#endif
+}
+
+inline LayoutPoint flooredLayoutPoint(const FloatPoint& p)
+{
+ return flooredFractionalLayoutPoint(p);
+}
+
+inline LayoutPoint flooredLayoutPoint(const FloatSize& s)
+{
+ return flooredLayoutPoint(FloatPoint(s));
+}
+
+inline int roundToInt(LayoutUnit value)
+{
+ return value.round();
+}
+
+inline int floorToInt(LayoutUnit value)
+{
+ return value.floor();
+}
+
+inline LayoutUnit roundedLayoutUnit(float value)
+{
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutUnit::fromFloatRound(value);
+#else
+ return static_cast<int>(lroundf(value));
+#endif
+}
+
+inline LayoutUnit ceiledLayoutUnit(float value)
+{
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutUnit::fromFloatCeil(value);
+#else
+ return ceilf(value);
+#endif
+}
+
+inline LayoutUnit absoluteValue(const LayoutUnit& value)
+{
+ return value.abs();
+}
+
+inline LayoutSize toLayoutSize(const LayoutPoint& p)
+{
+ return LayoutSize(p.x(), p.y());
+}
+
+inline LayoutPoint toLayoutPoint(const LayoutSize& p)
+{
+ return LayoutPoint(p.width(), p.height());
+}
+
+inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator)
+{
+ return numerator % denominator;
+}
+
+inline IntSize pixelSnappedIntSize(const FractionalLayoutSize& s, const FractionalLayoutPoint& p)
+{
+ return IntSize(snapSizeToPixel(s.width(), p.x()), snapSizeToPixel(s.height(), p.y()));
+}
+
+inline IntRect pixelSnappedIntRect(LayoutPoint location, LayoutSize size)
+{
+ return IntRect(roundedIntPoint(location), pixelSnappedIntSize(size, location));
+}
+
+inline bool isIntegerValue(const LayoutUnit value)
+{
+ return value.toInt() == value;
+}
+
+} // namespace WebCore
+
+#endif // LayoutTypesInlineMethods_h
diff --git a/Source/WebCore/rendering/PaintInfo.h b/Source/WebCore/rendering/PaintInfo.h
index 7ed743272..88a3c7abc 100644
--- a/Source/WebCore/rendering/PaintInfo.h
+++ b/Source/WebCore/rendering/PaintInfo.h
@@ -32,7 +32,7 @@
#include "GraphicsContext.h"
#include "IntRect.h"
-#include "LayoutTypes.h"
+#include "LayoutTypesInlineMethods.h"
#include "PaintPhase.h"
#include <limits>
#include <wtf/HashMap.h>
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 119cbb7fd..10216bc00 100755
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -61,6 +61,9 @@
#include "ShadowRoot.h"
#include "TransformState.h"
#include <wtf/StdLibExtras.h>
+#if ENABLE(CSS_EXCLUSIONS)
+#include "WrapShapeInfo.h"
+#endif
using namespace std;
using namespace WTF;
@@ -275,6 +278,10 @@ void RenderBlock::willBeDestroyed()
if (lineGridBox())
lineGridBox()->destroy(renderArena());
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo::removeWrapShapeInfoForRenderBlock(this);
+#endif
+
if (UNLIKELY(gDelayedUpdateScrollInfoSet != 0))
gDelayedUpdateScrollInfoSet->remove(this);
@@ -320,6 +327,12 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
{
RenderBox::styleDidChange(diff, oldStyle);
+#if ENABLE(CSS_EXCLUSIONS)
+ // FIXME: Bug 89993: Style changes should affect the WrapShapeInfos for other render blocks that
+ // share the same WrapShapeInfo
+ updateWrapShapeInfoAfterStyleChange(style()->wrapShapeInside(), oldStyle ? oldStyle->wrapShapeInside() : 0);
+#endif
+
if (!isAnonymousBlock()) {
// Ensure that all of our continuation blocks pick up the new style.
for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
@@ -1366,6 +1379,21 @@ void RenderBlock::layout()
clearLayoutOverflow();
}
+#if ENABLE(CSS_EXCLUSIONS)
+void RenderBlock::updateWrapShapeInfoAfterStyleChange(const BasicShape* wrapShape, const BasicShape* oldWrapShape)
+{
+ // FIXME: A future optimization would do a deep comparison for equality.
+ if (wrapShape == oldWrapShape)
+ return;
+
+ if (wrapShape) {
+ WrapShapeInfo* wrapShapeInfo = WrapShapeInfo::ensureWrapShapeInfoForRenderBlock(this);
+ wrapShapeInfo->dirtyWrapShapeSize();
+ } else
+ WrapShapeInfo::removeWrapShapeInfoForRenderBlock(this);
+}
+#endif
+
void RenderBlock::computeInitialRegionRangeForBlock()
{
if (inRenderFlowThread()) {
@@ -1422,6 +1450,9 @@ void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalH
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)->pageLogicalHeightChanged();
}
}
@@ -1461,6 +1492,11 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
relayoutChildren = true;
}
computeInitialRegionRangeForBlock();
+#if ENABLE(CSS_EXCLUSIONS)
+ // FIXME: Bug 93547: Resolve logical height for percentage based vertical lengths
+ if (WrapShapeInfo* wrapShapeInfo = this->wrapShapeInfo())
+ wrapShapeInfo->computeShapeSize(logicalWidth(), 0);
+#endif
// We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
// our current maximal positive and negative margins. These values are used when we
@@ -2049,28 +2085,28 @@ LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& margin
// For self-collapsing blocks that clear, they can still collapse their
// margins with following siblings. Reset the current margins to represent
// the self-collapsing block's margins only.
- // CSS2.1 states:
- // "An element that has had clearance applied to it never collapses its top margin with its parent block's bottom margin.
- // Therefore if we are at the bottom of the block, let's go ahead and reset margins to only include the
- // self-collapsing block's bottom margin.
- bool atBottomOfBlock = true;
- for (RenderBox* curr = child->nextSiblingBox(); curr && atBottomOfBlock; curr = curr->nextSiblingBox()) {
- if (!curr->isFloatingOrOutOfFlowPositioned())
- atBottomOfBlock = false;
- }
-
MarginValues childMargins = marginValuesForChild(child);
- if (atBottomOfBlock) {
- marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
- marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
- } else {
- marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
- marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
- }
-
- // Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
- // of the parent block).
- setLogicalHeight(child->logicalTop() - max(ZERO_LAYOUT_UNIT, marginInfo.margin()));
+ marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
+ marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
+
+ // 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);
+
+ // CSS2.1: "the amount of clearance is set so that clearance + margin-top = [height of float], i.e., clearance = [height of float] - margin-top"
+ // Move the top of the child box to the bottom of the float ignoring the child's top margin.
+ LayoutUnit collapsedMargin = collapsedMarginBeforeForChild(child);
+ setLogicalHeight(child->logicalTop() - collapsedMargin);
+ heightIncrease -= collapsedMargin;
} else
// Increase our height by the amount we had to clear.
setLogicalHeight(logicalHeight() + heightIncrease);
@@ -2084,8 +2120,14 @@ LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& margin
setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
marginInfo.setAtBeforeSideOfBlock(false);
}
-
- return yPos + heightIncrease;
+
+ LayoutUnit logicalTop = yPos + heightIncrease;
+ // After margin collapsing, one of our floats may now intrude into the child. If the child doesn't contain floats of its own it
+ // won't get picked up for relayout even though the logical top estimate was wrong - so add the newly intruding float now.
+ if (containsFloats() && child->isRenderBlock() && !toRenderBlock(child)->containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
+ toRenderBlock(child)->addIntrudingFloats(this, logicalLeftOffsetForContent(), logicalTop);
+
+ return logicalTop;
}
void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore) const
@@ -2122,7 +2164,7 @@ void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& pos
// Make sure to update the block margins now for the grandchild box so that we're looking at current values.
if (grandchildBox->needsLayout()) {
- grandchildBox->computeBlockDirectionMargins(this);
+ grandchildBox->computeAndSetBlockDirectionMargins(this);
grandchildBox->setMarginBeforeQuirk(grandchildBox->style()->marginBefore().quirk());
grandchildBox->setMarginAfterQuirk(grandchildBox->style()->marginAfter().quirk());
}
@@ -2246,7 +2288,10 @@ void RenderBlock::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit after
marginInfo.setAtAfterSideOfBlock(true);
// If we can't collapse with children then go ahead and add in the bottom margin.
+ // Don't do this for ordinary anonymous blocks as only the enclosing box should add in
+ // its margin.
if (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
+ && (!isAnonymousBlock() || isAnonymousColumnsBlock() || isAnonymousColumnSpanBlock())
&& (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginAfterQuirk()))
setLogicalHeight(logicalHeight() + marginInfo.margin());
@@ -2366,7 +2411,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay
LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
// The child is a normal flow object. Compute the margins we will use for collapsing now.
- child->computeBlockDirectionMargins(this);
+ child->computeAndSetBlockDirectionMargins(this);
// Do not allow a collapse if the margin-before-collapse style is set to SEPARATE.
RenderStyle* childStyle = child->style();
@@ -2615,14 +2660,6 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
r->layoutIfNeeded();
- // Adjust the static position of a center-aligned inline positioned object with a block child now that the child's width has been computed.
- if (!r->parent()->isRenderView() && r->parent()->isRenderBlock() && r->firstChild() && r->style()->position() == AbsolutePosition
- && r->style()->isOriginalDisplayInlineType() && (r->style()->textAlign() == CENTER || r->style()->textAlign() == WEBKIT_CENTER)) {
- RenderBlock* block = toRenderBlock(r->parent());
- LayoutUnit blockHeight = block->logicalHeight();
- block->setStaticInlinePositionForChild(r, blockHeight, block->startAlignedOffsetForLine(r, blockHeight, false));
- }
-
// Lay out again if our estimate was wrong.
if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) {
r->setChildNeedsLayout(true, MarkOnlyThis);
@@ -3177,9 +3214,10 @@ bool RenderBlock::isSelectionRoot() const
return false;
if (isBody() || isRoot() || hasOverflowClip()
- || isInFlowPositioned() || isFloatingOrOutOfFlowPositioned()
+ || isPositioned() || isFloating()
|| isTableCell() || isInlineBlockOrInlineTable()
- || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot())
+ || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
+ || isRenderFlowThread())
return true;
if (view() && view()->selectionStart()) {
@@ -3723,7 +3761,7 @@ RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
o->layoutIfNeeded();
else {
o->computeLogicalWidth();
- o->computeBlockDirectionMargins(this);
+ o->computeAndSetBlockDirectionMargins(this);
}
setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
@@ -4473,6 +4511,8 @@ bool RenderBlock::hasOverhangingFloat(RenderBox* renderer)
void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset)
{
+ ASSERT(!avoidsFloats());
+
// If the parent or previous sibling doesn't have any floats to add, don't bother.
if (!prev->m_floatingObjects)
return;
@@ -4641,15 +4681,15 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
return result;
}
-bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
+bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
{
if (!scrollsOverflow())
return false;
- return layer()->hitTestOverflowControls(result, roundedIntPoint(pointInContainer - toLayoutSize(accumulatedOffset)));
+ return layer()->hitTestOverflowControls(result, roundedIntPoint(locationInContainer - toLayoutSize(accumulatedOffset)));
}
-bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
LayoutPoint adjustedLocation(accumulatedOffset + location());
LayoutSize localOffset = toLayoutSize(adjustedLocation);
@@ -4659,21 +4699,21 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
LayoutRect overflowBox = visualOverflowRect();
flipForWritingMode(overflowBox);
overflowBox.moveBy(adjustedLocation);
- if (!pointInContainer.intersects(overflowBox))
+ if (!locationInContainer.intersects(overflowBox))
return false;
}
- if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, pointInContainer.point(), adjustedLocation)) {
- updateHitTestResult(result, pointInContainer.point() - localOffset);
+ if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, locationInContainer.point(), adjustedLocation)) {
+ updateHitTestResult(result, locationInContainer.point() - localOffset);
// FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
- if (!result.addNodeToRectBasedTestResult(node(), pointInContainer))
+ if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer))
return true;
}
// If we have clipping, then we can't have any spillout.
bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
bool useClip = (hasControlClip() || useOverflowClip);
- bool checkChildren = !useClip || (hasControlClip() ? pointInContainer.intersects(controlClipRect(adjustedLocation)) : pointInContainer.intersects(overflowClipRect(adjustedLocation, pointInContainer.region(), IncludeOverlayScrollbarSize)));
+ bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.intersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region(), IncludeOverlayScrollbarSize)));
if (checkChildren) {
// Hit test descendants first.
LayoutSize scrolledOffset(localOffset);
@@ -4682,14 +4722,14 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Hit test contents if we don't have columns.
if (!hasColumns()) {
- if (hitTestContents(request, result, pointInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
- updateHitTestResult(result, pointInContainer.point() - localOffset);
+ if (hitTestContents(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
+ updateHitTestResult(result, locationInContainer.point() - localOffset);
return true;
}
- if (hitTestAction == HitTestFloat && hitTestFloats(request, result, pointInContainer, toLayoutPoint(scrolledOffset)))
+ if (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, toLayoutPoint(scrolledOffset)))
return true;
- } else if (hitTestColumns(request, result, pointInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
- updateHitTestResult(result, flipForWritingMode(pointInContainer.point() - localOffset));
+ } else if (hitTestColumns(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
+ updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
return true;
}
}
@@ -4697,9 +4737,9 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Now hit test our background
if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
LayoutRect boundsRect(adjustedLocation, size());
- if (visibleToHitTesting() && pointInContainer.intersects(boundsRect)) {
- updateHitTestResult(result, flipForWritingMode(pointInContainer.point() - localOffset));
- if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
+ if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
+ updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
+ if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
return true;
}
}
@@ -4707,7 +4747,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
return false;
}
-bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
+bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
{
if (!m_floatingObjects)
return false;
@@ -4726,8 +4766,8 @@ bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& re
LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->x();
LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->y();
LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset));
- if (floatingObject->m_renderer->hitTest(request, result, pointInContainer, childPoint)) {
- updateHitTestResult(result, pointInContainer.point() - toLayoutSize(childPoint));
+ if (floatingObject->m_renderer->hitTest(request, result, locationInContainer, childPoint)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(childPoint));
return true;
}
}
@@ -4795,48 +4835,48 @@ private:
LayoutRect m_colRect;
};
-bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
// We need to do multiple passes, breaking up our hit testing into strips.
if (!hasColumns())
return false;
for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) {
- LayoutRect hitRect = pointInContainer.boundingBox();
+ LayoutRect hitRect = locationInContainer.boundingBox();
LayoutRect colRect = it.columnRect();
colRect.moveBy(accumulatedOffset);
- if (pointInContainer.intersects(colRect)) {
+ if (locationInContainer.intersects(colRect)) {
// The point is inside this column.
// Adjust accumulatedOffset to change where we hit test.
LayoutSize offset;
it.adjust(offset);
LayoutPoint finalLocation = accumulatedOffset + offset;
if (!result.isRectBasedTest() || colRect.contains(hitRect))
- return hitTestContents(request, result, pointInContainer, finalLocation, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(request, result, pointInContainer, finalLocation));
+ return hitTestContents(request, result, locationInContainer, finalLocation, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, finalLocation));
- hitTestContents(request, result, pointInContainer, finalLocation, hitTestAction);
+ hitTestContents(request, result, locationInContainer, finalLocation, hitTestAction);
}
}
return false;
}
-void RenderBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& pointInContainer) const
+void RenderBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const
{
for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) {
LayoutRect colRect = it.columnRect();
- if (colRect.contains(pointInContainer)) {
+ if (colRect.contains(locationInContainer)) {
it.adjust(offset);
return;
}
}
}
-bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
if (childrenInline() && !isTable()) {
// We have to hit-test our line boxes.
- if (m_lineBoxes.hitTest(this, request, result, pointInContainer, accumulatedOffset, hitTestAction))
+ if (m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction))
return true;
} else {
// Hit test our children.
@@ -4845,7 +4885,7 @@ bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
childHitTest = HitTestChildBlockBackground;
for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
LayoutPoint childPoint = flipForWritingModeForChild(child, accumulatedOffset);
- if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, pointInContainer, childPoint, childHitTest))
+ if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, locationInContainer, childPoint, childHitTest))
return true;
}
}
@@ -6851,11 +6891,11 @@ bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBou
// See if we're in the last region.
LayoutUnit pageOffset = offsetFromLogicalTopOfFirstPage() + logicalOffset;
- RenderRegion* region = enclosingRenderFlowThread()->renderRegionForLine(pageOffset, this);
+ RenderRegion* region = enclosingRenderFlowThread()->regionAtBlockOffset(pageOffset, this);
if (!region)
return false;
if (region->isLastRegion())
- return region->style()->regionOverflow() == BreakRegionOverflow
+ return region->isRenderRegionSet() || region->style()->regionOverflow() == BreakRegionOverflow
|| (pageBoundaryRule == IncludePageBoundary && pageOffset == region->offsetFromLogicalTopOfFirstPage());
return true;
}
@@ -6938,7 +6978,7 @@ LayoutUnit RenderBlock::pageLogicalTopForOffset(LayoutUnit offset) const
return 0;
return cumulativeOffset - roundToInt(cumulativeOffset - firstPageLogicalTop) % roundToInt(pageLogicalHeight);
}
- return enclosingRenderFlowThread()->regionLogicalTopForLine(cumulativeOffset);
+ return enclosingRenderFlowThread()->pageLogicalTopForOffset(cumulativeOffset);
}
LayoutUnit RenderBlock::pageLogicalHeightForOffset(LayoutUnit offset) const
@@ -6946,7 +6986,7 @@ LayoutUnit RenderBlock::pageLogicalHeightForOffset(LayoutUnit offset) const
RenderView* renderView = view();
if (!inRenderFlowThread())
return renderView->layoutState()->m_pageLogicalHeight;
- return enclosingRenderFlowThread()->regionLogicalHeightForLine(offset + offsetFromLogicalTopOfFirstPage());
+ return enclosingRenderFlowThread()->pageLogicalHeightForOffset(offset + offsetFromLogicalTopOfFirstPage());
}
LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule) const
@@ -6965,7 +7005,7 @@ LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, P
return remainingHeight;
}
- return enclosingRenderFlowThread()->regionRemainingLogicalHeightForLine(offset, pageBoundaryRule);
+ return enclosingRenderFlowThread()->pageRemainingLogicalHeightForOffset(offset, pageBoundaryRule);
}
LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins)
@@ -7172,7 +7212,7 @@ RenderRegion* RenderBlock::regionAtBlockOffset(LayoutUnit blockOffset) const
if (!flowThread || !flowThread->hasValidRegionInfo())
return 0;
- return flowThread->renderRegionForLine(offsetFromLogicalTopOfFirstPage() + blockOffset, true);
+ return flowThread->regionAtBlockOffset(offsetFromLogicalTopOfFirstPage() + blockOffset, true);
}
void RenderBlock::setStaticInlinePositionForChild(RenderBox* child, LayoutUnit blockOffset, LayoutUnit inlinePosition)
@@ -7329,6 +7369,8 @@ const char* RenderBlock::renderName() const
return "RenderBlock (generated)";
if (isRelPositioned())
return "RenderBlock (relative positioned)";
+ if (isStickyPositioned())
+ return "RenderBlock (sticky positioned)";
if (isRunIn())
return "RenderBlock (run-in)";
return "RenderBlock";
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index a31b26ed6..a33eeaf5b 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -29,16 +29,20 @@
#include "RenderBox.h"
#include "RenderLineBoxList.h"
#include "RootInlineBox.h"
+#include "TextBreakIterator.h"
#include "TextRun.h"
#include <wtf/OwnPtr.h>
#include <wtf/ListHashSet.h>
+#if ENABLE(CSS_EXCLUSIONS)
+#include "WrapShapeInfo.h"
+#endif
+
namespace WebCore {
class BidiContext;
class InlineIterator;
class LayoutStateMaintainer;
-class LazyLineBreakIterator;
class LineLayoutState;
class LineWidth;
class RenderInline;
@@ -48,6 +52,7 @@ struct BidiRun;
struct PaintInfo;
class LineInfo;
class RenderRubyRun;
+class TextLayout;
template <class Iterator, class Run> class BidiResolver;
template <class Run> class BidiRunList;
@@ -195,7 +200,7 @@ public:
: logicalWidth() - logicalRightOffsetForLine(position, firstLine, logicalHeight);
}
- LayoutUnit startAlignedOffsetForLine(RenderBox* child, LayoutUnit position, bool firstLine);
+ LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool firstLine);
LayoutUnit textIndentOffset() const;
virtual VisiblePosition positionForPoint(const LayoutPoint&);
@@ -229,7 +234,7 @@ public:
void adjustRectForColumns(LayoutRect&) const;
virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const;
- void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& pointInContainer) const;
+ void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const;
void addContinuationWithOutline(RenderInline*);
bool paintsContinuationOutline(RenderInline*);
@@ -396,6 +401,13 @@ public:
void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
#endif
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo() const
+ {
+ return style()->wrapShapeInside() && WrapShapeInfo::isWrapShapeInfoEnabledForRenderBlock(this) ? WrapShapeInfo::wrapShapeInfoForRenderBlock(this) : 0;
+ }
+#endif
+
protected:
virtual void willBeDestroyed();
@@ -431,7 +443,7 @@ protected:
virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual void computePreferredLogicalWidths();
@@ -485,6 +497,9 @@ protected:
virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
private:
+#if ENABLE(CSS_EXCLUSIONS)
+ void updateWrapShapeInfoAfterStyleChange(const BasicShape*, const BasicShape* oldWrapShape);
+#endif
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
@@ -692,7 +707,16 @@ private:
LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
// The following functions' implementations are in RenderBlockLineLayout.cpp.
- typedef std::pair<RenderText*, LazyLineBreakIterator> LineBreakIteratorInfo;
+ 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;
+ };
+
class LineBreaker {
public:
LineBreaker(RenderBlock* block)
@@ -701,7 +725,7 @@ private:
reset();
}
- InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, LineBreakIteratorInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines);
+ InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines);
bool lineWasHyphenated() { return m_hyphenated; }
const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
@@ -770,11 +794,11 @@ private:
LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
- virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
- virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
- bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
+ virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
+ virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
+ bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
- virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
+ virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
void computeInlinePreferredLogicalWidths();
void computeBlockPreferredLogicalWidths();
@@ -906,6 +930,7 @@ private:
bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
+ void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
bool quirkContainer() const { return m_quirkContainer; }
bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
bool marginBeforeQuirk() const { return m_marginBeforeQuirk; }
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index 55377d986..c0c3404ad 100755
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -36,7 +36,6 @@
#include "RenderRubyRun.h"
#include "RenderView.h"
#include "Settings.h"
-#include "TextBreakIterator.h"
#include "TrailingFloatsRootInlineBox.h"
#include "VerticalPositionCache.h"
#include "break_lines.h"
@@ -46,6 +45,10 @@
#include <wtf/Vector.h>
#include <wtf/unicode/CharacterNames.h>
+#if ENABLE(CSS_EXCLUSIONS)
+#include "WrapShapeInfo.h"
+#endif
+
#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
#include "SVGRootInlineBox.h"
@@ -70,9 +73,21 @@ public:
, m_left(0)
, m_right(0)
, m_availableWidth(0)
+#if ENABLE(CSS_EXCLUSIONS)
+ , m_segment(0)
+#endif
, m_isFirstLine(isFirstLine)
{
ASSERT(block);
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo = m_block->wrapShapeInfo();
+ // FIXME: Bug 91878: Add support for multiple segments, currently we only support one
+ if (wrapShapeInfo && wrapShapeInfo->lineState() == WrapShapeInfo::LINE_INSIDE_SHAPE) {
+ // All interior shape positions should have at least one segment
+ ASSERT(wrapShapeInfo->hasSegments());
+ m_segment = &wrapShapeInfo->segments()[0];
+ }
+#endif
updateAvailableWidth();
}
#if ENABLE(SUBPIXEL_LAYOUT)
@@ -114,6 +129,9 @@ private:
float m_left;
float m_right;
float m_availableWidth;
+#if ENABLE(CSS_EXCLUSIONS)
+ const LineSegment* m_segment;
+#endif
bool m_isFirstLine;
};
@@ -138,6 +156,13 @@ inline void LineWidth::updateAvailableWidth()
m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine, logicalHeight);
m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine, logicalHeight);
+#if ENABLE(CSS_EXCLUSIONS)
+ if (m_segment) {
+ m_left = max<float>(m_segment->logicalLeft, m_left);
+ m_right = min<float>(m_segment->logicalRight, m_right);
+ }
+#endif
+
computeAvailableWidthFromLeftAndRight();
}
@@ -397,9 +422,9 @@ static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRo
static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
{
if (o->isText()) {
- if (o->preferredLogicalWidthsDirty() && (o->isCounter() || o->isQuote()))
- toRenderText(o)->computePreferredLogicalWidths(0); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.
- toRenderText(o)->dirtyLineBoxes(fullLayout);
+ RenderText* renderText = toRenderText(o);
+ renderText->updateTextIfNeeded(); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.
+ renderText->dirtyLineBoxes(fullLayout);
} else
toRenderInline(o)->dirtyLineBoxes(fullLayout);
}
@@ -777,7 +802,15 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
// box is only affected if it is the first child of its parent element."
bool firstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->firstChild() != this);
float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight);
- float availableLogicalWidth = pixelSnappedLogicalRightOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight) - logicalLeft;
+ float logicalRight = pixelSnappedLogicalRightOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight);
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo = this->wrapShapeInfo();
+ if (wrapShapeInfo && wrapShapeInfo->lineState() == WrapShapeInfo::LINE_INSIDE_SHAPE) {
+ logicalLeft = max<float>(roundToInt(wrapShapeInfo->segments()[0].logicalLeft), logicalLeft);
+ logicalRight = min<float>(floorToInt(wrapShapeInfo->segments()[0].logicalRight), logicalRight);
+ }
+#endif
+ float availableLogicalWidth = logicalRight - logicalLeft;
bool needsWordSpacing = false;
float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
@@ -888,12 +921,12 @@ static void setStaticPositions(RenderBlock* block, RenderBox* child)
// A relative positioned inline encloses us. In this case, we also have to determine our
// position as though we were an inline. Set |staticInlinePosition| and |staticBlockPosition| on the relative positioned
// inline so that we can obtain the value later.
- toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startAlignedOffsetForLine(child, blockHeight, false));
+ toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startAlignedOffsetForLine(blockHeight, false));
toRenderInline(containerBlock)->layer()->setStaticBlockPosition(blockHeight);
}
if (child->style()->isOriginalDisplayInlineType())
- block->setStaticInlinePositionForChild(child, blockHeight, block->startAlignedOffsetForLine(child, blockHeight, false));
+ block->setStaticInlinePositionForChild(child, blockHeight, block->startAlignedOffsetForLine(blockHeight, false));
else
block->setStaticInlinePositionForChild(child, blockHeight, block->startOffsetForContent(blockHeight));
child->layer()->setStaticBlockPosition(blockHeight);
@@ -1240,6 +1273,15 @@ void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInli
repaintDirtyFloats(layoutState.floats());
}
+RenderBlock::RenderTextInfo::RenderTextInfo()
+ : m_text(0)
+{
+}
+
+RenderBlock::RenderTextInfo::~RenderTextInfo()
+{
+}
+
void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
{
RenderStyle* styleToUse = style();
@@ -1247,11 +1289,18 @@ void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, Inlin
LineMidpointState& lineMidpointState = resolver.midpointState();
InlineIterator end = resolver.position();
bool checkForEndLineMatch = layoutState.endLine();
- LineBreakIteratorInfo lineBreakIteratorInfo;
+ RenderTextInfo renderTextInfo;
VerticalPositionCache verticalPositionCache;
LineBreaker lineBreaker(this);
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo = this->wrapShapeInfo();
+ // Move to the top of the shape inside to begin layout
+ if (wrapShapeInfo && logicalHeight() < wrapShapeInfo->shapeTop())
+ setLogicalHeight(wrapShapeInfo->shapeTop());
+#endif
+
while (!end.atEnd()) {
// FIXME: Is this check necessary before the first iteration or can it be moved to the end?
if (checkForEndLineMatch) {
@@ -1270,7 +1319,13 @@ void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, Inlin
const InlineIterator oldEnd = end;
bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
FloatingObject* lastFloatFromPreviousLine = (m_floatingObjects && !m_floatingObjects->set().isEmpty()) ? m_floatingObjects->set().last() : 0;
- end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), lineBreakIteratorInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines);
+#if ENABLE(CSS_EXCLUSIONS)
+ // FIXME: Bug 89993: If the wrap shape comes from a parent, we will need to adjust
+ // the height coordinate
+ if (wrapShapeInfo)
+ wrapShapeInfo->computeSegmentsForLine(logicalHeight());
+#endif
+ end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines);
if (resolver.position().atEnd()) {
// FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
// Once BidiRunList is separated from BidiResolver this will not be needed.
@@ -1970,11 +2025,14 @@ static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObjec
return false;
}
-static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace)
+static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, TextLayout* layout = 0)
{
if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
return text->width(from, len, font, xPos);
+ if (layout)
+ return Font::width(*layout, from, len);
+
TextRun run = RenderBlock::constructTextRun(text, font, text->characters() + from, len, text->style());
run.setCharactersLength(text->textLength() - from);
ASSERT(run.charactersLength() >= run.length());
@@ -2136,8 +2194,7 @@ void RenderBlock::LineBreaker::reset()
m_clear = CNONE;
}
-InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo,
- LineBreakIteratorInfo& lineBreakIteratorInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines)
+InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines)
{
reset();
@@ -2376,6 +2433,14 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
ASSERT(current.m_pos == t->textLength());
}
+ if (renderTextInfo.m_text != t) {
+ t->updateTextIfNeeded();
+ renderTextInfo.m_text = t;
+ renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
+ renderTextInfo.m_lineBreakIterator.reset(t->characters(), t->textLength(), style->locale());
+ }
+ TextLayout* textLayout = renderTextInfo.m_layout.get();
+
for (; current.m_pos < t->textLength(); current.fastIncrementInTextNode()) {
bool previousCharacterIsSpace = currentCharacterIsSpace;
bool previousCharacterIsWS = currentCharacterIsWS;
@@ -2397,16 +2462,11 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
if ((breakAll || breakWords) && !midWordBreak) {
wrapW += charWidth;
bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && current.m_pos + 1 < t->textLength() && U16_IS_TRAIL(t->characters()[current.m_pos + 1]);
- charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace);
+ charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, textLayout);
midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth();
}
- if ((lineBreakIteratorInfo.first != t) || (lineBreakIteratorInfo.second.string() != t->characters())) {
- lineBreakIteratorInfo.first = t;
- lineBreakIteratorInfo.second.reset(t->characters(), t->textLength(), style->locale());
- }
-
- bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(lineBreakIteratorInfo.second, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
+ bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
&& (style->hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
if (betweenWords || midWordBreak) {
@@ -2428,9 +2488,9 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
float additionalTmpW;
if (wordTrailingSpaceWidth && currentCharacterIsSpace)
- additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
+ additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
else
- additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+ additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + lastSpaceWordSpacing;
width.addUncommittedWidth(additionalTmpW);
if (!appliedStartWidth) {
width.addUncommittedWidth(inlineLogicalWidth(current.m_obj, true, false));
@@ -2447,7 +2507,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
// as candidate width for this line.
bool lineWasTooWide = false;
if (width.fitsOnLine() && currentCharacterIsWS && currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
- float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + (applyWordSpacing ? wordSpacing : 0);
+ float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + (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,
@@ -2573,7 +2633,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
}
// IMPORTANT: current.m_pos is > length here!
- float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+ float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + lastSpaceWordSpacing;
width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(current.m_obj, !appliedStartWidth, includeEndWidth));
includeEndWidth = false;
@@ -2830,7 +2890,7 @@ bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObjec
return true;
}
-LayoutUnit RenderBlock::startAlignedOffsetForLine(RenderBox* child, LayoutUnit position, bool firstLine)
+LayoutUnit RenderBlock::startAlignedOffsetForLine(LayoutUnit position, bool firstLine)
{
ETextAlign textAlign = style()->textAlign();
@@ -2838,15 +2898,13 @@ LayoutUnit RenderBlock::startAlignedOffsetForLine(RenderBox* child, LayoutUnit p
return startOffsetForLine(position, firstLine);
// updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
- float logicalLeft;
- float availableLogicalWidth;
- logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
- availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
- float totalLogicalWidth = logicalWidthForChild(child);
+ float totalLogicalWidth = 0;
+ float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
+ float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
if (!style()->isLeftToRightDirection())
- return logicalWidth() - (logicalLeft + totalLogicalWidth);
+ return logicalWidth() - logicalLeft;
return logicalLeft;
}
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index f16457b5e..792b9c28b 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -134,16 +134,7 @@ void RenderBox::willBeDestroyed()
{
clearOverrideSize();
- if (style()) {
- RenderBlock::removePercentHeightDescendantIfNeeded(this);
-
- if (RenderView* view = this->view()) {
- if (FrameView* frameView = view->frameView()) {
- if (style()->position() == FixedPosition)
- frameView->removeFixedObject(this);
- }
- }
- }
+ RenderBlock::removePercentHeightDescendantIfNeeded(this);
RenderBoxModelObject::willBeDestroyed();
}
@@ -205,17 +196,6 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl
} else if (newStyle && isBody())
view()->repaint();
- if (FrameView *frameView = view()->frameView()) {
- bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition;
- bool oldStyleIsFixed = oldStyle && oldStyle->position() == FixedPosition;
- if (newStyleIsFixed != oldStyleIsFixed) {
- if (newStyleIsFixed)
- frameView->addFixedObject(this);
- else
- frameView->removeFixedObject(this);
- }
- }
-
RenderBoxModelObject::styleWillChange(diff, newStyle);
}
@@ -433,7 +413,7 @@ void RenderBox::updateLayerTransform()
layer()->updateTransform();
}
-LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
{
RenderStyle* styleToUse = style();
if (!styleToUse->logicalMaxWidth().isUndefined())
@@ -441,7 +421,7 @@ LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWi
return max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, availableWidth, cb, region, offsetFromLogicalTopOfFirstPage));
}
-LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight)
+LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight) const
{
RenderStyle* styleToUse = style();
if (!styleToUse->logicalMaxHeight().isUndefined()) {
@@ -758,25 +738,25 @@ LayoutUnit RenderBox::computeContentBoxLogicalHeight(LayoutUnit height) const
}
// Hit Testing
-bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
LayoutPoint adjustedLocation = accumulatedOffset + location();
// Check kids first.
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (!child->hasLayer() && child->nodeAtPoint(request, result, pointInContainer, adjustedLocation, action)) {
- updateHitTestResult(result, pointInContainer.point() - toLayoutSize(adjustedLocation));
+ if (!child->hasLayer() && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
return true;
}
}
// 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(pointInContainer.region());
+ LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
boundsRect.moveBy(adjustedLocation);
- if (visibleToHitTesting() && action == HitTestForeground && pointInContainer.intersects(boundsRect)) {
- updateHitTestResult(result, pointInContainer.point() - toLayoutSize(adjustedLocation));
- if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
+ if (visibleToHitTesting() && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+ if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
return true;
}
@@ -1171,7 +1151,7 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region
return clipRect;
}
-LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
{
RenderRegion* containingBlockRegion = 0;
LayoutUnit logicalTopPosition = logicalTop();
@@ -1374,9 +1354,6 @@ const RenderObject* RenderBox::pushMappingToContainer(const RenderBoxModelObject
void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
- // We don't expect absoluteToLocal() to be called during layout (yet)
- ASSERT(!view() || !view()->layoutStateEnabled());
-
bool isFixedPos = style()->position() == FixedPosition;
bool hasTransform = hasLayer() && layer()->transform();
if (hasTransform) {
@@ -1577,7 +1554,7 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, La
if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this);
- else if ((position == RelativePosition) && layer()) {
+ else if ((position == RelativePosition || position == StickyPosition) && 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
// right dirty rect. Since this is called from RenderObject::setStyle, the relative position
@@ -1640,15 +1617,26 @@ void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
void RenderBox::computeLogicalWidth()
{
- computeLogicalWidthInRegion();
+ LogicalExtentComputedValues computedValues;
+ computeLogicalWidthInRegion(computedValues);
+
+ setLogicalWidth(computedValues.m_extent);
+ setLogicalLeft(computedValues.m_position);
+ setMarginStart(computedValues.m_margins.m_start);
+ setMarginEnd(computedValues.m_margins.m_end);
}
-void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
{
+ computedValues.m_extent = logicalWidth();
+ computedValues.m_position = logicalLeft();
+ computedValues.m_margins.m_start = marginStart();
+ computedValues.m_margins.m_end = marginEnd();
+
if (isOutOfFlowPositioned()) {
// FIXME: This calculation is not patched for block-flow yet.
// https://bugs.webkit.org/show_bug.cgi?id=46500
- computePositionedLogicalWidth(region, offsetFromLogicalTopOfFirstPage);
+ computePositionedLogicalWidth(computedValues, region, offsetFromLogicalTopOfFirstPage);
return;
}
@@ -1661,7 +1649,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off
// FIXME: Account for block-flow in flexible boxes.
// https://bugs.webkit.org/show_bug.cgi?id=46418
if (hasOverrideWidth() && parent()->isFlexibleBoxIncludingDeprecated()) {
- setLogicalWidth(overrideLogicalContentWidth() + borderAndPaddingLogicalWidth());
+ computedValues.m_extent = overrideLogicalContentWidth() + borderAndPaddingLogicalWidth();
return;
}
@@ -1672,7 +1660,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off
bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching);
RenderStyle* styleToUse = style();
- Length logicalWidthLength = (treatAsReplaced) ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
+ Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
RenderBlock* cb = containingBlock();
LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region, offsetFromLogicalTopOfFirstPage));
@@ -1684,44 +1672,53 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off
if (isInline() && !isInlineBlockOrInlineTable()) {
// just calculate margins
RenderView* renderView = view();
- setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView));
- setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView));
+ computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
+ computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
if (treatAsReplaced)
- setLogicalWidth(max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth()));
+ computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
return;
}
// Width calculations
if (treatAsReplaced)
- setLogicalWidth(logicalWidthLength.value() + borderAndPaddingLogicalWidth());
+ computedValues.m_extent = logicalWidthLength.value() + borderAndPaddingLogicalWidth();
else {
LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
- setLogicalWidth(constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage));
+ computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
}
// Fieldsets are currently the only objects that stretch to their minimum width.
if (stretchesToMinIntrinsicLogicalWidth())
- setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth()));
+ computedValues.m_extent = max(computedValues.m_extent, minPreferredLogicalWidth());
// Margin calculations.
if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
RenderView* renderView = view();
- setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView));
- setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView));
+ 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, offsetFromLogicalTopOfFirstPage);
- computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth());
+ 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);
}
- if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (logicalWidth() + marginStart() + marginEnd())
- && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated())
- cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this));
+ if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end)
+ && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated()) {
+ LayoutUnit newMargin = containerLogicalWidth - computedValues.m_extent - cb->marginStartForChild(this);
+ bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
+ if (hasInvertedDirection)
+ computedValues.m_margins.m_start = newMargin;
+ else
+ computedValues.m_margins.m_end = newMargin;
+ }
}
LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, LayoutUnit availableLogicalWidth,
- const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+ const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
{
RenderStyle* styleToUse = style();
Length logicalWidth;
@@ -1820,7 +1817,7 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
return false;
}
-void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth)
+void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
{
const RenderStyle* containingBlockStyle = containingBlock->style();
Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
@@ -1829,8 +1826,8 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
if (isFloating() || isInline()) {
// Inline blocks/tables and floats don't have their margins increased.
- containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView));
- containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView));
+ marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
+ marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
return;
}
@@ -1841,15 +1838,15 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView);
LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView);
LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
- containingBlock->setMarginStartForChild(this, centeredMarginBoxStart + marginStartWidth);
- containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this) + marginEndWidth);
+ marginStart = centeredMarginBoxStart + marginStartWidth;
+ marginEnd = containerWidth - 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) {
- containingBlock->setMarginStartForChild(this, valueForLength(marginStartLength, containerWidth, renderView));
- containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this));
+ marginStart = valueForLength(marginStartLength, containerWidth, renderView);
+ marginEnd = containerWidth - childWidth - marginStart;
return;
}
@@ -1857,15 +1854,15 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
|| (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
- containingBlock->setMarginEndForChild(this, valueForLength(marginEndLength, containerWidth, renderView));
- containingBlock->setMarginStartForChild(this, containerWidth - childWidth - containingBlock->marginEndForChild(this));
+ marginEnd = valueForLength(marginEndLength, containerWidth, renderView);
+ marginStart = containerWidth - 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.
- containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView));
- containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView));
+ marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
+ marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
}
RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
@@ -1887,21 +1884,12 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout
|| isTableCell() || !isBlockFlow() || isRenderFlowThread())
return 0;
- // FIXME: It's gross to cast away the const, but it would be a huge refactoring to
- // change all width computation to avoid updating any member variables, and it would be pretty lame to
- // make all the variables mutable as well.
RenderFlowThread* flowThread = enclosingRenderFlowThread();
if (flowThread->style()->writingMode() != style()->writingMode())
return 0;
- LayoutUnit oldLogicalWidth = logicalWidth();
- LayoutUnit oldLogicalLeft = logicalLeft();
- LayoutUnit oldMarginStart = marginStart();
- LayoutUnit oldMarginEnd = marginEnd();
-
- RenderBox* mutableBox = const_cast<RenderBox*>(this);
-
- mutableBox->computeLogicalWidthInRegion(region, offsetFromLogicalTopOfFirstPage);
+ LogicalExtentComputedValues computedValues;
+ computeLogicalWidthInRegion(computedValues, region, offsetFromLogicalTopOfFirstPage);
// Now determine the insets based off where this object is supposed to be positioned.
RenderBlock* cb = containingBlock();
@@ -1911,22 +1899,16 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout
LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
- LayoutUnit marginStartInRegion = marginStart();
- LayoutUnit startMarginDelta = marginStartInRegion - oldMarginStart;
- LayoutUnit logicalWidthInRegion = logicalWidth();
- LayoutUnit logicalLeftInRegion = logicalLeft();
- LayoutUnit widthDelta = logicalWidthInRegion - oldLogicalWidth;
- LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - oldLogicalLeft : startMarginDelta;
+ 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 - (oldLogicalLeft + oldLogicalWidth);
+ LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth());
LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
- // Set our values back.
- mutableBox->setLogicalWidth(oldLogicalWidth);
- mutableBox->setLogicalLeft(oldLogicalLeft);
- mutableBox->setMarginStart(oldMarginStart);
- mutableBox->setMarginEnd(oldMarginEnd);
-
LayoutUnit logicalLeftOffset = 0;
if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
@@ -1953,26 +1935,74 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout
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;
+}
+
void RenderBox::computeLogicalHeight()
{
+ LogicalExtentComputedValues computedValues;
+ computeLogicalHeight(computedValues);
+
+ setLogicalHeight(computedValues.m_extent);
+ setLogicalTop(computedValues.m_position);
+ setMarginBefore(computedValues.m_margins.m_before);
+ setMarginAfter(computedValues.m_margins.m_after);
+}
+
+void RenderBox::computeLogicalHeight(LogicalExtentComputedValues& computedValues) const
+{
+ computedValues.m_extent = logicalHeight();
+ computedValues.m_position = logicalTop();
+
// Cell height is managed by the table and inline non-replaced elements do not support a height property.
if (isTableCell() || (isInline() && !isReplaced()))
return;
Length h;
if (isOutOfFlowPositioned())
- computePositionedLogicalHeight();
+ computePositionedLogicalHeight(computedValues);
else {
RenderBlock* cb = containingBlock();
bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
- if (!hasPerpendicularContainingBlock)
- computeBlockDirectionMargins(cb);
+ 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);
+ }
// For tables, calculate margins only.
if (isTable()) {
- if (hasPerpendicularContainingBlock)
- computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), logicalHeight());
+ if (hasPerpendicularContainingBlock) {
+ bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
+ computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), logicalHeight(),
+ shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
+ shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
+ }
return;
}
@@ -2018,10 +2048,14 @@ void RenderBox::computeLogicalHeight()
heightResult = h.value() + borderAndPaddingLogicalHeight();
}
- setLogicalHeight(heightResult);
+ computedValues.m_extent = heightResult;
- if (hasPerpendicularContainingBlock)
- computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), 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);
+ }
}
// WinIE quirk: The <html> block always fills the entire canvas in quirks mode. The <body> always fills the
@@ -2045,15 +2079,15 @@ void RenderBox::computeLogicalHeight()
visHeight = view()->viewWidth();
}
if (isRoot())
- setLogicalHeight(max(logicalHeight(), visHeight - margins));
+ computedValues.m_extent = max(computedValues.m_extent, visHeight - margins);
else {
LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
- setLogicalHeight(max(logicalHeight(), visHeight - marginsBordersPadding));
+ computedValues.m_extent = max(computedValues.m_extent, visHeight - marginsBordersPadding);
}
}
}
-LayoutUnit RenderBox::computeLogicalHeightUsing(SizeType heightType, const Length& height)
+LayoutUnit RenderBox::computeLogicalHeightUsing(SizeType heightType, const Length& height) const
{
LayoutUnit logicalHeight = computeContentLogicalHeightUsing(heightType, height);
if (logicalHeight != -1)
@@ -2066,10 +2100,10 @@ LayoutUnit RenderBox::computeLogicalClientHeight(SizeType heightType, const Leng
LayoutUnit heightIncludingScrollbar = computeContentLogicalHeightUsing(heightType, height);
if (heightIncludingScrollbar == -1)
return -1;
- return std::max(LayoutUnit(0), computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight());
+ return std::max<LayoutUnit>(0, computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight());
}
-LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, const Length& height)
+LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, const Length& height) const
{
if (height.isAuto())
return heightType == MinSize ? 0 : -1;
@@ -2082,7 +2116,7 @@ LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, cons
return -1;
}
-LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height)
+LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
{
LayoutUnit result = -1;
@@ -2098,7 +2132,7 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height)
break;
skippedAutoHeightContainingBlock = true;
cb = cb->containingBlock();
- cb->addPercentHeightDescendant(this);
+ cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
}
RenderStyle* cbstyle = cb->style();
@@ -2138,9 +2172,11 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height)
result = max<LayoutUnit>(0, contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight());
} else if (cbstyle->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight) {
// We need to recur and compute the percentage height for our containing block.
- result = cb->computePercentageLogicalHeight(cbstyle->logicalHeight());
- if (result != -1)
- result = cb->computeContentBoxLogicalHeight(result);
+ LayoutUnit heightWithScrollbar = cb->computePercentageLogicalHeight(cbstyle->logicalHeight());
+ if (heightWithScrollbar != -1) {
+ LayoutUnit contentBoxHeightWithScrollbar = cb->computeContentBoxLogicalHeight(heightWithScrollbar);
+ result = max<LayoutUnit>(0, contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight());
+ }
} else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || 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.
@@ -2270,10 +2306,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType sizeType, Lengt
cb = cb->containingBlock();
}
}
- availableHeight = computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight));
- if (cb->isBox() && cb->style()->logicalHeight().isFixed())
- availableHeight = max<LayoutUnit>(0, availableHeight - toRenderBox(cb)->scrollbarLogicalHeight());
- return availableHeight;
+ return computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight));
}
case ViewportPercentageWidth:
case ViewportPercentageHeight:
@@ -2291,9 +2324,6 @@ LayoutUnit RenderBox::availableLogicalHeight() const
LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const
{
- if (h.isFixed())
- return computeContentBoxLogicalHeight(h.value());
-
if (isRenderView())
return isHorizontalWritingMode() ? toRenderView(this)->frameView()->visibleHeight() : toRenderView(this)->frameView()->visibleWidth();
@@ -2303,19 +2333,16 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const
if (isTableCell() && (h.isAuto() || h.isPercent()))
return overrideLogicalContentHeight();
- if (h.isPercent()) {
- LayoutUnit availableHeight;
- // https://bugs.webkit.org/show_bug.cgi?id=64046
- // For absolutely positioned elements whose containing block is based on a block-level element,
- // the percentage is calculated with respect to the height of the padding box of that element
- if (isOutOfFlowPositioned())
- availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
- else
- availableHeight = containingBlock()->availableLogicalHeight();
+ if (h.isPercent() && isOutOfFlowPositioned()) {
+ LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
return computeContentBoxLogicalHeight(valueForLength(h, availableHeight));
}
- // FIXME: We can't just check top/bottom here.
+ LayoutUnit heightIncludingScrollbar = computeContentLogicalHeightUsing(MainOrPreferredSize, h);
+ if (heightIncludingScrollbar != -1)
+ return std::max<LayoutUnit>(0, computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight());
+
+ // FIXME: Check logicalTop/logicalBottom here to correctly handle vertical writing-mode.
// https://bugs.webkit.org/show_bug.cgi?id=46500
if (isRenderBlock() && isOutOfFlowPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this));
@@ -2329,13 +2356,13 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const
return containingBlock()->availableLogicalHeight();
}
-void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock)
+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.
- setMarginBefore(0);
- setMarginAfter(0);
+ marginBefore = 0;
+ marginAfter = 0;
return;
}
@@ -2344,8 +2371,17 @@ void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock)
LayoutUnit cw = containingBlockLogicalWidthForContent();
RenderView* renderView = view();
RenderStyle* containingBlockStyle = containingBlock->style();
- containingBlock->setMarginBeforeForChild(this, minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView));
- containingBlock->setMarginAfterForChild(this, minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView));
+ 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);
+ containingBlock->setMarginBeforeForChild(this, marginBefore);
+ containingBlock->setMarginAfterForChild(this, marginAfter);
}
LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region,
@@ -2496,10 +2532,10 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh
}
}
-void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
{
if (isReplaced()) {
- computePositionedLogicalWidthReplaced(); // FIXME: Patch for regions when we add replaced element support.
+ computePositionedLogicalWidthReplaced(computedValues); // FIXME: Patch for regions when we add replaced element support.
return;
}
@@ -2534,8 +2570,6 @@ void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit o
const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
- LayoutUnit& marginLogicalLeftAlias = m_marginBox.mutableLogicalLeft(style()->writingMode());
- LayoutUnit& marginLogicalRightAlias = m_marginBox.mutableLogicalRight(style()->writingMode());
Length logicalLeftLength = style()->logicalLeft();
Length logicalRightLength = style()->logicalRight();
@@ -2569,70 +2603,57 @@ void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit o
computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
// Calculate constraint equation values for 'width' case.
- LayoutUnit logicalWidthResult;
- LayoutUnit logicalLeftResult;
computePositionedLogicalWidthUsing(MainOrPreferredSize, style()->logicalWidth(), containerBlock, containerDirection,
containerLogicalWidth, bordersPlusPadding,
logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
- logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
- setLogicalWidth(logicalWidthResult);
- setLogicalLeft(logicalLeftResult);
+ computedValues);
// Calculate constraint equation values for 'max-width' case.
if (!style()->logicalMaxWidth().isUndefined()) {
- LayoutUnit maxLogicalWidth;
- LayoutUnit maxMarginLogicalLeft;
- LayoutUnit maxMarginLogicalRight;
- LayoutUnit maxLogicalLeftPos;
+ LogicalExtentComputedValues maxValues;
computePositionedLogicalWidthUsing(MaxSize, style()->logicalMaxWidth(), containerBlock, containerDirection,
containerLogicalWidth, bordersPlusPadding,
logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
- maxLogicalWidth, maxMarginLogicalLeft, maxMarginLogicalRight, maxLogicalLeftPos);
+ maxValues);
- if (logicalWidth() > maxLogicalWidth) {
- setLogicalWidth(maxLogicalWidth);
- marginLogicalLeftAlias = maxMarginLogicalLeft;
- marginLogicalRightAlias = maxMarginLogicalRight;
- setLogicalLeft(maxLogicalLeftPos);
+ if (computedValues.m_extent > maxValues.m_extent) {
+ computedValues.m_extent = maxValues.m_extent;
+ computedValues.m_position = maxValues.m_position;
+ computedValues.m_margins.m_start = maxValues.m_margins.m_start;
+ computedValues.m_margins.m_end = maxValues.m_margins.m_end;
}
}
// Calculate constraint equation values for 'min-width' case.
if (!style()->logicalMinWidth().isZero()) {
- LayoutUnit minLogicalWidth;
- LayoutUnit minMarginLogicalLeft;
- LayoutUnit minMarginLogicalRight;
- LayoutUnit minLogicalLeftPos;
+ LogicalExtentComputedValues minValues;
computePositionedLogicalWidthUsing(MinSize, style()->logicalMinWidth(), containerBlock, containerDirection,
containerLogicalWidth, bordersPlusPadding,
logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
- minLogicalWidth, minMarginLogicalLeft, minMarginLogicalRight, minLogicalLeftPos);
+ minValues);
- if (logicalWidth() < minLogicalWidth) {
- setLogicalWidth(minLogicalWidth);
- marginLogicalLeftAlias = minMarginLogicalLeft;
- marginLogicalRightAlias = minMarginLogicalRight;
- setLogicalLeft(minLogicalLeftPos);
+ if (computedValues.m_extent < minValues.m_extent) {
+ computedValues.m_extent = minValues.m_extent;
+ computedValues.m_position = minValues.m_position;
+ computedValues.m_margins.m_start = minValues.m_margins.m_start;
+ computedValues.m_margins.m_end = minValues.m_margins.m_end;
}
}
- if (stretchesToMinIntrinsicLogicalWidth() && logicalWidth() < minPreferredLogicalWidth() - bordersPlusPadding) {
+ if (stretchesToMinIntrinsicLogicalWidth() && computedValues.m_extent < minPreferredLogicalWidth() - bordersPlusPadding) {
computePositionedLogicalWidthUsing(MainOrPreferredSize, Length(minPreferredLogicalWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection,
containerLogicalWidth, bordersPlusPadding,
logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
- logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
- setLogicalWidth(logicalWidthResult);
- setLogicalLeft(logicalLeftResult);
+ computedValues);
}
- // Put logicalWidth() into correct form.
- setLogicalWidth(logicalWidth() + bordersPlusPadding);
+ computedValues.m_extent += bordersPlusPadding;
// Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
if (inRenderFlowThread() && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
- LayoutUnit logicalLeftPos = logicalLeft();
+ LayoutUnit logicalLeftPos = computedValues.m_position;
const RenderBlock* cb = toRenderBlock(containerBlock);
LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
@@ -2641,7 +2662,7 @@ void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit o
RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
if (boxInfo) {
logicalLeftPos += boxInfo->logicalLeft();
- setLogicalLeft(logicalLeftPos);
+ computedValues.m_position = logicalLeftPos;
}
}
}
@@ -2661,7 +2682,7 @@ static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const
void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
- LayoutUnit& logicalWidthValue, LayoutUnit& marginLogicalLeftValue, LayoutUnit& marginLogicalRightValue, LayoutUnit& logicalLeftPos)
+ LogicalExtentComputedValues& computedValues) const
{
if (widthSizeType == MinSize && logicalWidth.isAuto())
logicalWidth = Length(0, Fixed);
@@ -2676,6 +2697,8 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt
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) {
/*-----------------------------------------------------------------------*\
@@ -2694,9 +2717,9 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt
// case because the value is not used for any further calculations.
logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ computedValues.m_extent = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
- const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
// Margins are now the only unknown
if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
@@ -2791,8 +2814,8 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt
LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
LayoutUnit availableWidth = availableSpace - logicalRightValue;
- logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
- logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue);
+ computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth);
+ 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);
@@ -2801,19 +2824,19 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt
LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
LayoutUnit availableWidth = availableSpace - logicalLeftValue;
- logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
+ computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth);
} else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 4: (solve for left)
- logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
- logicalLeftValue = availableSpace - (logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
+ computedValues.m_extent = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView));
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 5: (solve for width)
logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalWidthValue = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
+ computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
} else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 6: (no need solve for right)
logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
- logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ computedValues.m_extent = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
}
}
@@ -2828,13 +2851,13 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt
InlineFlowBox* firstLine = flow->firstLineBox();
InlineFlowBox* lastLine = flow->lastLineBox();
if (firstLine && lastLine && firstLine != lastLine) {
- logicalLeftPos = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
+ computedValues.m_position = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
return;
}
}
- logicalLeftPos = logicalLeftValue + marginLogicalLeftValue;
- computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidthValue, containerBlock, containerLogicalWidth);
+ computedValues.m_position = logicalLeftValue + marginLogicalLeftValue;
+ computeLogicalLeftPositionedOffset(computedValues.m_position, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
}
static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock)
@@ -2851,10 +2874,10 @@ static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom
logicalTop.setValue(Fixed, staticLogicalTop);
}
-void RenderBox::computePositionedLogicalHeight()
+void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& computedValues) const
{
if (isReplaced()) {
- computePositionedLogicalHeightReplaced();
+ computePositionedLogicalHeightReplaced(computedValues);
return;
}
@@ -2874,9 +2897,6 @@ void RenderBox::computePositionedLogicalHeight()
const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
const Length marginBefore = styleToUse->marginBefore();
const Length marginAfter = styleToUse->marginAfter();
- LayoutUnit& marginBeforeAlias = m_marginBox.mutableBefore(styleToUse->writingMode());
- LayoutUnit& marginAfterAlias = m_marginBox.mutableAfter(styleToUse->writingMode());
-
Length logicalTopLength = styleToUse->logicalTop();
Length logicalBottomLength = styleToUse->logicalBottom();
@@ -2901,62 +2921,52 @@ void RenderBox::computePositionedLogicalHeight()
// Calculate the static distance if needed.
computeBlockStaticDistance(logicalTopLength, logicalBottomLength, this, containerBlock);
- LayoutUnit logicalHeightResult; // Needed to compute overflow.
- LayoutUnit logicalTopPos;
-
// Calculate constraint equation values for 'height' case.
computePositionedLogicalHeightUsing(MainOrPreferredSize, styleToUse->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
- logicalHeightResult, marginBeforeAlias, marginAfterAlias, logicalTopPos);
- setLogicalTop(logicalTopPos);
+ computedValues);
// Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
// see FIXME 2
// Calculate constraint equation values for 'max-height' case.
if (!styleToUse->logicalMaxHeight().isUndefined()) {
- LayoutUnit maxLogicalHeight;
- LayoutUnit maxMarginBefore;
- LayoutUnit maxMarginAfter;
- LayoutUnit maxLogicalTopPos;
+ LogicalExtentComputedValues maxValues;
computePositionedLogicalHeightUsing(MaxSize, styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
- maxLogicalHeight, maxMarginBefore, maxMarginAfter, maxLogicalTopPos);
+ maxValues);
- if (logicalHeightResult > maxLogicalHeight) {
- logicalHeightResult = maxLogicalHeight;
- marginBeforeAlias = maxMarginBefore;
- marginAfterAlias = maxMarginAfter;
- setLogicalTop(maxLogicalTopPos);
+ if (computedValues.m_extent > maxValues.m_extent) {
+ computedValues.m_extent = maxValues.m_extent;
+ computedValues.m_position = maxValues.m_position;
+ computedValues.m_margins.m_before = maxValues.m_margins.m_before;
+ computedValues.m_margins.m_after = maxValues.m_margins.m_after;
}
}
// Calculate constraint equation values for 'min-height' case.
if (!styleToUse->logicalMinHeight().isZero()) {
- LayoutUnit minLogicalHeight;
- LayoutUnit minMarginBefore;
- LayoutUnit minMarginAfter;
- LayoutUnit minLogicalTopPos;
+ LogicalExtentComputedValues minValues;
computePositionedLogicalHeightUsing(MinSize, styleToUse->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
- minLogicalHeight, minMarginBefore, minMarginAfter, minLogicalTopPos);
+ minValues);
- if (logicalHeightResult < minLogicalHeight) {
- logicalHeightResult = minLogicalHeight;
- marginBeforeAlias = minMarginBefore;
- marginAfterAlias = minMarginAfter;
- setLogicalTop(minLogicalTopPos);
+ if (computedValues.m_extent < minValues.m_extent) {
+ computedValues.m_extent = minValues.m_extent;
+ computedValues.m_position = minValues.m_position;
+ computedValues.m_margins.m_before = minValues.m_margins.m_before;
+ computedValues.m_margins.m_after = minValues.m_margins.m_after;
}
}
// Set final height value.
- setLogicalHeight(logicalHeightResult + bordersPlusPadding);
+ computedValues.m_extent += bordersPlusPadding;
// Adjust logicalTop if we need to for perpendicular writing modes in regions.
if (inRenderFlowThread() && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode()) {
- LayoutUnit logicalTopPos = logicalTop();
+ LayoutUnit logicalTopPos = computedValues.m_position;
const RenderBlock* cb = toRenderBlock(containerBlock);
LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
@@ -2965,7 +2975,7 @@ void RenderBox::computePositionedLogicalHeight()
RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
if (boxInfo) {
logicalTopPos += boxInfo->logicalLeft();
- setLogicalTop(logicalTopPos);
+ computedValues.m_position = logicalTopPos;
}
}
}
@@ -2996,7 +3006,7 @@ static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const R
void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding,
Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
- LayoutUnit& logicalHeightValue, LayoutUnit& marginBeforeValue, LayoutUnit& marginAfterValue, LayoutUnit& logicalTopPos)
+ LogicalExtentComputedValues& computedValues) const
{
if (heightSizeType == MinSize && logicalHeightLength.isAuto())
logicalHeightLength = Length(0, Fixed);
@@ -3005,6 +3015,7 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len
// converted to the static position in computePositionedLogicalHeight()
ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto()));
+ LayoutUnit logicalHeightValue;
LayoutUnit contentLogicalHeight = logicalHeight() - bordersPlusPadding;
LayoutUnit logicalTopValue = 0;
@@ -3041,20 +3052,20 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len
if (marginBefore.isAuto() && marginAfter.isAuto()) {
// Both margins auto, solve for equality
// NOTE: This may result in negative values.
- marginBeforeValue = availableSpace / 2; // split the difference
- marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences
+ computedValues.m_margins.m_before = availableSpace / 2; // split the difference
+ computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; // account for odd valued differences
} else if (marginBefore.isAuto()) {
// Solve for top margin
- marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView);
- marginBeforeValue = availableSpace - marginAfterValue;
+ computedValues.m_margins.m_after = valueForLength(marginAfter, containerLogicalHeight, renderView);
+ computedValues.m_margins.m_before = availableSpace - computedValues.m_margins.m_after;
} else if (marginAfter.isAuto()) {
// Solve for bottom margin
- marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView);
- marginAfterValue = availableSpace - marginBeforeValue;
+ computedValues.m_margins.m_before = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before;
} else {
// Over-constrained, (no need solve for bottom)
- marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView);
- marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView);
+ computedValues.m_margins.m_before = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ computedValues.m_margins.m_after = valueForLength(marginAfter, containerLogicalHeight, renderView);
}
} else {
/*--------------------------------------------------------------------*\
@@ -3083,10 +3094,10 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- marginBeforeValue = minimumValueForLength(marginBefore, containerLogicalHeight, renderView);
- marginAfterValue = minimumValueForLength(marginAfter, containerLogicalHeight, renderView);
+ computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerLogicalHeight, renderView);
+ computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerLogicalHeight, renderView);
- const LayoutUnit availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalHeight - (computedValues.m_margins.m_before + computedValues.m_margins.m_after + bordersPlusPadding);
// Use rule/case that applies.
if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
@@ -3111,13 +3122,14 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len
logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
}
}
+ computedValues.m_extent = logicalHeightValue;
// Use computed values to calculate the vertical position.
- logicalTopPos = logicalTopValue + marginBeforeValue;
- computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeightValue, containerBlock, containerLogicalHeight);
+ computedValues.m_position = logicalTopValue + computedValues.m_margins.m_before;
+ computeLogicalTopPositionedOffset(computedValues.m_position, this, logicalHeightValue, containerBlock, containerLogicalHeight);
}
-void RenderBox::computePositionedLogicalWidthReplaced()
+void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValues& computedValues) const
{
// The following is based off of the W3C Working Draft from April 11, 2006 of
// CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements"
@@ -3141,8 +3153,8 @@ void RenderBox::computePositionedLogicalWidthReplaced()
Length logicalRight = style()->logicalRight();
Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
- LayoutUnit& marginLogicalLeftAlias = m_marginBox.mutableLogicalLeft(style()->writingMode());
- LayoutUnit& marginLogicalRightAlias = m_marginBox.mutableLogicalRight(style()->writingMode());
+ LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
+ LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
/*-----------------------------------------------------------------------*\
* 1. The used value of 'width' is determined as for inline replaced
@@ -3151,9 +3163,9 @@ void RenderBox::computePositionedLogicalWidthReplaced()
// NOTE: This value of width is FINAL in that the min/max width calculations
// are dealt with in computeReplacedWidth(). This means that the steps to produce
// correct max/min in the non-replaced version, are not necessary.
- setLogicalWidth(computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth());
+ computedValues.m_extent = computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth();
- const LayoutUnit availableSpace = containerLogicalWidth - logicalWidth();
+ const LayoutUnit availableSpace = containerLogicalWidth - computedValues.m_extent;
/*-----------------------------------------------------------------------*\
* 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
@@ -3249,7 +3261,7 @@ void RenderBox::computePositionedLogicalWidthReplaced()
logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
// If the containing block is right-to-left, then push the left position as far to the right as possible
if (containerDirection == RTL) {
- int totalLogicalWidth = logicalWidth() + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
+ int totalLogicalWidth = computedValues.m_extent + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
}
}
@@ -3276,17 +3288,17 @@ void RenderBox::computePositionedLogicalWidthReplaced()
InlineFlowBox* firstLine = flow->firstLineBox();
InlineFlowBox* lastLine = flow->lastLineBox();
if (firstLine && lastLine && firstLine != lastLine) {
- setLogicalLeft(logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()));
+ computedValues.m_position = logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
return;
}
}
LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
- computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidth(), containerBlock, containerLogicalWidth);
- setLogicalLeft(logicalLeftPos.round());
+ computeLogicalLeftPositionedOffset(logicalLeftPos, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
+ computedValues.m_position = logicalLeftPos.round();
}
-void RenderBox::computePositionedLogicalHeightReplaced()
+void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValues& computedValues) const
{
// The following is based off of the W3C Working Draft from April 11, 2006 of
// CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements"
@@ -3302,8 +3314,8 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// Variables to solve.
Length marginBefore = style()->marginBefore();
Length marginAfter = style()->marginAfter();
- LayoutUnit& marginBeforeAlias = m_marginBox.mutableBefore(style()->writingMode());
- LayoutUnit& marginAfterAlias = m_marginBox.mutableAfter(style()->writingMode());
+ LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before;
+ LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after;
Length logicalTop = style()->logicalTop();
Length logicalBottom = style()->logicalBottom();
@@ -3316,8 +3328,8 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// NOTE: This value of height is FINAL in that the min/max height calculations
// are dealt with in computeReplacedHeight(). This means that the steps to produce
// correct max/min in the non-replaced version, are not necessary.
- setLogicalHeight(computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight());
- const LayoutUnit availableSpace = containerLogicalHeight - logicalHeight();
+ computedValues.m_extent = computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight();
+ const LayoutUnit availableSpace = containerLogicalHeight - computedValues.m_extent;
/*-----------------------------------------------------------------------*\
* 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
@@ -3411,8 +3423,8 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// Use computed values to calculate the vertical position.
LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
- computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeight(), containerBlock, containerLogicalHeight);
- setLogicalTop(logicalTopPos.round());
+ computeLogicalTopPositionedOffset(logicalTopPos, this, computedValues.m_extent, containerBlock, containerLogicalHeight);
+ computedValues.m_position = logicalTopPos.round();
}
LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index f011714cb..ed70a94b8 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -44,7 +44,7 @@ public:
// 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() || isOutOfFlowPositioned() || isInFlowPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns() || !style()->hasAutoZIndex(); }
+ virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || createsGroup() || hasClipPath() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns() || !style()->hasAutoZIndex(); }
// Use this with caution! No type checking is done!
RenderBox* firstChildBox() const;
@@ -75,8 +75,8 @@ public:
LayoutUnit logicalWidth() const { return style()->isHorizontalWritingMode() ? width() : height(); }
LayoutUnit logicalHeight() const { return style()->isHorizontalWritingMode() ? height() : width(); }
- LayoutUnit constrainLogicalWidthInRegionByMinMax(LayoutUnit, LayoutUnit, RenderBlock*, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = ZERO_LAYOUT_UNIT);
- LayoutUnit constrainLogicalHeightByMinMax(LayoutUnit);
+ LayoutUnit constrainLogicalWidthInRegionByMinMax(LayoutUnit, LayoutUnit, RenderBlock*, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = ZERO_LAYOUT_UNIT) const;
+ LayoutUnit constrainLogicalHeightByMinMax(LayoutUnit) const;
int pixelSnappedLogicalHeight() const { return style()->isHorizontalWritingMode() ? pixelSnappedHeight() : pixelSnappedWidth(); }
int pixelSnappedLogicalWidth() const { return style()->isHorizontalWritingMode() ? pixelSnappedWidth() : pixelSnappedHeight(); }
@@ -284,7 +284,7 @@ public:
virtual void layout();
virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual LayoutUnit minPreferredLogicalWidth() const;
virtual LayoutUnit maxPreferredLogicalWidth() const;
@@ -306,12 +306,37 @@ public:
virtual void borderFitAdjust(LayoutRect&) const { } // Shrink the box in which the border paints if border-fit is set.
+ struct ComputedMarginValues {
+ ComputedMarginValues()
+ : m_before(0)
+ , m_after(0)
+ , m_start(0)
+ , m_end(0)
+ {
+ }
+ LayoutUnit m_before;
+ LayoutUnit m_after;
+ LayoutUnit m_start;
+ LayoutUnit m_end;
+ };
+ struct LogicalExtentComputedValues {
+ LogicalExtentComputedValues()
+ : m_extent(0)
+ , m_position(0)
+ {
+ }
+
+ LayoutUnit m_extent;
+ 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
// of the containing block.
- void computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth);
+ void computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const;
// Used to resolve margins in the containing block's block-flow direction.
- void computeBlockDirectionMargins(const RenderBlock* containingBlock);
+ void computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const;
+ void computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock);
enum RenderBoxRegionInfoFlags { CacheRenderBoxRegionInfo, DoNotCacheRenderBoxRegionInfo };
LayoutRect borderBoxRectInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage = 0, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
@@ -338,12 +363,13 @@ public:
LayoutUnit containingBlockLogicalWidthForContentInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
LayoutUnit containingBlockAvailableLineWidthInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
LayoutUnit perpendicularContainingBlockLogicalHeight() const;
-
+
virtual void computeLogicalWidth();
virtual void computeLogicalHeight();
+ void computeLogicalHeight(LogicalExtentComputedValues&) const;
RenderBoxRegionInfo* renderBoxRegionInfo(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
- void computeLogicalWidthInRegion(RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = ZERO_LAYOUT_UNIT);
+ void computeLogicalWidthInRegion(LogicalExtentComputedValues&, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = ZERO_LAYOUT_UNIT) const;
bool stretchesToViewport() const
{
@@ -359,12 +385,12 @@ public:
bool sizesLogicalWidthToFitContent(SizeType) const;
virtual bool stretchesToMinIntrinsicLogicalWidth() const { return false; }
- LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage);
+ LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
- LayoutUnit computeLogicalWidthInRegionUsing(SizeType, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage);
- LayoutUnit computeLogicalHeightUsing(SizeType, const Length& height);
+ LayoutUnit computeLogicalWidthInRegionUsing(SizeType, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+ LayoutUnit computeLogicalHeightUsing(SizeType, const Length& height) const;
LayoutUnit computeLogicalClientHeight(SizeType, const Length& height);
- LayoutUnit computeContentLogicalHeightUsing(SizeType, const Length& height);
+ LayoutUnit computeContentLogicalHeightUsing(SizeType, const Length& height) const;
LayoutUnit computeReplacedLogicalWidthUsing(SizeType, Length width) const;
LayoutUnit computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, bool includeMaxWidth = true) const;
LayoutUnit computeReplacedLogicalHeightUsing(SizeType, Length height) const;
@@ -373,7 +399,7 @@ public:
virtual LayoutUnit computeReplacedLogicalWidth(bool includeMaxWidth = true) const;
virtual LayoutUnit computeReplacedLogicalHeight() const;
- LayoutUnit computePercentageLogicalHeight(const Length& height);
+ LayoutUnit computePercentageLogicalHeight(const Length& height) const;
// Block flows subclass availableWidth/Height to handle multi column layout (shrinking the width/height available to children when laying out.)
virtual LayoutUnit availableLogicalWidth() const { return contentLogicalWidth(); }
@@ -536,7 +562,7 @@ protected:
void paintCustomHighlight(const LayoutPoint&, const AtomicString& type, bool behindText);
#endif
- void computePositionedLogicalWidth(RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0);
+ void computePositionedLogicalWidth(LogicalExtentComputedValues&, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0) const;
virtual bool shouldComputeSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
@@ -561,24 +587,26 @@ private:
LayoutUnit offsetFromLogicalTopOfFirstPage = 0, bool checkForPerpendicularWritingMode = true) const;
LayoutUnit containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode = true) const;
- void computePositionedLogicalHeight();
+ void computePositionedLogicalHeight(LogicalExtentComputedValues&) const;
void computePositionedLogicalWidthUsing(SizeType, Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
- LayoutUnit& logicalWidthValue, LayoutUnit& marginLogicalLeftValue, LayoutUnit& marginLogicalRightValue, LayoutUnit& logicalLeftPos);
+ LogicalExtentComputedValues&) const;
void computePositionedLogicalHeightUsing(SizeType, Length logicalHeight, const RenderBoxModelObject* containerBlock,
LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding,
Length logicalTop, Length logicalBottom, Length marginLogicalTop, Length marginLogicalBottom,
- LayoutUnit& logicalHeightValue, LayoutUnit& marginLogicalTopValue, LayoutUnit& marginLogicalBottomValue, LayoutUnit& logicalTopPos);
+ LogicalExtentComputedValues&) const;
- void computePositionedLogicalHeightReplaced();
- void computePositionedLogicalWidthReplaced();
+ void computePositionedLogicalHeightReplaced(LogicalExtentComputedValues&) const;
+ void computePositionedLogicalWidthReplaced(LogicalExtentComputedValues&) const;
// This function calculates the minimum and maximum preferred widths for an object.
// These values are used in shrink-to-fit layout systems.
// These include tables, positioned objects, floats and flexible boxes.
virtual void computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); }
+ virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE { return frameRect(); }
+
private:
// The width/height of the contents + borders + padding. The x/y location is relative to our container (which is not always our parent).
LayoutRect m_frameRect;
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index 7dcd24129..8deeddf38 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -37,6 +37,7 @@
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderView.h"
+#include "ScrollingConstraints.h"
#include "Settings.h"
#include "TransformState.h"
#include <wtf/CurrentTime.h>
@@ -348,6 +349,15 @@ void RenderBoxModelObject::willBeDestroyed()
// A continuation of this RenderObject should be destroyed at subclasses.
ASSERT(!continuation());
+ if (isPositioned()) {
+ if (RenderView* view = this->view()) {
+ if (FrameView* frameView = view->frameView()) {
+ if (style()->hasViewportConstrainedPosition())
+ frameView->removeViewportConstrainedObject(this);
+ }
+ }
+ }
+
// If this is a first-letter object with a remaining text fragment then the
// entry needs to be cleared from the map.
if (firstLetterRemainingText())
@@ -446,6 +456,17 @@ void RenderBoxModelObject::styleDidChange(StyleDifference diff, const RenderStyl
if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
setChildNeedsLayout(true);
}
+
+ if (FrameView *frameView = view()->frameView()) {
+ bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
+ bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
+ if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
+ if (newStyleIsViewportConstained && layer())
+ frameView->addViewportConstrainedObject(this);
+ else
+ frameView->removeViewportConstrainedObject(this);
+ }
+ }
}
void RenderBoxModelObject::updateBoxModelInfoFromStyle()
@@ -456,6 +477,7 @@ void RenderBoxModelObject::updateBoxModelInfoFromStyle()
setHasBoxDecorations(hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow());
setInline(styleToUse->isDisplayInlineType());
setRelPositioned(styleToUse->position() == RelativePosition);
+ setStickyPositioned(styleToUse->position() == StickyPosition);
setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
}
@@ -534,6 +556,8 @@ LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const L
if (!isOutOfFlowPositioned()) {
if (isRelPositioned())
referencePoint.move(relativePositionOffset());
+ else if (isStickyPositioned())
+ referencePoint.move(stickyPositionOffset());
const RenderObject* curr = parent();
while (curr != offsetParent) {
// FIXME: What are we supposed to do inside SVG content?
@@ -542,7 +566,7 @@ LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const L
referencePoint.move(curr->parent()->offsetForColumns(referencePoint));
curr = curr->parent();
}
- if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isRelPositioned() && !offsetParent->isOutOfFlowPositioned())
+ if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation());
}
}
@@ -550,11 +574,73 @@ LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const L
return referencePoint;
}
+void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewportConstraints& constraints, const FloatRect& viewportRect) const
+{
+ RenderBlock* containingBlock = this->containingBlock();
+
+ LayoutRect containerContentRect = containingBlock->contentBoxRect();
+
+ LayoutUnit minLeftMargin = minimumValueForLength(style()->marginLeft(), containingBlock->availableLogicalWidth(), view());
+ LayoutUnit minTopMargin = minimumValueForLength(style()->marginTop(), containingBlock->availableLogicalWidth(), view());
+ LayoutUnit minRightMargin = minimumValueForLength(style()->marginRight(), containingBlock->availableLogicalWidth(), view());
+ LayoutUnit minBottomMargin = minimumValueForLength(style()->marginBottom(), containingBlock->availableLogicalWidth(), view());
+
+ // Compute the container-relative area within which the sticky element is allowed to move.
+ containerContentRect.move(minLeftMargin, minTopMargin);
+ containerContentRect.contract(minLeftMargin + minRightMargin, minTopMargin + minBottomMargin);
+ constraints.setAbsoluteContainingBlockRect(containingBlock->localToAbsoluteQuad(FloatRect(containerContentRect)).boundingBox());
+
+ LayoutRect stickyBoxRect = frameRectForStickyPositioning();
+ LayoutRect flippedStickyBoxRect = stickyBoxRect;
+ containingBlock->flipForWritingMode(flippedStickyBoxRect);
+ LayoutPoint stickyLocation = flippedStickyBoxRect.location();
+
+ // FIXME: sucks to call localToAbsolute again, but we can't just offset from the previously computed rect if there are transforms.
+ FloatRect absContainerFrame = containingBlock->localToAbsoluteQuad(FloatRect(FloatPoint(), containingBlock->size())).boundingBox();
+ // 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()));
+ constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
+ }
+
+ if (!style()->right().isAuto()) {
+ constraints.setRightOffset(valueForLength(style()->right(), viewportRect.width(), view()));
+ constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight);
+ }
+
+ if (!style()->top().isAuto()) {
+ constraints.setTopOffset(valueForLength(style()->top(), viewportRect.height(), view()));
+ constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
+ }
+
+ if (!style()->bottom().isAuto()) {
+ constraints.setBottomOffset(valueForLength(style()->bottom(), viewportRect.height(), view()));
+ constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom);
+ }
+}
+
+LayoutSize RenderBoxModelObject::stickyPositionOffset() const
+{
+ LayoutRect viewportRect = view()->frameView()->visibleContentRect();
+
+ StickyPositionViewportConstraints constraints;
+ computeStickyPositionConstraints(constraints, viewportRect);
+
+ // 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));
+}
+
LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const
{
if (isRelPositioned())
return relativePositionOffset();
+ if (isStickyPositioned())
+ return stickyPositionOffset();
+
return LayoutSize();
}
@@ -2730,9 +2816,6 @@ bool RenderBoxModelObject::shouldAntialiasLines(GraphicsContext* context)
void RenderBoxModelObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
- // We don't expect absoluteToLocal() to be called during layout (yet)
- ASSERT(!view() || !view()->layoutStateEnabled());
-
RenderObject* o = container();
if (!o)
return;
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index 8d5e83e7a..6ee354c9a 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -24,6 +24,7 @@
#ifndef RenderBoxModelObject_h
#define RenderBoxModelObject_h
+#include "LayoutTypesInlineMethods.h"
#include "RenderObject.h"
#include "ShadowData.h"
@@ -50,6 +51,7 @@ enum ContentChangeType {
};
class KeyframeList;
+class StickyPositionViewportConstraints;
// This class is the base for all objects that adhere to the CSS box model as described
// at http://www.w3.org/TR/CSS21/box.html
@@ -62,6 +64,10 @@ public:
LayoutSize relativePositionOffset() const;
LayoutSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
+ void computeStickyPositionConstraints(StickyPositionViewportConstraints&, const FloatRect& viewportRect) const;
+ LayoutSize stickyPositionOffset() const;
+ LayoutSize stickyPositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? stickyPositionOffset() : stickyPositionOffset().transposedSize(); }
+
LayoutSize offsetForInFlowPosition() const;
// IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
@@ -82,7 +88,8 @@ public:
bool hasSelfPaintingLayer() const;
RenderLayer* layer() const { return m_layer; }
- virtual bool requiresLayer() const { return isRoot() || isOutOfFlowPositioned() || isInFlowPositioned() || isTransparent() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
+
+ virtual bool requiresLayer() const { 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;
@@ -275,6 +282,8 @@ public:
private:
virtual bool isBoxModelObject() const { return true; }
+
+ virtual LayoutRect frameRectForStickyPositioning() const = 0;
IntSize calculateFillTileSize(const FillLayer*, const IntSize& scaledPositioningAreaSize) const;
diff --git a/Source/WebCore/rendering/RenderCounter.cpp b/Source/WebCore/rendering/RenderCounter.cpp
index de45d895e..e3496b136 100644
--- a/Source/WebCore/rendering/RenderCounter.cpp
+++ b/Source/WebCore/rendering/RenderCounter.cpp
@@ -30,6 +30,7 @@
#include "RenderListItem.h"
#include "RenderListMarker.h"
#include "RenderStyle.h"
+#include "RenderView.h"
#include <wtf/StdLibExtras.h>
#ifndef NDEBUG
@@ -40,7 +41,7 @@ namespace WebCore {
using namespace HTMLNames;
-typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<CounterNode> > CounterMap;
+typedef HashMap<AtomicString, RefPtr<CounterNode> > CounterMap;
typedef HashMap<const RenderObject*, OwnPtr<CounterMap> > CounterMaps;
static CounterNode* makeCounterNode(RenderObject*, const AtomicString& identifier, bool alwaysCreateCounter);
@@ -241,20 +242,11 @@ static bool planCounter(RenderObject* object, const AtomicString& identifier, bo
return false; // Counters are forbidden from all other pseudo elements.
}
- if (const CounterDirectiveMap* directivesMap = style->counterDirectives()) {
- CounterDirectives directives = directivesMap->get(identifier.impl());
- if (directives.m_reset) {
- value = directives.m_resetValue;
- if (directives.m_increment)
- value += directives.m_incrementValue;
- isReset = true;
- return true;
- }
- if (directives.m_increment) {
- value = directives.m_incrementValue;
- isReset = false;
- return true;
- }
+ const CounterDirectives directives = style->getCounterDirectives(identifier);
+ if (directives.isDefined()) {
+ value = directives.combinedValue();
+ isReset = directives.isReset();
+ return true;
}
if (identifier == "list-item") {
@@ -420,7 +412,7 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id
if (object->hasCounterNodeMap()) {
if (CounterMap* nodeMap = counterMaps().get(object)) {
- if (CounterNode* node = nodeMap->get(identifier.impl()).get())
+ if (CounterNode* node = nodeMap->get(identifier).get())
return node;
}
}
@@ -443,7 +435,7 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id
counterMaps().set(object, adoptPtr(nodeMap));
object->setHasCounterNodeMap(true);
}
- nodeMap->set(identifier.impl(), newNode);
+ nodeMap->set(identifier, newNode);
if (newNode->parent())
return newNode.get();
// Checking if some nodes that were previously counter tree root nodes
@@ -455,7 +447,7 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id
skipDescendants = false;
if (!currentRenderer->hasCounterNodeMap())
continue;
- CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier.impl()).get();
+ CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier).get();
if (!currentCounter)
continue;
skipDescendants = true;
@@ -537,6 +529,11 @@ PassRefPtr<StringImpl> RenderCounter::originalText() const
return text.impl();
}
+void RenderCounter::updateText()
+{
+ computePreferredLogicalWidths(0);
+}
+
void RenderCounter::computePreferredLogicalWidths(float lead)
{
setTextInternal(originalText());
@@ -558,8 +555,8 @@ static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier,
for (RefPtr<CounterNode> child = node->lastDescendant(); child && child != node; child = previous) {
previous = child->previousInPreOrder();
child->parent()->removeChild(child.get());
- ASSERT(counterMaps().get(child->owner())->get(identifier.impl()) == child);
- counterMaps().get(child->owner())->remove(identifier.impl());
+ ASSERT(counterMaps().get(child->owner())->get(identifier) == child);
+ counterMaps().get(child->owner())->remove(identifier);
}
if (CounterNode* parent = node->parent())
parent->removeChild(node);
@@ -574,8 +571,7 @@ void RenderCounter::destroyCounterNodes(RenderObject* owner)
CounterMap* map = mapsIterator->second.get();
CounterMap::const_iterator end = map->end();
for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
- AtomicString identifier(it->first.get());
- destroyCounterNodeWithoutMapRemoval(identifier, it->second.get());
+ destroyCounterNodeWithoutMapRemoval(it->first, it->second.get());
}
maps.remove(mapsIterator);
owner->setHasCounterNodeMap(false);
@@ -586,7 +582,7 @@ void RenderCounter::destroyCounterNode(RenderObject* owner, const AtomicString&
CounterMap* map = counterMaps().get(owner);
if (!map)
return;
- CounterMap::iterator mapIterator = map->find(identifier.impl());
+ CounterMap::iterator mapIterator = map->find(identifier);
if (mapIterator == map->end())
return;
destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->second.get());
@@ -629,22 +625,22 @@ static void updateCounters(RenderObject* renderer)
CounterDirectiveMap::const_iterator end = directiveMap->end();
if (!renderer->hasCounterNodeMap()) {
for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it)
- makeCounterNode(renderer, AtomicString(it->first.get()), false);
+ makeCounterNode(renderer, it->first, false);
return;
}
CounterMap* counterMap = counterMaps().get(renderer);
ASSERT(counterMap);
for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) {
- RefPtr<CounterNode> node = counterMap->get(it->first.get());
+ RefPtr<CounterNode> node = counterMap->get(it->first);
if (!node) {
- makeCounterNode(renderer, AtomicString(it->first.get()), false);
+ makeCounterNode(renderer, it->first, false);
continue;
}
RefPtr<CounterNode> newParent = 0;
RefPtr<CounterNode> newPreviousSibling = 0;
- findPlaceForCounter(renderer, AtomicString(it->first.get()), node->hasResetType(), newParent, newPreviousSibling);
- if (node != counterMap->get(it->first.get()))
+ findPlaceForCounter(renderer, it->first, node->hasResetType(), newParent, newPreviousSibling);
+ if (node != counterMap->get(it->first))
continue;
CounterNode* parent = node->parent();
if (newParent == parent && newPreviousSibling == node->previousSibling())
@@ -652,7 +648,7 @@ static void updateCounters(RenderObject* renderer)
if (parent)
parent->removeChild(node.get());
if (newParent)
- newParent->insertAfter(node.get(), newPreviousSibling.get(), it->first.get());
+ newParent->insertAfter(node.get(), newPreviousSibling.get(), it->first);
}
}
@@ -688,17 +684,17 @@ void RenderCounter::rendererStyleChanged(RenderObject* renderer, const RenderSty
if (oldMapIt != oldMapEnd) {
if (oldMapIt->second == it->second)
continue;
- RenderCounter::destroyCounterNode(renderer, it->first.get());
+ RenderCounter::destroyCounterNode(renderer, it->first);
}
// We must create this node here, because the changed node may be a node with no display such as
// as those created by the increment or reset directives and the re-layout that will happen will
// not catch the change if the node had no children.
- makeCounterNode(renderer, it->first.get(), false);
+ makeCounterNode(renderer, it->first, false);
}
// Destroying old counters that do not exist in the new counterDirective map.
for (CounterDirectiveMap::const_iterator it = oldCounterDirectives->begin(); it !=oldMapEnd; ++it) {
if (!newCounterDirectives->contains(it->first))
- RenderCounter::destroyCounterNode(renderer, it->first.get());
+ RenderCounter::destroyCounterNode(renderer, it->first);
}
} else {
if (renderer->hasCounterNodeMap())
@@ -710,7 +706,7 @@ void RenderCounter::rendererStyleChanged(RenderObject* renderer, const RenderSty
// We must create this node here, because the added node may be a node with no display such as
// as those created by the increment or reset directives and the re-layout that will happen will
// not catch the change if the node had no children.
- makeCounterNode(renderer, it->first.get(), false);
+ makeCounterNode(renderer, it->first, false);
}
}
}
@@ -735,7 +731,7 @@ void showCounterRendererTree(const WebCore::RenderObject* renderer, const char*
fprintf(stderr, "%p N:%p P:%p PS:%p NS:%p C:%p\n",
current, current->node(), current->parent(), current->previousSibling(),
current->nextSibling(), current->hasCounterNodeMap() ?
- counterName ? WebCore::counterMaps().get(current)->get(identifier.impl()).get() : (WebCore::CounterNode*)1 : (WebCore::CounterNode*)0);
+ counterName ? WebCore::counterMaps().get(current)->get(identifier).get() : (WebCore::CounterNode*)1 : (WebCore::CounterNode*)0);
}
fflush(stderr);
}
diff --git a/Source/WebCore/rendering/RenderCounter.h b/Source/WebCore/rendering/RenderCounter.h
index 6ba936f86..548828647 100644
--- a/Source/WebCore/rendering/RenderCounter.h
+++ b/Source/WebCore/rendering/RenderCounter.h
@@ -48,6 +48,7 @@ private:
virtual bool isCounter() const;
virtual PassRefPtr<StringImpl> originalText() const;
+ virtual void updateText() OVERRIDE;
virtual void computePreferredLogicalWidths(float leadWidth);
// Removes the reference to the CounterNode associated with this renderer.
diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
index 8fa73ae4f..e2fe1cf5c 100644
--- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
@@ -379,7 +379,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
continue;
// Compute the child's vertical margins.
- child->computeBlockDirectionMargins(this);
+ child->computeAndSetBlockDirectionMargins(this);
if (!child->needsLayout())
child->markForPaginationRelayoutIfNeeded();
@@ -684,7 +684,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
}
// Compute the child's vertical margins.
- child->computeBlockDirectionMargins(this);
+ child->computeAndSetBlockDirectionMargins(this);
// Add in the child's marginTop to our height.
setHeight(height() + child->marginTop());
diff --git a/Source/WebCore/rendering/RenderDialog.cpp b/Source/WebCore/rendering/RenderDialog.cpp
new file mode 100644
index 000000000..4fb940925
--- /dev/null
+++ b/Source/WebCore/rendering/RenderDialog.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderDialog.h"
+
+#if ENABLE(DIALOG_ELEMENT)
+#include "FrameView.h"
+#include "LayoutRepainter.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+void RenderDialog::layout()
+{
+ LayoutRepainter repainter(*this, true);
+ LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+ RenderBlock::layout();
+
+ RenderStyle* styleToUse = style();
+ if (styleToUse->position() != AbsolutePosition || !styleToUse->top().isAuto() || !styleToUse->bottom().isAuto()) {
+ statePusher.pop();
+ return;
+ }
+
+ // Adjust the dialog's position to be centered in or at the top of the viewport.
+ // FIXME: Figure out what to do in vertical writing mode.
+ FrameView* frameView = document()->view();
+ int scrollTop = frameView->scrollOffset().height();
+ FloatPoint absolutePoint(0, scrollTop);
+ int visibleHeight = frameView->visibleContentRect(true).height();
+ if (height() < visibleHeight)
+ absolutePoint.move(0, (visibleHeight - height()) / 2);
+ FloatPoint localPoint = containingBlock()->absoluteToLocal(absolutePoint);
+ LayoutUnit localTop = LayoutSize(localPoint.x(), localPoint.y()).height();
+ setY(localTop);
+
+ statePusher.pop();
+ // FIXME: Since there is always a layer here, repainter shouldn't be necessary. But without it, the dialog is sometimes not painted (see bug 90670).
+ repainter.repaintAfterLayout();
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/rendering/RenderDialog.h b/Source/WebCore/rendering/RenderDialog.h
new file mode 100644
index 000000000..ea669469e
--- /dev/null
+++ b/Source/WebCore/rendering/RenderDialog.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 RenderDialog_h
+#define RenderDialog_h
+
+#if ENABLE(DIALOG_ELEMENT)
+#include "RenderBlock.h"
+#include "RenderWidget.h"
+
+namespace WebCore {
+
+class HTMLDialogElement;
+
+class RenderDialog : public RenderBlock {
+public:
+ explicit RenderDialog(Node* node)
+ : RenderBlock(node)
+ { }
+
+ virtual ~RenderDialog() { }
+ virtual void layout() OVERRIDE;
+
+private:
+ virtual const char* renderName() const { return "RenderDialog"; }
+ virtual bool isDialog() const OVERRIDE { return true; }
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // RenderDialog_h
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.cpp b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
index 135959420..dcb3cc3b0 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.cpp
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
@@ -265,16 +265,16 @@ void RenderEmbeddedObject::viewCleared()
}
}
-bool RenderEmbeddedObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderEmbeddedObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- if (!RenderPart::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, hitTestAction))
+ if (!RenderPart::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
return false;
if (!widget() || !widget()->isPluginViewBase())
return true;
PluginViewBase* view = static_cast<PluginViewBase*>(widget());
- IntPoint roundedPoint = pointInContainer.roundedPoint();
+ IntPoint roundedPoint = locationInContainer.roundedPoint();
if (Scrollbar* horizontalScrollbar = view->horizontalScrollbar()) {
if (horizontalScrollbar->shouldParticipateInHitTesting() && horizontalScrollbar->frameRect().contains(roundedPoint)) {
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.h b/Source/WebCore/rendering/RenderEmbeddedObject.h
index 6edc9bfb7..3f318b167 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.h
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.h
@@ -71,7 +71,7 @@ private:
virtual void layout();
virtual void viewCleared();
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier, Node** stopNode);
virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier, Node** stopNode);
diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp
index f3e47df47..059ff4818 100644
--- a/Source/WebCore/rendering/RenderFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderFlowThread.cpp
@@ -52,6 +52,9 @@ RenderFlowThread::RenderFlowThread(Node* node)
, m_regionsHaveUniformLogicalWidth(true)
, m_regionsHaveUniformLogicalHeight(true)
, m_overset(true)
+ , m_hasRegionsWithStyling(false)
+ , m_dispatchRegionLayoutUpdateEvent(false)
+ , m_pageLogicalHeightChanged(false)
{
ASSERT(node->document()->cssRegionsEnabled());
setIsAnonymous(false);
@@ -130,7 +133,7 @@ private:
void RenderFlowThread::layout()
{
- bool regionsChanged = m_regionsInvalidated && everHadLayout();
+ m_pageLogicalHeightChanged = m_regionsInvalidated && everHadLayout();
if (m_regionsInvalidated) {
m_regionsInvalidated = false;
m_hasValidRegions = false;
@@ -148,8 +151,8 @@ void RenderFlowThread::layout()
region->deleteAllRenderBoxRegionInfo();
- LayoutUnit regionLogicalWidth = region->logicalWidthForFlowThreadContent();
- LayoutUnit regionLogicalHeight = region->logicalHeightForFlowThreadContent();
+ LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
+ LayoutUnit regionLogicalHeight = region->pageLogicalHeight();
if (!m_hasValidRegions)
m_hasValidRegions = true;
@@ -171,21 +174,24 @@ void RenderFlowThread::layout()
if (!region->isValid())
continue;
- LayoutUnit regionLogicalWidth = region->logicalWidthForFlowThreadContent();
- LayoutUnit regionLogicalHeight = region->logicalHeightForFlowThreadContent();
+ LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
+ LayoutUnit regionLogicalHeight = region->logicalHeightOfAllFlowThreadContent();
LayoutRect regionRect(style()->direction() == LTR ? ZERO_LAYOUT_UNIT : logicalWidth() - regionLogicalWidth, logicalHeight, regionLogicalWidth, regionLogicalHeight);
- region->setRegionRect(isHorizontalWritingMode() ? regionRect : regionRect.transposedRect());
+ region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect : regionRect.transposedRect());
logicalHeight += regionLogicalHeight;
}
}
}
CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
- LayoutStateMaintainer statePusher(view(), this, regionsChanged);
RenderBlock::layout();
- statePusher.pop();
-
+
+ m_pageLogicalHeightChanged = false;
+
+ if (lastRegion())
+ lastRegion()->expandToEncompassFlowThreadContentsIfNeeded();
+
if (shouldDispatchRegionLayoutUpdateEvent())
dispatchRegionLayoutUpdateEvent();
}
@@ -198,7 +204,7 @@ void RenderFlowThread::computeLogicalWidth()
if (!region->isValid())
continue;
ASSERT(!region->needsLayout());
- logicalWidth = max(region->logicalWidthForFlowThreadContent(), logicalWidth);
+ logicalWidth = max(region->pageLogicalWidth(), logicalWidth);
}
setLogicalWidth(logicalWidth);
@@ -208,7 +214,7 @@ void RenderFlowThread::computeLogicalWidth()
if (!region->isValid())
continue;
- LayoutUnit regionLogicalWidth = region->logicalWidthForFlowThreadContent();
+ LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
if (regionLogicalWidth != logicalWidth) {
LayoutUnit logicalLeft = style()->direction() == LTR ? ZERO_LAYOUT_UNIT : logicalWidth - regionLogicalWidth;
region->setRenderBoxRegionInfo(this, logicalLeft, regionLogicalWidth, false);
@@ -225,13 +231,13 @@ void RenderFlowThread::computeLogicalHeight()
if (!region->isValid())
continue;
ASSERT(!region->needsLayout());
- logicalHeight += region->logicalHeightForFlowThreadContent();
+ logicalHeight += region->logicalHeightOfAllFlowThreadContent();
}
setLogicalHeight(logicalHeight);
}
-void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* region, const LayoutPoint& paintOffset)
+void RenderFlowThread::paintFlowThreadPortionInRegion(PaintInfo& paintInfo, RenderRegion* region, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const LayoutPoint& paintOffset) const
{
GraphicsContext* context = paintInfo.context;
if (!context)
@@ -240,9 +246,7 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio
// Adjust the clipping rect for the region.
// paintOffset contains the offset where the painting should occur
// adjusted with the region padding and border.
- LayoutRect regionRect(region->regionRect());
- LayoutRect regionOversetRect(region->regionOversetRect());
- LayoutRect regionClippingRect(paintOffset + (regionOversetRect.location() - regionRect.location()), regionOversetRect.size());
+ LayoutRect regionClippingRect(paintOffset + (flowThreadPortionOverflowRect.location() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size());
PaintInfo info(paintInfo);
info.rect.intersect(pixelSnappedIntRect(regionClippingRect));
@@ -254,14 +258,14 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio
// RenderFlowThread should start painting its content in a position that is offset
// from the region rect's current position. The amount of offset is equal to the location of
- // region in flow coordinates.
+ // the flow thread portion in the flow thread's local coordinates.
IntPoint renderFlowThreadOffset;
if (style()->isFlippedBlocksWritingMode()) {
- LayoutRect flippedRegionRect(regionRect);
- flipForWritingMode(flippedRegionRect);
- renderFlowThreadOffset = roundedIntPoint(paintOffset - flippedRegionRect.location());
+ LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
+ flipForWritingMode(flippedFlowThreadPortionRect);
+ renderFlowThreadOffset = roundedIntPoint(paintOffset - flippedFlowThreadPortionRect.location());
} else
- renderFlowThreadOffset = roundedIntPoint(paintOffset - regionRect.location());
+ renderFlowThreadOffset = roundedIntPoint(paintOffset - flowThreadPortionRect.location());
context->translate(renderFlowThreadOffset.x(), renderFlowThreadOffset.y());
info.rect.moveBy(-renderFlowThreadOffset);
@@ -272,29 +276,27 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio
}
}
-bool RenderFlowThread::hitTestRegion(RenderRegion* region, const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
+bool RenderFlowThread::hitTestFlowThreadPortionInRegion(RenderRegion* region, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
{
- LayoutRect regionRect(region->regionRect());
- LayoutRect regionOversetRect = region->regionOversetRect();
- LayoutRect regionClippingRect(accumulatedOffset + (regionOversetRect.location() - regionRect.location()), regionOversetRect.size());
- if (!regionClippingRect.contains(pointInContainer.point()))
+ LayoutRect regionClippingRect(accumulatedOffset + (flowThreadPortionOverflowRect.location() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size());
+ if (!regionClippingRect.contains(locationInContainer.point()))
return false;
LayoutSize renderFlowThreadOffset;
if (style()->isFlippedBlocksWritingMode()) {
- LayoutRect flippedRegionRect(regionRect);
- flipForWritingMode(flippedRegionRect);
- renderFlowThreadOffset = accumulatedOffset - flippedRegionRect.location();
+ LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
+ flipForWritingMode(flippedFlowThreadPortionRect);
+ renderFlowThreadOffset = accumulatedOffset - flippedFlowThreadPortionRect.location();
} else
- renderFlowThreadOffset = accumulatedOffset - regionRect.location();
+ 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);
- // Make a new temporary hitTestPoint in the new region.
- HitTestPoint newHitTestPoint(pointInContainer, -renderFlowThreadOffset, region);
+ // Make a new temporary HitTestLocation in the new region.
+ HitTestLocation newHitTestLocation(locationInContainer, -renderFlowThreadOffset, region);
- bool isPointInsideFlowThread = layer()->hitTest(newRequest, newHitTestPoint, result);
+ 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
@@ -315,37 +317,22 @@ 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.
+
+ // 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.
+ CurrentRenderFlowThreadDisabler disabler(view());
+
for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
RenderRegion* region = *iter;
if (!region->isValid())
continue;
- // We only have to issue a repaint in this region if the region rect intersects the repaint rect.
- LayoutRect flippedRegionRect(region->regionRect());
- LayoutRect flippedRegionOversetRect(region->regionOversetRect());
- flipForWritingMode(flippedRegionRect); // Put the region rects into physical coordinates.
- flipForWritingMode(flippedRegionOversetRect);
-
- LayoutRect clippedRect(repaintRect);
- clippedRect.intersect(flippedRegionOversetRect);
- if (clippedRect.isEmpty())
- continue;
-
- // Put the region rect into the region's physical coordinate space.
- clippedRect.setLocation(region->contentBoxRect().location() + (clippedRect.location() - flippedRegionRect.location()));
-
- // Now switch to the region's writing mode coordinate space and let it repaint itself.
- region->flipForWritingMode(clippedRect);
- LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the region is somewhere else.
-
- // Can't use currentFlowThread as it possible to have imbricated flow threads and the wrong one could be used,
- // so, we let each region figure out the proper enclosing flow thread
- CurrentRenderFlowThreadDisabler disabler(view());
- region->repaintRectangle(clippedRect, immediate);
+ region->repaintFlowThreadContent(repaintRect, immediate);
}
}
-RenderRegion* RenderFlowThread::renderRegionForLine(LayoutUnit position, bool extendLastRegion) const
+RenderRegion* RenderFlowThread::regionAtBlockOffset(LayoutUnit offset, bool extendLastRegion) const
{
ASSERT(!m_regionsInvalidated);
@@ -360,58 +347,52 @@ RenderRegion* RenderFlowThread::renderRegionForLine(LayoutUnit position, bool ex
if (!region->isValid())
continue;
- if (position <= 0)
+ if (offset <= 0)
return region;
- LayoutRect regionRect = region->regionRect();
-
- if ((useHorizontalWritingMode && position < regionRect.maxY()) || (!useHorizontalWritingMode && position < regionRect.maxX()))
+ LayoutRect regionRect = region->flowThreadPortionRect();
+ if ((useHorizontalWritingMode && offset < regionRect.maxY()) || (!useHorizontalWritingMode && offset < regionRect.maxX()))
return region;
- if (extendLastRegion)
+ if (extendLastRegion || region->isRenderRegionSet())
lastValidRegion = region;
}
return lastValidRegion;
}
-LayoutUnit RenderFlowThread::regionLogicalTopForLine(LayoutUnit position) const
+LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset) const
{
- RenderRegion* region = renderRegionForLine(position);
- if (!region)
- return 0;
- return isHorizontalWritingMode() ? region->regionRect().y() : region->regionRect().x();
+ RenderRegion* region = regionAtBlockOffset(offset);
+ return region ? region->pageLogicalTopForOffset(offset) : ZERO_LAYOUT_UNIT;
}
-LayoutUnit RenderFlowThread::regionLogicalWidthForLine(LayoutUnit position) const
+LayoutUnit RenderFlowThread::pageLogicalWidthForOffset(LayoutUnit offset) const
{
- RenderRegion* region = renderRegionForLine(position, true);
- if (!region)
- return contentLogicalWidth();
- return isHorizontalWritingMode() ? region->regionRect().width() : region->regionRect().height();
+ RenderRegion* region = regionAtBlockOffset(offset, true);
+ return region ? region->pageLogicalWidth() : contentLogicalWidth();
}
-LayoutUnit RenderFlowThread::regionLogicalHeightForLine(LayoutUnit position) const
+LayoutUnit RenderFlowThread::pageLogicalHeightForOffset(LayoutUnit offset) const
{
- RenderRegion* region = renderRegionForLine(position);
- if (!region)
- return 0;
- return isHorizontalWritingMode() ? region->regionRect().height() : region->regionRect().width();
+ RenderRegion* region = regionAtBlockOffset(offset);
+ return region ? region->pageLogicalHeight() : ZERO_LAYOUT_UNIT;
}
-LayoutUnit RenderFlowThread::regionRemainingLogicalHeightForLine(LayoutUnit position, PageBoundaryRule pageBoundaryRule) const
+LayoutUnit RenderFlowThread::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule) const
{
- RenderRegion* region = renderRegionForLine(position);
+ RenderRegion* region = regionAtBlockOffset(offset);
if (!region)
- return 0;
-
- LayoutUnit regionLogicalBottom = isHorizontalWritingMode() ? region->regionRect().maxY() : region->regionRect().maxX();
- LayoutUnit remainingHeight = regionLogicalBottom - position;
+ return ZERO_LAYOUT_UNIT;
+
+ LayoutUnit pageLogicalTop = region->pageLogicalTopForOffset(offset);
+ LayoutUnit pageLogicalHeight = region->pageLogicalHeight();
+ LayoutUnit pageLogicalBottom = pageLogicalTop + pageLogicalHeight;
+ LayoutUnit remainingHeight = pageLogicalBottom - offset;
if (pageBoundaryRule == IncludePageBoundary) {
// If IncludePageBoundary is set, the line exactly on the top edge of a
// region will act as being part of the previous region.
- LayoutUnit regionHeight = isHorizontalWritingMode() ? region->regionRect().height() : region->regionRect().width();
- remainingHeight = intMod(remainingHeight, regionHeight);
+ remainingHeight = intMod(remainingHeight, pageLogicalHeight);
}
return remainingHeight;
}
@@ -429,11 +410,11 @@ RenderRegion* RenderFlowThread::mapFromFlowToRegion(TransformState& transformSta
// Note: Using the center in order to avoid rounding errors.
LayoutPoint center = boxRect.center();
- RenderRegion* renderRegion = renderRegionForLine(isHorizontalWritingMode() ? center.y() : center.x(), true);
+ RenderRegion* renderRegion = regionAtBlockOffset(isHorizontalWritingMode() ? center.y() : center.x(), true);
if (!renderRegion)
return 0;
- LayoutRect flippedRegionRect(renderRegion->regionRect());
+ LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect());
flipForWritingMode(flippedRegionRect);
transformState.move(renderRegion->contentBoxRect().location() - flippedRegionRect.location());
@@ -541,7 +522,7 @@ LayoutUnit RenderFlowThread::contentLogicalLeftOfFirstRegion() const
RenderRegion* region = *iter;
if (!region->isValid())
continue;
- return isHorizontalWritingMode() ? region->regionRect().x() : region->regionRect().y();
+ return isHorizontalWritingMode() ? region->flowThreadPortionRect().x() : region->flowThreadPortionRect().y();
}
ASSERT_NOT_REACHED();
return 0;
@@ -605,8 +586,8 @@ void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit off
return;
// FIXME: Not right for differing writing-modes.
- RenderRegion* startRegion = renderRegionForLine(offsetFromLogicalTopOfFirstPage, true);
- RenderRegion* endRegion = renderRegionForLine(offsetFromLogicalTopOfFirstPage + box->logicalHeight(), true);
+ RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage, true);
+ RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage + box->logicalHeight(), true);
RenderRegionRangeMap::iterator it = m_regionRangeMap.find(box);
if (it == m_regionRangeMap.end()) {
m_regionRangeMap.set(box, RenderRegionRange(startRegion, endRegion));
@@ -669,8 +650,8 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE
region->setRegionState(RenderRegion::RegionUndefined);
continue;
}
- LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->regionRect().y() : region->regionRect().x());
- LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->regionRect().maxY() : region->regionRect().maxX());
+ LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x());
+ LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().maxY() : region->flowThreadPortionRect().maxX());
RenderRegion::RegionState previousState = region->regionState();
RenderRegion::RegionState state = RenderRegion::RegionFit;
if (flowMin <= 0)
@@ -688,7 +669,7 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE
}
// 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
+ // If there are no valid regions in the chain, overset is true.
m_overset = lastReg ? lastReg->regionState() == RenderRegion::RegionOverset : true;
}
diff --git a/Source/WebCore/rendering/RenderFlowThread.h b/Source/WebCore/rendering/RenderFlowThread.h
index 34dec69d8..32803adde 100644
--- a/Source/WebCore/rendering/RenderFlowThread.h
+++ b/Source/WebCore/rendering/RenderFlowThread.h
@@ -73,11 +73,11 @@ public:
virtual void removeRegionFromThread(RenderRegion*);
const RenderRegionList& renderRegionList() const { return m_regionList; }
- void computeLogicalWidth();
- void computeLogicalHeight();
+ virtual void computeLogicalWidth() OVERRIDE;
+ virtual void computeLogicalHeight() OVERRIDE;
- void paintIntoRegion(PaintInfo&, RenderRegion*, const LayoutPoint& paintOffset);
- bool hitTestRegion(RenderRegion*, const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
+ void paintFlowThreadPortionInRegion(PaintInfo&, RenderRegion*, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const LayoutPoint&) const;
+ bool hitTestFlowThreadPortionInRegion(RenderRegion*, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
bool hasRegions() const { return m_regionList.size(); }
bool hasValidRegions() const { ASSERT(!m_regionsInvalidated); return m_hasValidRegions; }
@@ -94,11 +94,11 @@ public:
void repaintRectangleInRegions(const LayoutRect&, bool immediate);
- LayoutUnit regionLogicalTopForLine(LayoutUnit position) const;
- LayoutUnit regionLogicalWidthForLine(LayoutUnit position) const;
- LayoutUnit regionLogicalHeightForLine(LayoutUnit position) const;
- LayoutUnit regionRemainingLogicalHeightForLine(LayoutUnit position, PageBoundaryRule = IncludePageBoundary) const;
- RenderRegion* renderRegionForLine(LayoutUnit position, bool extendLastRegion = false) const;
+ LayoutUnit pageLogicalTopForOffset(LayoutUnit) const;
+ LayoutUnit pageLogicalWidthForOffset(LayoutUnit) const;
+ LayoutUnit pageLogicalHeightForOffset(LayoutUnit) const;
+ LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary) const;
+ RenderRegion* regionAtBlockOffset(LayoutUnit, bool extendLastRegion = false) const;
bool regionsHaveUniformLogicalWidth() const { return m_regionsHaveUniformLogicalWidth; }
bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLogicalHeight; }
@@ -129,6 +129,8 @@ public:
// Check if the object is in region and the region is part of this flow thread.
bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
+ bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
+
protected:
virtual const char* renderName() const = 0;
@@ -180,6 +182,7 @@ protected:
bool m_overset;
bool m_hasRegionsWithStyling;
bool m_dispatchRegionLayoutUpdateEvent;
+ bool m_pageLogicalHeightChanged;
};
inline RenderFlowThread* toRenderFlowThread(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderFlowThreadContainer.cpp b/Source/WebCore/rendering/RenderFlowThreadContainer.cpp
deleted file mode 100644
index 680ac4ec0..000000000
--- a/Source/WebCore/rendering/RenderFlowThreadContainer.cpp
+++ /dev/null
@@ -1,47 +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 "RenderFlowThreadContainer.h"
-
-namespace WebCore {
-
-RenderFlowThreadContainer::RenderFlowThreadContainer(Node* node)
-: RenderFlowThread(node)
-{
-}
-
-void RenderFlowThreadContainer::layout()
-{
- ASSERT(needsLayout());
- setNeedsLayout(false);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderFlowThreadContainer.h b/Source/WebCore/rendering/RenderFlowThreadContainer.h
deleted file mode 100644
index 5a958ce3a..000000000
--- a/Source/WebCore/rendering/RenderFlowThreadContainer.h
+++ /dev/null
@@ -1,52 +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 RenderFlowThreadContainer_h
-#define RenderFlowThreadContainer_h
-
-
-#include "RenderFlowThread.h"
-
-namespace WebCore {
-
-class RenderFlowThreadContainer: public RenderFlowThread {
-public:
- RenderFlowThreadContainer(Node*);
- virtual ~RenderFlowThreadContainer() { };
-
- virtual void layout() OVERRIDE;
- virtual bool isRenderFlowThreadContainer() const OVERRIDE { return true; }
-
-private:
- virtual const char* renderName() const { return "RenderFlowThreadContainer"; }
-};
-
-} // namespace WebCore
-
-#endif // RenderFlowThread_h
diff --git a/Source/WebCore/rendering/RenderFrameBase.cpp b/Source/WebCore/rendering/RenderFrameBase.cpp
index aa82870d4..be92c0fa8 100644
--- a/Source/WebCore/rendering/RenderFrameBase.cpp
+++ b/Source/WebCore/rendering/RenderFrameBase.cpp
@@ -29,6 +29,8 @@
#include "Frame.h"
#include "FrameView.h"
#include "HTMLFrameElementBase.h"
+#include "HitTestResult.h"
+#include "RenderLayer.h"
#include "RenderView.h"
namespace WebCore {
@@ -104,4 +106,33 @@ void RenderFrameBase::layoutWithFlattening(bool hasFixedWidth, bool hasFixedHeig
setNeedsLayout(false);
}
+bool RenderFrameBase::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+ if (request.allowsChildFrameContent()) {
+ FrameView* childFrameView = static_cast<FrameView*>(widget());
+ RenderView* childRoot = childFrameView ? static_cast<RenderView*>(childFrameView->frame()->contentRenderer()) : 0;
+
+ if (childRoot) {
+ LayoutPoint adjustedLocation = accumulatedOffset + location();
+ HitTestLocation newHitTestLocation(locationInContainer, -toLayoutSize(adjustedLocation));
+ HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest);
+
+ bool isInsideChildFrame = childRoot->layer()->hitTest(newHitTestRequest, newHitTestLocation, result);
+ if (isInsideChildFrame)
+ return true;
+
+ if (request.shouldTestChildFrameScrollBars()) {
+ // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls,
+ // so we need to test ScrollView scrollbars separately here.
+ // FIXME: Consider if this test could be done unconditionally.
+ Scrollbar* frameScrollbar = childFrameView->scrollbarAtPoint(newHitTestLocation.roundedPoint());
+ if (frameScrollbar)
+ result.setScrollbar(frameScrollbar);
+ }
+ }
+ }
+
+ return RenderPart::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
+}
+
}
diff --git a/Source/WebCore/rendering/RenderFrameBase.h b/Source/WebCore/rendering/RenderFrameBase.h
index 4fad560c5..a7deedab1 100644
--- a/Source/WebCore/rendering/RenderFrameBase.h
+++ b/Source/WebCore/rendering/RenderFrameBase.h
@@ -36,6 +36,7 @@ protected:
explicit RenderFrameBase(Element*);
public:
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
void layoutWithFlattening(bool fixedWidth, bool fixedHeight);
};
diff --git a/Source/WebCore/rendering/RenderFrameSet.cpp b/Source/WebCore/rendering/RenderFrameSet.cpp
index c89547863..e6df40b9a 100644
--- a/Source/WebCore/rendering/RenderFrameSet.cpp
+++ b/Source/WebCore/rendering/RenderFrameSet.cpp
@@ -158,12 +158,12 @@ void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
}
bool RenderFrameSet::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
- const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+ const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
if (action != HitTestForeground)
return false;
- bool inside = RenderBox::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, action)
+ bool inside = RenderBox::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action)
|| m_isResizing;
if (inside && frameSet()->noResize()
diff --git a/Source/WebCore/rendering/RenderFrameSet.h b/Source/WebCore/rendering/RenderFrameSet.h
index 7d69770e7..b670575c3 100644
--- a/Source/WebCore/rendering/RenderFrameSet.h
+++ b/Source/WebCore/rendering/RenderFrameSet.h
@@ -96,7 +96,7 @@ private:
virtual bool isFrameSet() const { return true; }
virtual void layout();
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual void paint(PaintInfo&, const LayoutPoint&);
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
diff --git a/Source/WebCore/rendering/RenderGeometryMap.h b/Source/WebCore/rendering/RenderGeometryMap.h
index 98f44c633..495d0bf22 100644
--- a/Source/WebCore/rendering/RenderGeometryMap.h
+++ b/Source/WebCore/rendering/RenderGeometryMap.h
@@ -29,13 +29,17 @@
#include "FloatPoint.h"
#include "FloatQuad.h"
#include "IntSize.h"
-#include "RenderObject.h"
+#include "LayoutTypesInlineMethods.h"
#include "TransformationMatrix.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
+class RenderBoxModelObject;
class RenderLayer;
+class RenderObject;
+class RenderView;
+class TransformState;
// Stores data about how to map from one renderer to its container.
struct RenderGeometryMapStep {
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index f399abc4d..1953f5331 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -499,16 +499,16 @@ HTMLMapElement* RenderImage::imageMap() const
return i ? i->treeScope()->getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
}
-bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
- bool inside = RenderReplaced::nodeAtPoint(request, tempResult, pointInContainer, accumulatedOffset, hitTestAction);
+ HitTestResult tempResult(result.hitTestLocation());
+ bool inside = RenderReplaced::nodeAtPoint(request, tempResult, locationInContainer, accumulatedOffset, hitTestAction);
if (tempResult.innerNode() && node()) {
if (HTMLMapElement* map = imageMap()) {
LayoutRect contentBox = contentBoxRect();
float scaleFactor = 1 / style()->effectiveZoom();
- LayoutPoint mapLocation = pointInContainer.point() - toLayoutSize(accumulatedOffset) - locationOffset() - toLayoutSize(contentBox.location());
+ LayoutPoint mapLocation = locationInContainer.point() - toLayoutSize(accumulatedOffset) - locationOffset() - toLayoutSize(contentBox.location());
mapLocation.scale(scaleFactor, scaleFactor);
if (map->mapMouseEvent(mapLocation, contentBox.size(), tempResult))
diff --git a/Source/WebCore/rendering/RenderImage.h b/Source/WebCore/rendering/RenderImage.h
index 6bddb0a58..2358fb2db 100644
--- a/Source/WebCore/rendering/RenderImage.h
+++ b/Source/WebCore/rendering/RenderImage.h
@@ -92,7 +92,7 @@ private:
virtual int minimumReplacedHeight() const;
virtual void notifyFinished(CachedResource*);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE;
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index b139bcb44..941375509 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -750,6 +750,8 @@ const char* RenderInline::renderName() const
{
if (isRelPositioned())
return "RenderInline (relative positioned)";
+ if (isStickyPositioned())
+ return "RenderInline (sticky positioned)";
if (isAnonymous())
return "RenderInline (generated)";
if (isRunIn())
@@ -758,14 +760,14 @@ const char* RenderInline::renderName() const
}
bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
- const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+ const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- return m_lineBoxes.hitTest(this, request, result, pointInContainer, accumulatedOffset, hitTestAction);
+ return m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
}
VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point)
{
- // FIXME: Does not deal with relative positioned inlines (should it?)
+ // FIXME: Does not deal with relative or sticky positioned inlines (should it?)
RenderBlock* cb = containingBlock();
if (firstLineBox()) {
// This inline actually has a line box. We must have clicked in the border/padding of one of these boxes. We
@@ -1064,7 +1066,7 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer,
if (style()->hasInFlowPosition() && layer()) {
// Apply the in-flow 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
- // right dirty rect. Since this is called from RenderObject::setStyle, the relative position
+ // right dirty rect. Since this is called from RenderObject::setStyle, the relative or sticky position
// flag on the RenderObject has been cleared, so use the one on the style().
topLeft += layer()->offsetForInFlowPosition();
}
diff --git a/Source/WebCore/rendering/RenderInline.h b/Source/WebCore/rendering/RenderInline.h
index 9adec42b0..4a5bb09dc 100644
--- a/Source/WebCore/rendering/RenderInline.h
+++ b/Source/WebCore/rendering/RenderInline.h
@@ -89,7 +89,7 @@ public:
protected:
virtual void willBeDestroyed();
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
@@ -122,9 +122,9 @@ private:
virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual bool requiresLayer() const { return isInFlowPositioned() || isTransparent() || hasMask() || hasFilter(); }
+ virtual bool requiresLayer() const { return isInFlowPositioned() || createsGroup() || hasClipPath(); }
virtual LayoutUnit offsetLeft() const;
virtual LayoutUnit offsetTop() const;
@@ -140,6 +140,8 @@ private:
virtual VisiblePosition positionForPoint(const LayoutPoint&);
+ virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE { return linesBoundingBox(); }
+
virtual IntRect borderBoundingBox() const
{
IntRect boundingBox = linesBoundingBox();
diff --git a/Source/WebCore/rendering/RenderInputSpeech.h b/Source/WebCore/rendering/RenderInputSpeech.h
index f37b836f4..6735961fb 100644
--- a/Source/WebCore/rendering/RenderInputSpeech.h
+++ b/Source/WebCore/rendering/RenderInputSpeech.h
@@ -31,12 +31,18 @@
#ifndef RenderInputSpeech_h
#define RenderInputSpeech_h
-#include "RenderObject.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(StyleResolver*, RenderStyle*, Element*);
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index edb3cf58d..271999385 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -126,9 +126,9 @@ using namespace HTMLNames;
const int MinimumWidthWhileResizing = 100;
const int MinimumHeightWhileResizing = 40;
-bool ClipRect::intersects(const HitTestPoint& hitTestPoint)
+bool ClipRect::intersects(const HitTestLocation& hitTestLocation)
{
- return hitTestPoint.intersects(m_rect);
+ return hitTestLocation.intersects(m_rect);
}
RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
@@ -161,6 +161,9 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
#if ENABLE(CSS_FILTERS)
, m_hasFilterInfo(false)
#endif
+#if ENABLE(CSS_COMPOSITING)
+ , m_blendMode(BlendModeNormal)
+#endif
, m_renderer(renderer)
, m_parent(0)
, m_previous(0)
@@ -519,10 +522,10 @@ void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrol
updateLayerPosition();
- if ((flags & HasSeenFixedPositionedAncestor) || renderer()->style()->position() == FixedPosition) {
+ if ((flags & HasSeenViewportConstrainedAncestor) || renderer()->style()->hasViewportConstrainedPosition()) {
// FIXME: Is it worth passing the offsetFromRoot around like in updateLayerPositions?
computeRepaintRects();
- flags |= HasSeenFixedPositionedAncestor;
+ flags |= HasSeenViewportConstrainedAncestor;
} else if ((flags & HasSeenAncestorWithOverflowClip) && !m_canSkipRepaintRectsUpdateOnScroll) {
// If we have seen an overflow clip, we should update our repaint rects as clippedOverflowRectForRepaint
// intersects it with our ancestor overflow clip that may have moved.
@@ -543,6 +546,18 @@ void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrol
m_marquee->updateMarqueePosition();
}
+#if ENABLE(CSS_COMPOSITING)
+void RenderLayer::updateBlendMode()
+{
+ BlendMode newBlendMode = renderer()->style()->blendMode();
+ if (newBlendMode != m_blendMode) {
+ m_blendMode = newBlendMode;
+ if (backing())
+ backing()->setBlendMode(newBlendMode);
+ }
+}
+#endif
+
void RenderLayer::updateTransform()
{
// hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
@@ -933,7 +948,7 @@ RenderLayer* RenderLayer::stackingContext() const
static inline bool isPositionedContainer(RenderLayer* layer)
{
RenderBoxModelObject* layerRenderer = layer->renderer();
- return layer->isRootLayer() || layerRenderer->isOutOfFlowPositioned() || layerRenderer->isInFlowPositioned() || layer->hasTransform();
+ return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTransform();
}
static inline bool isFixedPositionedContainer(RenderLayer* layer)
@@ -1552,6 +1567,20 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutR
rect.move(-delta.x(), -delta.y());
}
+#if USE(ACCELERATED_COMPOSITING)
+bool RenderLayer::usesCompositedScrolling() const
+{
+ if (!scrollsOverflow() || !allowsScrolling())
+ return false;
+
+#if ENABLE(OVERFLOW_SCROLLING)
+ return renderer()->style()->useTouchOverflowScrolling();
+#else
+ return false;
+#endif
+}
+#endif
+
static inline int adjustedScrollDelta(int beginningDelta) {
// This implemention matches Firefox's.
// http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
@@ -1636,8 +1665,8 @@ IntSize RenderLayer::clampScrollOffset(const IntSize& scrollOffset) const
int maxX = scrollWidth() - box->pixelSnappedClientWidth();
int maxY = scrollHeight() - box->pixelSnappedClientHeight();
- int x = min(max(scrollOffset.width(), 0), maxX);
- int y = min(max(scrollOffset.height(), 0), maxY);
+ int x = max(min(scrollOffset.width(), maxX), 0);
+ int y = max(min(scrollOffset.height(), maxY), 0);
return IntSize(x, y);
}
@@ -1703,7 +1732,7 @@ void RenderLayer::scrollTo(int x, int y)
}
// Just schedule a full repaint of our object.
- if (view)
+ if (view && !usesCompositedScrolling())
renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
// Schedule the scroll DOM event.
@@ -2401,7 +2430,7 @@ bool RenderLayer::hasOverflowControls() const
return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
}
-void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
+void RenderLayer::positionOverflowControls(const IntSize& offsetFromRoot)
{
if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
return;
@@ -2412,7 +2441,7 @@ void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
const IntRect borderBox = box->pixelSnappedBorderBoxRect();
const IntRect& scrollCorner = scrollCornerRect();
- IntRect absBounds(borderBox.location() + offsetFromLayer, borderBox.size());
+ IntRect absBounds(borderBox.location() + offsetFromRoot, borderBox.size());
if (m_vBar)
m_vBar->setFrameRect(IntRect(verticalScrollbarStart(absBounds.x(), absBounds.maxX()),
absBounds.y() + box->borderTop(),
@@ -2425,34 +2454,15 @@ void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
m_hBar->height()));
-#if USE(ACCELERATED_COMPOSITING)
- if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
- if (m_hBar) {
- layer->setPosition(m_hBar->frameRect().location() - offsetFromLayer);
- layer->setSize(m_hBar->frameRect().size());
- }
- layer->setDrawsContent(m_hBar);
- }
- if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
- if (m_vBar) {
- layer->setPosition(m_vBar->frameRect().location() - offsetFromLayer);
- layer->setSize(m_vBar->frameRect().size());
- }
- layer->setDrawsContent(m_vBar);
- }
-
- if (GraphicsLayer* layer = layerForScrollCorner()) {
- const LayoutRect& scrollCornerAndResizer = scrollCornerAndResizerRect();
- layer->setPosition(scrollCornerAndResizer.location());
- layer->setSize(scrollCornerAndResizer.size());
- layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
- }
-#endif
-
if (m_scrollCorner)
m_scrollCorner->setFrameRect(scrollCorner);
if (m_resizer)
m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (isComposited())
+ backing()->positionOverflowControlsLayers(offsetFromRoot);
+#endif
}
int RenderLayer::scrollWidth() const
@@ -2626,6 +2636,12 @@ void RenderLayer::updateScrollInfoAfterLayout()
if (originalScrollOffset != scrollOffset())
scrollToOffsetWithoutAnimation(toPoint(scrollOffset()));
+
+#if USE(ACCELERATED_COMPOSITING)
+ // Composited scrolling may need to be enabled or disabled if the amount of overflow changed.
+ if (renderer()->view() && compositor()->updateLayerCompositingState(this))
+ compositor()->setCompositingLayersNeedRebuild();
+#endif
}
void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
@@ -3009,7 +3025,8 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
// Make sure the parent's clip rects have been calculated.
ClipRect clipRect = paintDirtyRect;
if (parent()) {
- clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects);
+ clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
+ IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
clipRect.intersect(paintDirtyRect);
// Push the parent coordinate space's clip.
@@ -3093,6 +3110,18 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
// Ensure our lists are up-to-date.
updateLayerListsIfNeeded();
+ // Apply clip-path to context.
+ RenderStyle* style = renderer()->style();
+ if (renderer()->hasClipPath() && !context->paintingDisabled() && style) {
+ if (BasicShape* clipShape = style->clipPath()) {
+ // FIXME: Investigate if it is better to store and update a Path object in RenderStyle.
+ // https://bugs.webkit.org/show_bug.cgi?id=95619
+ Path clipPath;
+ clipShape->path(clipPath, calculateLayerBounds(this, rootLayer, 0));
+ transparencyLayerContext->clipPath(clipPath, clipShape->windRule());
+ }
+ }
+
#if ENABLE(CSS_FILTERS)
FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
@@ -3125,7 +3154,8 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
#endif
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
- calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+ calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect,
+ IgnoreOverlayScrollbarSize, localPaintFlags & PaintLayerPaintingOverflowContents ? IgnoreOverflowClip : RespectOverflowClip);
paintOffset = toPoint(layerBounds.location() - renderBoxLocation() + subPixelAccumulation);
}
@@ -3144,7 +3174,8 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
performOverlapTests(*overlapTestRequests, rootLayer, this);
// We want to paint our layer, but only if we intersect the damage rect.
- shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
+ if (this != rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents))
+ shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
if (localPaintFlags & PaintLayerPaintingCompositingBackgroundPhase) {
if (shouldPaintContent && !selectionOnly) {
@@ -3411,10 +3442,10 @@ static inline LayoutRect frameVisibleRect(RenderObject* renderer)
bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
{
- return hitTest(request, result.hitTestPoint(), result);
+ return hitTest(request, result.hitTestLocation(), result);
}
-bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestPoint& hitTestPoint, HitTestResult& result)
+bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result)
{
renderer()->document()->updateLayout();
@@ -3422,12 +3453,12 @@ bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestPoint& hit
if (!request.ignoreClipping())
hitTestArea.intersect(frameVisibleRect(renderer()));
- RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestPoint, false);
+ RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestLocation, false);
if (!insideLayer) {
// We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
// return ourselves. We do this so mouse events continue getting delivered after a drag has
// exited the WebView, and so hit testing over a scrollbar hits the content document.
- if ((request.active() || request.release()) && isRootLayer()) {
+ if (!request.isChildFrameHitTest() && (request.active() || request.release()) && isRootLayer()) {
renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(result.point()));
insideLayer = this;
}
@@ -3474,7 +3505,7 @@ static double computeZOffset(const HitTestingTransformState& transformState)
}
PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
- const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint,
+ const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
const HitTestingTransformState* containerTransformState) const
{
RefPtr<HitTestingTransformState> transformState;
@@ -3484,9 +3515,9 @@ PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(Rend
transformState = HitTestingTransformState::create(*containerTransformState);
convertToLayerCoords(containerLayer, offset);
} else {
- // If this is the first time we need to make transform state, then base it off of hitTestPoint,
+ // If this is the first time we need to make transform state, then base it off of hitTestLocation,
// which is relative to rootLayer.
- transformState = HitTestingTransformState::create(hitTestPoint.transformedPoint(), hitTestPoint.transformedRect(), FloatQuad(hitTestRect));
+ transformState = HitTestingTransformState::create(hitTestLocation.transformedPoint(), hitTestLocation.transformedRect(), FloatQuad(hitTestRect));
convertToLayerCoords(rootLayer, offset);
}
@@ -3527,16 +3558,16 @@ static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, doubl
return true;
}
-// hitTestPoint and hitTestRect are relative to rootLayer.
+// hitTestLocation and hitTestRect are relative to rootLayer.
// A 'flattening' layer is one preserves3D() == false.
// transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
-// transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer.
+// transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the containing flattening layer.
// transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
//
// If zOffset is non-null (which indicates that the caller wants z offset information),
// *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint, bool appliedTransform,
+ const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, bool appliedTransform,
const HitTestingTransformState* transformState, double* zOffset)
{
// The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
@@ -3547,14 +3578,14 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
if (transform() && !appliedTransform) {
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- ClipRect clipRect = backgroundClipRect(rootLayer, hitTestPoint.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ ClipRect clipRect = backgroundClipRect(rootLayer, hitTestLocation.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, IncludeOverlayScrollbarSize);
// Go ahead and test the enclosing clip now.
- if (!clipRect.intersects(hitTestPoint))
+ if (!clipRect.intersects(hitTestLocation))
return 0;
}
// Create a transform state to accumulate this transform.
- RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
+ RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState);
// If the transform can't be inverted, then don't hit test this layer at all.
if (!newTransformState->m_accumulatedTransform.isInvertible())
@@ -3564,19 +3595,19 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
// from the transformState, which store the point and quad in the coords of the last flattened
// layer, and the accumulated transform which lets up map through preserve-3d layers.
//
- // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
+ // We can't just map hitTestLocation and hitTestRect because they may have been flattened (losing z)
// by our container.
FloatPoint localPoint = newTransformState->mappedPoint();
FloatQuad localPointQuad = newTransformState->mappedQuad();
LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea();
- HitTestPoint newHitTestPoint;
- if (hitTestPoint.isRectBasedTest())
- newHitTestPoint = HitTestPoint(localPoint, localPointQuad);
+ HitTestLocation newHitTestLocation;
+ if (hitTestLocation.isRectBasedTest())
+ newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
else
- newHitTestPoint = HitTestPoint(localPoint);
+ newHitTestLocation = HitTestLocation(localPoint);
// Now do a hit test with the root layer shifted to be us.
- return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestPoint, true, newTransformState.get(), zOffset);
+ return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestLocation, true, newTransformState.get(), zOffset);
}
// Ensure our lists and 3d status are up-to-date.
@@ -3590,7 +3621,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
localTransformState = const_cast<HitTestingTransformState*>(transformState);
} else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
// We need transform state for the first time, or to offset the container state, so create it here.
- localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
+ localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState);
}
// Check for hit test on backface if backface-visibility is 'hidden'
@@ -3614,7 +3645,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
ClipRect bgRect;
ClipRect fgRect;
ClipRect outlineRect;
- calculateRects(rootLayer, hitTestPoint.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, IncludeOverlayScrollbarSize);
+ calculateRects(rootLayer, hitTestLocation.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, IncludeOverlayScrollbarSize);
// The following are used for keeping track of the z-depth of the hit point of 3d-transformed
// descendants.
@@ -3643,7 +3674,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
RenderLayer* candidateLayer = 0;
// Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
- RenderLayer* hitLayer = hitTestList(posZOrderList(), rootLayer, request, result, hitTestRect, hitTestPoint,
+ RenderLayer* hitLayer = hitTestList(posZOrderList(), rootLayer, request, result, hitTestRect, hitTestLocation,
localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
if (hitLayer) {
if (!depthSortDescendants)
@@ -3652,7 +3683,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
}
// Now check our overflow objects.
- hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint,
+ hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestLocation,
localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
if (hitLayer) {
if (!depthSortDescendants)
@@ -3661,11 +3692,11 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
}
// Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
- if (fgRect.intersects(hitTestPoint) && isSelfPaintingLayer()) {
+ if (fgRect.intersects(hitTestLocation) && isSelfPaintingLayer()) {
// Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
- HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
- if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
- isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
+ HitTestResult tempResult(result.hitTestLocation());
+ if (hitTestContents(request, tempResult, layerBounds, hitTestLocation, HitTestDescendants)
+ && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
if (result.isRectBasedTest())
result.append(tempResult);
else
@@ -3679,7 +3710,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
}
// Now check our negative z-index children.
- hitLayer = hitTestList(negZOrderList(), rootLayer, request, result, hitTestRect, hitTestPoint,
+ hitLayer = hitTestList(negZOrderList(), rootLayer, request, result, hitTestRect, hitTestLocation,
localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
if (hitLayer) {
if (!depthSortDescendants)
@@ -3691,25 +3722,26 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
if (candidateLayer)
return candidateLayer;
- if (bgRect.intersects(hitTestPoint) && isSelfPaintingLayer()) {
- HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
- if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
- isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
+ if (bgRect.intersects(hitTestLocation) && isSelfPaintingLayer()) {
+ HitTestResult tempResult(result.hitTestLocation());
+ if (hitTestContents(request, tempResult, layerBounds, hitTestLocation, HitTestSelf)
+ && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
if (result.isRectBasedTest())
result.append(tempResult);
else
result = tempResult;
return this;
- } else if (result.isRectBasedTest())
+ }
+ if (result.isRectBasedTest())
result.append(tempResult);
}
return 0;
}
-bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestPoint& hitTestPoint, HitTestFilter hitTestFilter) const
+bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter) const
{
- if (!renderer()->hitTest(request, result, hitTestPoint,
+ if (!renderer()->hitTest(request, result, hitTestLocation,
toLayoutPoint(layerBounds.location() - renderBoxLocation()),
hitTestFilter)) {
// It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
@@ -3735,7 +3767,7 @@ bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult&
RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint,
+ const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
const HitTestingTransformState* transformState,
double* zOffsetForDescendants, double* zOffset,
const HitTestingTransformState* unflattenedTransformState,
@@ -3748,11 +3780,11 @@ RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* r
for (int i = list->size() - 1; i >= 0; --i) {
RenderLayer* childLayer = list->at(i);
RenderLayer* hitLayer = 0;
- HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
+ HitTestResult tempResult(result.hitTestLocation());
if (childLayer->isPaginated())
- hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
+ hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestLocation, transformState, zOffsetForDescendants);
else
- hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants);
+ hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
// If it a rect-based test, we can safely append the temporary result since it might had hit
// nodes but not necesserily had hitLayer set.
@@ -3772,7 +3804,7 @@ RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* r
}
RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset)
+ const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
{
Vector<RenderLayer*> columnLayers;
RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
@@ -3784,12 +3816,12 @@ RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, Re
}
ASSERT(columnLayers.size());
- return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset,
+ return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset,
columnLayers, columnLayers.size() - 1);
}
RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset,
+ const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
{
RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
@@ -3846,7 +3878,7 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
LayoutRect localClipRect(hitTestRect);
localClipRect.intersect(colRect);
- if (!localClipRect.isEmpty() && hitTestPoint.intersects(localClipRect)) {
+ if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect)) {
RenderLayer* hitLayer = 0;
if (!columnIndex) {
// Apply a translation transform to change where the layer paints.
@@ -3858,7 +3890,7 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
newTransform.translateRight(offset.width(), offset.height());
childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
- hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset);
+ hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestLocation, false, transformState, zOffset);
if (oldHasTransform)
childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
else
@@ -3867,19 +3899,19 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
// Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
// This involves subtracting out the position of the layer in our current coordinate space.
RenderLayer* nextLayer = columnLayers[columnIndex - 1];
- RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState);
+ RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestLocation, transformState);
newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
FloatPoint localPoint = newTransformState->mappedPoint();
FloatQuad localPointQuad = newTransformState->mappedQuad();
LayoutRect localHitTestRect = newTransformState->mappedArea().enclosingBoundingBox();
- HitTestPoint newHitTestPoint;
- if (hitTestPoint.isRectBasedTest())
- newHitTestPoint = HitTestPoint(localPoint, localPointQuad);
+ HitTestLocation newHitTestLocation;
+ if (hitTestLocation.isRectBasedTest())
+ newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
else
- newHitTestPoint = HitTestPoint(localPoint);
+ newHitTestLocation = HitTestLocation(localPoint);
newTransformState->flatten();
- hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestPoint,
+ hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestLocation,
newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
}
@@ -3891,11 +3923,12 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
return 0;
}
-void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy)
+void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip)
{
ASSERT(clipRectsType < NumCachedClipRectsTypes);
if (m_clipRectsCache && m_clipRectsCache->m_clipRects[clipRectsType]) {
ASSERT(rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
+ ASSERT(m_clipRectsCache->m_respectingOverflowClip[clipRectsType] == (respectOverflowClip == RespectOverflowClip));
return; // We have the correct cached value.
}
@@ -3903,10 +3936,10 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* re
// examine the parent. We want to cache clip rects with us as the root.
RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
if (parentLayer)
- parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy);
+ parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
ClipRects clipRects;
- calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
+ calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
if (!m_clipRectsCache)
m_clipRectsCache = adoptPtr(new ClipRectsCache);
@@ -3918,10 +3951,11 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* re
#ifndef NDEBUG
m_clipRectsCache->m_clipRectsRoot[clipRectsType] = rootLayer;
+ m_clipRectsCache->m_respectingOverflowClip[clipRectsType] = respectOverflowClip == RespectOverflowClip;
#endif
}
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
{
if (!parent()) {
// The root layer's clip rect is always infinite.
@@ -3940,7 +3974,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
if (useCached && parentLayer->clipRects(clipRectsType))
clipRects = *parentLayer->clipRects(clipRectsType);
else
- parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects);
+ parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects, IgnoreOverlayScrollbarSize, respectOverflowClip);
} else
clipRects.reset(PaintInfo::infiniteRect());
@@ -3956,7 +3990,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
clipRects.setOverflowClipRect(clipRects.posClipRect());
// Update the clip rects that will be passed to child layers.
- if (renderer()->hasClipOrOverflowClip()) {
+ if ((renderer()->hasOverflowClip() && (respectOverflowClip == RespectOverflowClip || this != rootLayer)) || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
// This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
@@ -3975,7 +4009,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
if (renderer()->style()->hasBorderRadius())
newOverflowClip.setHasRadius(true);
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
- if (renderer()->isOutOfFlowPositioned() || renderer()->isInFlowPositioned())
+ if (renderer()->isPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
}
if (renderer()->hasClip()) {
@@ -3987,15 +4021,15 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
}
}
-void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
+void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
{
ASSERT(parent());
if (clipRectsType == TemporaryClipRects) {
- parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
+ parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
return;
}
- parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy);
+ parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
clipRects = *parent()->clipRects(clipRectsType);
}
@@ -4010,11 +4044,11 @@ static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRect
return parentRects.overflowClipRect();
}
-ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy) const
+ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
{
ASSERT(parent());
ClipRects parentRects;
- parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy);
+ parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy, respectOverflowClip);
ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
RenderView* view = renderer()->view();
ASSERT(view);
@@ -4027,10 +4061,10 @@ ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderReg
}
void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
- ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy) const
+ ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
{
if (rootLayer != this && parent()) {
- backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy);
+ backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
backgroundRect.intersect(paintDirtyRect);
} else
backgroundRect = paintDirtyRect;
@@ -4045,7 +4079,7 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* reg
// Update the clip rects that will be passed to child layers.
if (renderer()->hasClipOrOverflowClip()) {
// This layer establishes a clip of some kind.
- if (renderer()->hasOverflowClip()) {
+ if (renderer()->hasOverflowClip() && (this != rootLayer || respectOverflowClip == RespectOverflowClip)) {
foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, region, relevancy));
if (renderer()->style()->hasBorderRadius())
foregroundRect.setHasRadius(true);
@@ -4068,12 +4102,14 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* reg
LayoutRect layerBoundsWithVisualOverflow = renderBox()->visualOverflowRect();
renderBox()->flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
layerBoundsWithVisualOverflow.moveBy(offset);
- backgroundRect.intersect(layerBoundsWithVisualOverflow);
+ if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
+ backgroundRect.intersect(layerBoundsWithVisualOverflow);
} else {
// Shift the bounds to be for our region only.
LayoutRect bounds = renderBox()->borderBoxRectInRegion(region);
bounds.moveBy(offset);
- backgroundRect.intersect(bounds);
+ if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
+ backgroundRect.intersect(bounds);
}
}
}
@@ -4086,7 +4122,8 @@ LayoutRect RenderLayer::childrenClipRect() const
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
- calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ // Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
+ calculateRects(clippingRootLayer, 0, TemporaryClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
}
@@ -4396,6 +4433,9 @@ RenderLayerBacking* RenderLayer::ensureBacking()
#if ENABLE(CSS_FILTERS)
updateOrRemoveFilterEffect();
#endif
+#if ENABLE(CSS_COMPOSITING)
+ backing()->setBlendMode(m_blendMode);
+#endif
}
return m_backing.get();
}
@@ -4777,19 +4817,24 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
|| renderer()->isEmbeddedObject()
|| renderer()->isRenderIFrame()
|| (renderer()->style()->specifiesColumns() && !isRootLayer()))
- && !renderer()->isOutOfFlowPositioned()
- && !renderer()->isInFlowPositioned()
+ && !renderer()->isPositioned()
&& !renderer()->hasTransform()
+ && !renderer()->hasClipPath()
#if ENABLE(CSS_FILTERS)
&& !renderer()->hasFilter()
#endif
- && !isTransparent();
+#if ENABLE(CSS_COMPOSITING)
+ && !renderer()->hasBlendMode()
+#endif
+ && !isTransparent()
+ && !usesCompositedScrolling();
}
bool RenderLayer::shouldBeSelfPaintingLayer() const
{
return !isNormalFlowOnly()
|| hasOverlayScrollbars()
+ || usesCompositedScrolling()
|| renderer()->hasReflection()
|| renderer()->hasMask()
|| renderer()->isTableRow()
@@ -4935,6 +4980,9 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
updateDescendantDependentFlags();
updateTransform();
+#if ENABLE(CSS_COMPOSITING)
+ updateBlendMode();
+#endif
#if USE(ACCELERATED_COMPOSITING)
if (compositor()->updateLayerCompositingState(this))
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index e4f790e05..32d41e3ba 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -115,7 +115,7 @@ public:
bool isEmpty() const { return m_rect.isEmpty(); }
bool intersects(const LayoutRect& rect) { return m_rect.intersects(rect); }
- bool intersects(const HitTestPoint&);
+ bool intersects(const HitTestLocation&);
private:
LayoutRect m_rect;
@@ -230,14 +230,17 @@ struct ClipRectsCache {
ClipRectsCache()
{
#ifndef NDEBUG
- for (int i = 0; i < NumCachedClipRectsTypes; ++i)
+ for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
m_clipRectsRoot[i] = 0;
+ m_respectingOverflowClip[i] = false;
+ }
#endif
}
RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes];
#ifndef NDEBUG
const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
+ bool m_respectingOverflowClip[NumCachedClipRectsTypes];
#endif
};
@@ -504,6 +507,7 @@ public:
PaintLayerPaintingCompositingBackgroundPhase = 1 << 5,
PaintLayerPaintingCompositingForegroundPhase = 1 << 6,
PaintLayerPaintingCompositingMaskPhase = 1 << 7,
+ PaintLayerPaintingOverflowContents = 1 << 8,
PaintLayerPaintingCompositingAllPhases = (PaintLayerPaintingCompositingBackgroundPhase | PaintLayerPaintingCompositingForegroundPhase | PaintLayerPaintingCompositingMaskPhase)
};
@@ -516,21 +520,23 @@ public:
void paint(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior = PaintBehaviorNormal, RenderObject* paintingRoot = 0,
RenderRegion* = 0, PaintLayerFlags = 0);
bool hitTest(const HitTestRequest&, HitTestResult&);
- bool hitTest(const HitTestRequest&, const HitTestPoint&, HitTestResult&);
+ bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior, RenderObject* paintingRoot);
+ enum ShouldRespectOverflowClip { IgnoreOverflowClip, RespectOverflowClip };
+
// This method figures out our layerBounds in coordinates relative to
// |rootLayer}. It also computes our background and foreground clip rects
// for painting/event handling.
void calculateRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect,
- OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
// Compute and cache clip rects computed with the given layer as the root
- void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
+ void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip);
// 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 RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ void calculateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
ClipRects* clipRects(ClipRectsType type) const { ASSERT(type < NumCachedClipRectsTypes); return m_clipRectsCache ? m_clipRectsCache->m_clipRects[type].get() : 0; }
@@ -568,7 +574,7 @@ public:
enum UpdateLayerPositionsAfterScrollFlag {
NoFlag = 0,
- HasSeenFixedPositionedAncestor = 1 << 0,
+ HasSeenViewportConstrainedAncestor = 1 << 0,
HasSeenAncestorWithOverflowClip = 1 << 1
};
@@ -606,6 +612,12 @@ public:
bool hasFilter() const { return false; }
#endif
+#if ENABLE(CSS_COMPOSITING)
+ bool hasBlendMode() const { return renderer()->hasBlendMode(); }
+#else
+ bool hasBlendMode() const { return false; }
+#endif
+
// Overloaded new operator. Derived classes must override operator new
// in order to allocate out of the RenderArena.
void* operator new(size_t, RenderArena*);
@@ -622,9 +634,11 @@ public:
virtual GraphicsLayer* layerForHorizontalScrollbar() const;
virtual GraphicsLayer* layerForVerticalScrollbar() const;
virtual GraphicsLayer* layerForScrollCorner() const;
+ virtual bool usesCompositedScrolling() const OVERRIDE;
#else
bool isComposited() const { return false; }
bool hasCompositedMask() const { return false; }
+ bool usesCompositedScrolling() const { return false; }
#endif
bool paintsWithTransparency(PaintBehavior paintBehavior) const
@@ -663,6 +677,8 @@ public:
void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; }
#endif
+ Node* enclosingElement() const;
+
private:
void updateZOrderLists();
void rebuildZOrderLists();
@@ -737,25 +753,25 @@ private:
PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint&, bool appliedTransform,
+ const LayoutRect& hitTestRect, const HitTestLocation&, bool appliedTransform,
const HitTestingTransformState* transformState = 0, double* zOffset = 0);
RenderLayer* hitTestList(Vector<RenderLayer*>*, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint&,
+ const LayoutRect& hitTestRect, const HitTestLocation&,
const HitTestingTransformState* transformState, double* zOffsetForDescendants, double* zOffset,
const HitTestingTransformState* unflattenedTransformState, bool depthSortDescendants);
RenderLayer* hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint&,
+ const LayoutRect& hitTestRect, const HitTestLocation&,
const HitTestingTransformState* transformState, double* zOffset);
RenderLayer* hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
- const LayoutRect& hitTestRect, const HitTestPoint&,
+ const LayoutRect& hitTestRect, const HitTestLocation&,
const HitTestingTransformState* transformState, double* zOffset,
const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
PassRefPtr<HitTestingTransformState> createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
- const LayoutRect& hitTestRect, const HitTestPoint&,
+ const LayoutRect& hitTestRect, const HitTestLocation&,
const HitTestingTransformState* containerTransformState) const;
- bool hitTestContents(const HitTestRequest&, HitTestResult&, const LayoutRect& layerBounds, const HitTestPoint&, HitTestFilter) const;
+ bool hitTestContents(const HitTestRequest&, HitTestResult&, const LayoutRect& layerBounds, const HitTestLocation&, HitTestFilter) const;
void computeScrollDimensions();
bool hasHorizontalOverflow() const;
@@ -816,8 +832,6 @@ private:
// Both updates the status, and returns true if descendants of this have 3d.
bool update3DTransformedDescendantStatus();
- Node* enclosingElement() const;
-
void createReflection();
void removeReflection();
@@ -829,8 +843,8 @@ private:
void updateOrRemoveFilterEffect();
#endif
- void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
- ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, ClipRects&, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
+ ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip) const;
LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
RenderLayer* enclosingTransformedAncestor() const;
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 6641bbc56..26cd50f50 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -55,8 +55,8 @@
#include "Settings.h"
#include "StyleResolver.h"
#include "TiledBacking.h"
-
#include <wtf/CurrentTime.h>
+#include <wtf/text/StringBuilder.h>
#if ENABLE(CSS_FILTERS)
#include "FilterEffectRenderer.h"
@@ -138,6 +138,7 @@ RenderLayerBacking::~RenderLayerBacking()
updateOverflowControlsLayers(false, false, false);
updateForegroundLayer(false);
updateMaskLayer(false);
+ updateScrollingLayers(false);
destroyGraphicsLayers();
}
@@ -218,6 +219,9 @@ void RenderLayerBacking::destroyGraphicsLayers()
m_foregroundLayer = nullptr;
m_containmentLayer = nullptr;
m_maskLayer = nullptr;
+
+ m_scrollingLayer = nullptr;
+ m_scrollingContentsLayer = nullptr;
}
void RenderLayerBacking::updateLayerOpacity(const RenderStyle* style)
@@ -258,10 +262,10 @@ static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
|| (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
}
-static bool layerOrAncestorIsTransformed(RenderLayer* layer)
+static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
{
for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
- if (curr->hasTransform())
+ if (curr->hasTransform() || curr->usesCompositedScrolling())
return true;
}
@@ -280,7 +284,7 @@ bool RenderLayerBacking::shouldClipCompositedBounds() const
if (!compositor()->compositingConsultsOverlap())
return false;
- if (layerOrAncestorIsTransformed(m_owningLayer))
+ if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
return false;
return true;
@@ -366,12 +370,21 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
layerConfigChanged = true;
- if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
+ bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
+
+ // Our scrolling layer will clip.
+ if (m_owningLayer->usesCompositedScrolling())
+ needsDescendentsClippingLayer = false;
+
+ if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer))
layerConfigChanged = true;
if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
layerConfigChanged = true;
+ if (updateScrollingLayers(m_owningLayer->usesCompositedScrolling()))
+ layerConfigChanged = true;
+
if (layerConfigChanged)
updateInternalHierarchy();
@@ -520,12 +533,19 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
graphicsLayerParentLocation = ancestorCompositingBounds.location();
else
graphicsLayerParentLocation = renderer()->view()->documentRect().location();
+
+ if (compAncestor && compAncestor->usesCompositedScrolling()) {
+ RenderBox* renderBox = toRenderBox(compAncestor->renderer());
+ IntSize scrollOffset = compAncestor->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.
- IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects).rect()); // FIXME: Incorrect for CSS regions.
+ IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, RenderLayer::IgnoreOverflowClip).rect()); // FIXME: Incorrect for CSS regions.
ASSERT(parentClipRect != PaintInfo::infiniteRect());
m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
m_ancestorClippingLayer->setSize(parentClipRect.size());
@@ -633,6 +653,36 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location()));
}
+ if (m_scrollingLayer) {
+ ASSERT(m_scrollingContentsLayer);
+ RenderBox* renderBox = toRenderBox(renderer());
+ IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
+ IntSize scrollOffset = m_owningLayer->scrolledContentOffset();
+
+ m_scrollingLayer->setPosition(FloatPoint() + (paddingBox.location() - localCompositingBounds.location()));
+
+ m_scrollingLayer->setSize(paddingBox.size());
+ m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
+
+ IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
+ m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location());
+
+ bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
+
+ IntSize scrollSize(m_owningLayer->scrollWidth(), m_owningLayer->scrollHeight());
+ if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
+ m_scrollingContentsLayer->setNeedsDisplay();
+
+ IntSize scrollingContentsOffset = paddingBox.location() - IntPoint() - scrollOffset;
+ if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
+ compositor()->scrollingLayerDidChange(m_owningLayer);
+
+ m_scrollingContentsLayer->setSize(scrollSize);
+ // FIXME: Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
+ // FIXME: The paint offset and the scroll offset should really be separate concepts.
+ m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset);
+ }
+
m_graphicsLayer->setContentsRect(contentsBox());
// If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
@@ -657,6 +707,12 @@ void RenderLayerBacking::updateInternalHierarchy()
m_graphicsLayer->addChild(m_containmentLayer.get());
}
+ if (m_scrollingLayer) {
+ GraphicsLayer* superlayer = m_containmentLayer ? m_containmentLayer.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.
@@ -676,6 +732,19 @@ void RenderLayerBacking::updateInternalHierarchy()
void RenderLayerBacking::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() && hasBoxDecorationsOrBackground(renderer());
+ m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
+
+ bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
+ m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
+ return;
+ }
+
bool hasPaintedContent = containsPaintedContent();
// FIXME: we could refine this to only allocate backing for one of these layers if possible.
@@ -779,6 +848,35 @@ bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScroll
return layersChanged;
}
+void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
+{
+ IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
+ if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+ Scrollbar* hBar = m_owningLayer->horizontalScrollbar();
+ if (hBar) {
+ layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
+ layer->setSize(hBar->frameRect().size());
+ }
+ layer->setDrawsContent(hBar);
+ }
+
+ if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+ Scrollbar* vBar = m_owningLayer->verticalScrollbar();
+ if (vBar) {
+ layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
+ layer->setSize(vBar->frameRect().size());
+ }
+ layer->setDrawsContent(vBar);
+ }
+
+ if (GraphicsLayer* layer = layerForScrollCorner()) {
+ const LayoutRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
+ layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
+ layer->setSize(scrollCornerAndResizer.size());
+ layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
+ }
+}
+
bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
{
bool layerChanged = false;
@@ -826,6 +924,41 @@ bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
return layerChanged;
}
+bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
+{
+ bool layerChanged = false;
+ if (needsScrollingLayers) {
+ if (!m_scrollingLayer) {
+ // Outer layer which corresponds with the scroll view.
+ m_scrollingLayer = createGraphicsLayer("Scrolling container");
+ m_scrollingLayer->setDrawsContent(false);
+ m_scrollingLayer->setMasksToBounds(true);
+
+ // Inner layer which renders the content that scrolls.
+ m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
+ m_scrollingContentsLayer->setDrawsContent(true);
+ m_scrollingContentsLayer->setPaintingPhase(GraphicsLayerPaintForeground | GraphicsLayerPaintOverflowContents);
+ m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
+
+ layerChanged = true;
+ }
+ } else if (m_scrollingLayer) {
+ m_scrollingLayer = nullptr;
+ m_scrollingContentsLayer = nullptr;
+ layerChanged = true;
+ }
+
+ if (layerChanged) {
+ updateInternalHierarchy();
+ m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+ m_graphicsLayer->setNeedsDisplay();
+ if (renderer()->view())
+ compositor()->scrollingLayerDidChange(m_owningLayer);
+ }
+
+ return layerChanged;
+}
+
GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
{
unsigned phase = GraphicsLayerPaintBackground;
@@ -834,6 +967,9 @@ GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() co
if (!m_maskLayer)
phase |= GraphicsLayerPaintMask;
+ if (m_scrollingContentsLayer)
+ phase &= ~GraphicsLayerPaintForeground;
+
return static_cast<GraphicsLayerPaintingPhase>(phase);
}
@@ -1166,6 +1302,14 @@ IntRect RenderLayerBacking::contentsBox() const
return contentsRect;
}
+GraphicsLayer* RenderLayerBacking::parentForSublayers() const
+{
+ if (m_scrollingContentsLayer)
+ return m_scrollingContentsLayer.get();
+
+ return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
+}
+
bool RenderLayerBacking::paintsIntoWindow() const
{
if (m_usingTiledCacheLayer)
@@ -1214,6 +1358,9 @@ void RenderLayerBacking::setContentsNeedDisplay()
if (m_maskLayer && m_maskLayer->drawsContent())
m_maskLayer->setNeedsDisplay();
+
+ if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
+ m_scrollingContentsLayer->setNeedsDisplay();
}
// r is in the coordinate space of the layer's render object
@@ -1238,6 +1385,12 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
}
+
+ if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
+ IntRect layerDirtyRect = r;
+ layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
+ m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
+ }
}
void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
@@ -1259,7 +1412,9 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
if (paintingPhase & GraphicsLayerPaintMask)
paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
-
+ if (paintingPhase & GraphicsLayerPaintOverflowContents)
+ paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
+
// FIXME: GraphicsLayers need a way to split for RenderRegions.
m_owningLayer->paintLayerContents(rootLayer, context, paintDirtyRect, LayoutSize(), paintBehavior, paintingRoot, 0, 0, paintFlags);
@@ -1290,12 +1445,14 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
if (Page* page = renderer()->frame()->page())
page->setIsPainting(true);
#endif
- if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) {
+
+ if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get() || graphicsLayer == m_scrollingContentsLayer.get()) {
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), &context, clip);
// The dirtyRect is in the coords of the painting root.
- IntRect dirtyRect = compositedBounds();
- dirtyRect.intersect(clip);
+ IntRect dirtyRect = clip;
+ if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
+ dirtyRect.intersect(compositedBounds());
// We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
@@ -1590,29 +1747,35 @@ AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID
String RenderLayerBacking::nameForLayer() const
{
- String name = renderer()->renderName();
+ StringBuilder name;
+ name.append(renderer()->renderName());
if (Node* node = renderer()->node()) {
- if (node->isElementNode())
- name += " " + static_cast<Element*>(node)->tagName();
- if (node->hasID())
- name += " id=\'" + static_cast<Element*>(node)->getIdAttribute() + "\'";
+ if (node->isElementNode()) {
+ name.append(' ');
+ name.append(static_cast<Element*>(node)->tagName());
+ }
+ if (node->hasID()) {
+ name.appendLiteral(" id=\'");
+ name.append(static_cast<Element*>(node)->getIdAttribute());
+ name.append('\'');
+ }
if (node->hasClass()) {
+ name.appendLiteral(" class=\'");
StyledElement* styledElement = static_cast<StyledElement*>(node);
- String classes;
for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
if (i > 0)
- classes += " ";
- classes += styledElement->classNames()[i];
+ name.append(' ');
+ name.append(styledElement->classNames()[i]);
}
- name += " class=\'" + classes + "\'";
+ name.append('\'');
}
}
if (m_owningLayer->isReflection())
- name += " (reflection)";
+ name.appendLiteral(" (reflection)");
- return name;
+ return name.toString();
}
CompositingLayerType RenderLayerBacking::compositingLayerType() const
@@ -1637,6 +1800,9 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const
if (m_maskLayer)
backingMemory += m_maskLayer->backingStoreMemoryEstimate();
+ if (m_scrollingContentsLayer)
+ backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
+
if (m_layerForHorizontalScrollbar)
backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
diff --git a/Source/WebCore/rendering/RenderLayerBacking.h b/Source/WebCore/rendering/RenderLayerBacking.h
index f107dc279..0508b52bb 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.h
+++ b/Source/WebCore/rendering/RenderLayerBacking.h
@@ -83,10 +83,14 @@ public:
bool hasContentsLayer() const { return m_foregroundLayer != 0; }
GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); }
+
+ bool hasScrollingLayer() const { return m_scrollingLayer; }
+ GraphicsLayer* scrollingLayer() const { return m_scrollingLayer.get(); }
+ GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
bool hasMaskLayer() const { return m_maskLayer != 0; }
- GraphicsLayer* parentForSublayers() const { return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get(); }
+ GraphicsLayer* parentForSublayers() const;
GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer.get() : m_graphicsLayer.get(); }
// RenderLayers with backing normally short-circuit paintLayer() because
@@ -127,6 +131,7 @@ public:
void updateCompositedBounds();
void updateAfterWidgetResize();
+ void positionOverflowControlsLayers(const IntSize& offsetFromRoot);
// GraphicsLayerClient interface
virtual bool shouldUseTileCache(const GraphicsLayer*) const;
@@ -186,6 +191,7 @@ private:
bool requiresHorizontalScrollbarLayer() const;
bool requiresVerticalScrollbarLayer() const;
bool requiresScrollCornerLayer() const;
+ bool updateScrollingLayers(bool scrollingLayers);
GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
@@ -247,6 +253,9 @@ private:
OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
OwnPtr<GraphicsLayer> m_layerForScrollCorner;
+ 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.
+
IntRect m_compositedBounds;
bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 72ba4c2f8..f967233ef 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -1025,7 +1025,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
// 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 (!layerBacking->hasClippingLayer()) {
+ if (!layerBacking->hasClippingLayer() && !layerBacking->hasScrollingLayer()) {
if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) {
overflowControlLayer->removeFromParent();
layerBacking->parentForSublayers()->addChild(overflowControlLayer);
@@ -1092,6 +1092,13 @@ void RenderLayerCompositor::frameViewDidScroll()
m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
}
+void RenderLayerCompositor::scrollingLayerDidChange(RenderLayer* layer)
+{
+ RenderLayerBacking* backing = layer->backing();
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer, backing ? backing->scrollingContentsLayer() : 0);
+}
+
String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo)
{
updateCompositingLayers(CompositingUpdateAfterLayout);
@@ -1444,7 +1451,9 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
|| clipsCompositingDescendants(layer)
|| requiresCompositingForAnimation(renderer)
|| requiresCompositingForFilters(renderer)
- || requiresCompositingForPosition(renderer, layer);
+ || requiresCompositingForPosition(renderer, layer)
+ || requiresCompositingForOverflowScrolling(layer)
+ || requiresCompositingForBlending(renderer);
}
bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
@@ -1472,7 +1481,9 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, co
|| (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
|| requiresCompositingForAnimation(renderer)
|| requiresCompositingForFilters(renderer)
+ || requiresCompositingForBlending(renderer)
|| requiresCompositingForPosition(renderer, layer)
+ || requiresCompositingForOverflowScrolling(layer)
|| renderer->isTransparent()
|| renderer->hasMask()
|| renderer->hasReflection()
@@ -1530,6 +1541,9 @@ const char* RenderLayerCompositor::reasonForCompositing(const RenderLayer* layer
if (requiresCompositingForPosition(renderer, layer))
return "position: fixed";
+ if (requiresCompositingForOverflowScrolling(layer))
+ return "-webkit-overflow-scrolling: touch";
+
if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForStacking)
return "stacking";
@@ -1554,6 +1568,9 @@ const char* RenderLayerCompositor::reasonForCompositing(const RenderLayer* layer
if (renderer->hasFilter())
return "filter with composited descendants";
+
+ if (renderer->hasBlendMode())
+ return "blending with composited descendants";
}
if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForPerspective)
@@ -1766,7 +1783,7 @@ bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderObject* r
// 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 && (layer->transform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection() || renderer->hasFilter())) {
+ if (hasCompositedDescendants && (layer->transform() || renderer->createsGroup() || renderer->hasReflection())) {
reason = RenderLayer::IndirectCompositingForGraphicalEffect;
return true;
}
@@ -1802,6 +1819,16 @@ bool RenderLayerCompositor::requiresCompositingForFilters(RenderObject* renderer
#endif
}
+bool RenderLayerCompositor::requiresCompositingForBlending(RenderObject* renderer) const
+{
+#if ENABLE(CSS_COMPOSITING)
+ return renderer->hasBlendMode();
+#else
+ UNUSED_PARAM(renderer);
+ return false;
+#endif
+}
+
bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer) const
{
// position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
@@ -1834,6 +1861,11 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* rendere
return true;
}
+bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer* layer) const
+{
+ return layer->usesCompositedScrolling();
+}
+
bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
{
if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index 5b87e53c4..46a97a57f 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -192,6 +192,8 @@ public:
void frameViewDidChangeSize();
void frameViewDidScroll();
+ void scrollingLayerDidChange(RenderLayer*);
+
String layerTreeAsText(bool showDebugInfo = false);
// These are named to avoid conflicts with the functions in GraphicsLayerClient
@@ -290,8 +292,10 @@ private:
bool requiresCompositingForPlugin(RenderObject*) const;
bool requiresCompositingForFrame(RenderObject*) const;
bool requiresCompositingForFilters(RenderObject*) const;
+ bool requiresCompositingForBlending(RenderObject* renderer) const;
bool requiresCompositingForScrollableFrame() const;
bool requiresCompositingForPosition(RenderObject*, const RenderLayer*) const;
+ bool requiresCompositingForOverflowScrolling(const RenderLayer*) const;
bool requiresCompositingForIndirectReason(RenderObject*, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
bool requiresScrollLayer(RootLayerAttachment) const;
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.h b/Source/WebCore/rendering/RenderLayerFilterInfo.h
index ab45a9fca..cf2be232e 100644
--- a/Source/WebCore/rendering/RenderLayerFilterInfo.h
+++ b/Source/WebCore/rendering/RenderLayerFilterInfo.h
@@ -36,6 +36,7 @@
#include "CachedSVGDocument.h"
#endif
#include "FilterOperation.h"
+#include "FractionalLayoutRect.h"
#include "LayoutTypes.h"
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
diff --git a/Source/WebCore/rendering/RenderLineBoxList.cpp b/Source/WebCore/rendering/RenderLineBoxList.cpp
index 2739d4124..ea50d52e8 100644
--- a/Source/WebCore/rendering/RenderLineBoxList.cpp
+++ b/Source/WebCore/rendering/RenderLineBoxList.cpp
@@ -273,7 +273,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
}
}
-bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) const
+bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) const
{
if (hitTestAction != HitTestForeground)
return false;
@@ -284,10 +284,10 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq
if (!firstLineBox())
return false;
- LayoutPoint point = pointInContainer.point();
+ LayoutPoint point = locationInContainer.point();
LayoutRect rect = firstLineBox()->isHorizontal() ?
- IntRect(point.x(), point.y() - pointInContainer.topPadding(), 1, pointInContainer.topPadding() + pointInContainer.bottomPadding() + 1) :
- IntRect(point.x() - pointInContainer.leftPadding(), point.y(), pointInContainer.rightPadding() + pointInContainer.leftPadding() + 1, 1);
+ IntRect(point.x(), point.y() - locationInContainer.topPadding(), 1, locationInContainer.topPadding() + locationInContainer.bottomPadding() + 1) :
+ IntRect(point.x() - locationInContainer.leftPadding(), point.y(), locationInContainer.rightPadding() + locationInContainer.leftPadding() + 1, 1);
if (!anyLineIntersectsRect(renderer, rect, accumulatedOffset))
return false;
@@ -298,9 +298,9 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq
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, pointInContainer, accumulatedOffset, root->lineTop(), root->lineBottom());
+ bool inside = curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, root->lineTop(), root->lineBottom());
if (inside) {
- renderer->updateHitTestResult(result, pointInContainer.point() - toLayoutSize(accumulatedOffset));
+ renderer->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
return true;
}
}
diff --git a/Source/WebCore/rendering/RenderLineBoxList.h b/Source/WebCore/rendering/RenderLineBoxList.h
index 2c2038295..e5b085edf 100644
--- a/Source/WebCore/rendering/RenderLineBoxList.h
+++ b/Source/WebCore/rendering/RenderLineBoxList.h
@@ -30,7 +30,7 @@
#ifndef RenderLineBoxList_h
#define RenderLineBoxList_h
-#include "RenderBox.h"
+#include "RenderObject.h"
namespace WebCore {
@@ -64,7 +64,7 @@ public:
void dirtyLinesFromChangedChild(RenderObject* parent, RenderObject* child);
void paint(RenderBoxModelObject*, PaintInfo&, const LayoutPoint&) const;
- bool hitTest(RenderBoxModelObject*, const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) const;
+ bool hitTest(RenderBoxModelObject*, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) const;
private:
bool anyLineIntersectsRect(RenderBoxModelObject*, const LayoutRect&, const LayoutPoint&, bool usePrintRect = false, LayoutUnit outlineSize = 0) const;
diff --git a/Source/WebCore/rendering/RenderListBox.cpp b/Source/WebCore/rendering/RenderListBox.cpp
index 6376b098b..db70b08a5 100644
--- a/Source/WebCore/rendering/RenderListBox.cpp
+++ b/Source/WebCore/rendering/RenderListBox.cpp
@@ -459,7 +459,7 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint&
}
}
-bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
+bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
{
if (!m_vBar || !m_vBar->shouldParticipateInHitTesting())
return false;
@@ -469,7 +469,7 @@ bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const Layout
m_vBar->width(),
height() - borderTop() - borderBottom());
- if (vertRect.contains(pointInContainer)) {
+ if (vertRect.contains(locationInContainer)) {
result.setScrollbar(m_vBar.get());
return true;
}
@@ -689,21 +689,21 @@ void RenderListBox::setScrollTop(int newTop)
scrollToOffsetWithoutAnimation(VerticalScrollbar, index);
}
-bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- if (!RenderBlock::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, hitTestAction))
+ if (!RenderBlock::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
return false;
const Vector<HTMLElement*>& listItems = selectElement()->listItems();
int size = numItems();
LayoutPoint adjustedLocation = accumulatedOffset + location();
for (int i = 0; i < size; ++i) {
- if (itemBoundingBoxRect(adjustedLocation, i).contains(pointInContainer.point())) {
+ if (itemBoundingBoxRect(adjustedLocation, i).contains(locationInContainer.point())) {
if (Element* node = listItems[i]) {
result.setInnerNode(node);
if (!result.innerNonSharedNode())
result.setInnerNonSharedNode(node);
- result.setLocalPoint(pointInContainer.point() - toLayoutSize(adjustedLocation));
+ result.setLocalPoint(locationInContainer.point() - toLayoutSize(adjustedLocation));
break;
}
}
diff --git a/Source/WebCore/rendering/RenderListBox.h b/Source/WebCore/rendering/RenderListBox.h
index 496191206..9a0110efc 100644
--- a/Source/WebCore/rendering/RenderListBox.h
+++ b/Source/WebCore/rendering/RenderListBox.h
@@ -70,14 +70,14 @@ private:
virtual void paintObject(PaintInfo&, const LayoutPoint&);
virtual LayoutRect controlClipRect(const LayoutPoint&) const;
- virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
+ virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
virtual void computePreferredLogicalWidths();
virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
- virtual void computeLogicalHeight();
+ virtual void computeLogicalHeight() OVERRIDE;
virtual void layout();
@@ -98,7 +98,7 @@ private:
virtual void setScrollLeft(int);
virtual void setScrollTop(int);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
// ScrollableArea interface.
virtual int scrollSize(ScrollbarOrientation) const OVERRIDE;
diff --git a/Source/WebCore/rendering/RenderMediaControls.h b/Source/WebCore/rendering/RenderMediaControls.h
index f9d3f3d78..8a16c2f78 100644
--- a/Source/WebCore/rendering/RenderMediaControls.h
+++ b/Source/WebCore/rendering/RenderMediaControls.h
@@ -28,12 +28,18 @@
#if ENABLE(VIDEO)
-#include "RenderObject.h"
#include "MediaControlElements.h"
namespace WebCore {
+struct PaintInfo;
+
class HTMLMediaElement;
+class IntRect;
+class IntSize;
+class RenderBox;
+class RenderObject;
+class RenderStyle;
class RenderMediaControls {
public:
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
index d2954dc3a..38a4e5a3e 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
@@ -327,6 +327,22 @@ static bool paintMediaFullscreenButton(RenderObject* object, const PaintInfo& pa
return paintMediaButton(paintInfo.context, rect, mediaFullscreenButton);
}
+static bool paintMediaClosedCaptionsButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ HTMLMediaElement* mediaElement = toParentMediaElement(object);
+ if (!mediaElement)
+ return false;
+
+ static Image* mediaClosedCaptionButton = platformResource("mediaplayerClosedCaption");
+ static Image* mediaClosedCaptionButtonDisabled = platformResource("mediaplayerClosedCaptionDisabled");
+
+ if (mediaElement->webkitClosedCaptionsVisible())
+ return paintMediaButton(paintInfo.context, rect, mediaClosedCaptionButton);
+
+ return paintMediaButton(paintInfo.context, rect, mediaClosedCaptionButtonDisabled);
+}
+
+
bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType part, RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
switch (part) {
@@ -336,6 +352,8 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType
case MediaPauseButton:
case MediaPlayButton:
return paintMediaPlayButton(object, paintInfo, rect);
+ case MediaShowClosedCaptionsButton:
+ return paintMediaClosedCaptionsButton(object, paintInfo, rect);
case MediaSlider:
return paintMediaSlider(object, paintInfo, rect);
case MediaSliderThumb:
@@ -360,7 +378,6 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType
case MediaRewindButton:
case MediaReturnToRealtimeButton:
case MediaStatusDisplay:
- case MediaShowClosedCaptionsButton:
case MediaHideClosedCaptionsButton:
case MediaTextTrackDisplayContainer:
case MediaTextTrackDisplay:
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.h b/Source/WebCore/rendering/RenderMediaControlsChromium.h
index c3b801bf0..6015cb1fc 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.h
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.h
@@ -28,12 +28,16 @@
#ifndef RenderMediaControlsChromium_h
#define RenderMediaControlsChromium_h
-#include "RenderObject.h"
#include "MediaControlElements.h"
namespace WebCore {
+struct PaintInfo;
+
class HTMLMediaElement;
+class IntRect;
+class RenderObject;
+
class RenderMediaControlsChromium {
public:
static bool paintMediaControlsPart(MediaControlElementType, RenderObject*, const PaintInfo&, const IntRect&);
diff --git a/Source/WebCore/rendering/RenderMenuList.cpp b/Source/WebCore/rendering/RenderMenuList.cpp
index 5b79d6c90..06367c726 100644
--- a/Source/WebCore/rendering/RenderMenuList.cpp
+++ b/Source/WebCore/rendering/RenderMenuList.cpp
@@ -212,7 +212,7 @@ void RenderMenuList::setTextFromOption(int optionIndex)
int size = listItems.size();
int i = select->optionToListIndex(optionIndex);
- String text = "";
+ String text = emptyString();
if (i >= 0 && i < size) {
Element* element = listItems[i];
if (element->hasTagName(optionTag)) {
diff --git a/Source/WebCore/rendering/RenderMeter.h b/Source/WebCore/rendering/RenderMeter.h
index 34909eeb0..b73218598 100644
--- a/Source/WebCore/rendering/RenderMeter.h
+++ b/Source/WebCore/rendering/RenderMeter.h
@@ -39,8 +39,8 @@ public:
virtual void updateFromElement();
private:
- virtual void computeLogicalWidth();
- virtual void computeLogicalHeight();
+ virtual void computeLogicalWidth() OVERRIDE;
+ virtual void computeLogicalHeight() OVERRIDE;
virtual const char* renderName() const { return "RenderMeter"; }
virtual bool isMeter() const { return true; }
diff --git a/Source/WebCore/rendering/RenderMultiColumnBlock.cpp b/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
index 9f6bdefb4..64271a329 100644
--- a/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
+++ b/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
@@ -78,23 +78,19 @@ bool RenderMultiColumnBlock::recomputeLogicalWidth()
return relayoutChildren;
}
-void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
+void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& /*pageLogicalHeight*/, bool& /*pageLogicalHeightChanged*/, bool& /*hasSpecifiedPageLogicalHeight*/)
{
- // We need to go ahead and set our explicit page height if one exists, so that we can
- // avoid doing multiple layout passes.
+ // We don't actually update any of the variables. We just subclassed to adjust our column height.
computeLogicalHeight();
LayoutUnit newContentLogicalHeight = contentLogicalHeight();
if (newContentLogicalHeight > ZERO_LAYOUT_UNIT) {
- pageLogicalHeight = newContentLogicalHeight;
- hasSpecifiedPageLogicalHeight = true;
+ // The regions will be invalidated when we lay them out and they change size to
+ // the new column height.
+ if (columnHeight() != newContentLogicalHeight)
+ setColumnHeight(newContentLogicalHeight);
}
setLogicalHeight(ZERO_LAYOUT_UNIT);
- if (columnHeight() != pageLogicalHeight && everHadLayout()) {
- setColumnHeight(pageLogicalHeight);
- pageLogicalHeightChanged = true;
- }
-
// Set up our column sets.
ensureColumnSets();
}
diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
index 6f236d1f4..c69e65016 100644
--- a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
+++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
@@ -38,6 +38,8 @@ public:
private:
virtual const char* renderName() const OVERRIDE;
+
+ virtual void computeLogicalHeight() OVERRIDE {}; // We simply remain at our intrinsic height.
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderMultiColumnSet.cpp b/Source/WebCore/rendering/RenderMultiColumnSet.cpp
index 3ac55cc9e..369011980 100644
--- a/Source/WebCore/rendering/RenderMultiColumnSet.cpp
+++ b/Source/WebCore/rendering/RenderMultiColumnSet.cpp
@@ -24,21 +24,33 @@
*/
#include "config.h"
+#include "RenderMultiColumnSet.h"
+
+#include "HitTestResult.h"
#include "PaintInfo.h"
#include "RenderMultiColumnFlowThread.h"
-#include "RenderMultiColumnSet.h"
#include "RenderMultiColumnBlock.h"
+using std::min;
+using std::max;
+
namespace WebCore {
RenderMultiColumnSet::RenderMultiColumnSet(Node* node, RenderFlowThread* flowThread)
: RenderRegionSet(node, flowThread)
- , m_columnCount(1)
- , m_columnWidth(ZERO_LAYOUT_UNIT)
- , m_columnHeight(ZERO_LAYOUT_UNIT)
+ , m_computedColumnCount(1)
+ , m_computedColumnWidth(ZERO_LAYOUT_UNIT)
+ , m_computedColumnHeight(ZERO_LAYOUT_UNIT)
{
}
+LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
+{
+ LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x());
+ unsigned columnIndex = (offset - portionLogicalTop) / computedColumnHeight();
+ return portionLogicalTop + columnIndex * computedColumnHeight();
+}
+
void RenderMultiColumnSet::computeLogicalWidth()
{
// Our logical width starts off matching the column block itself.
@@ -49,17 +61,17 @@ void RenderMultiColumnSet::computeLogicalWidth()
setLogicalWidth(parentBox()->contentLogicalWidth());
RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
- setColumnWidthAndCount(parentBlock->columnWidth(), parentBlock->columnCount()); // FIXME: This will eventually vary if we are contained inside regions.
+ setComputedColumnWidthAndCount(parentBlock->columnWidth(), parentBlock->columnCount()); // FIXME: This will eventually vary if we are contained inside regions.
}
void RenderMultiColumnSet::computeLogicalHeight()
{
// Make sure our column height is up to date.
RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
- setColumnHeight(parentBlock->columnHeight()); // FIXME: Once we make more than one column set, this will become variable.
+ setComputedColumnHeight(parentBlock->columnHeight()); // FIXME: Once we make more than one column set, this will become variable.
// Our logical height is always just the height of our columns.
- setLogicalHeight(columnHeight());
+ setLogicalHeight(computedColumnHeight());
}
LayoutUnit RenderMultiColumnSet::columnGap() const
@@ -69,10 +81,20 @@ LayoutUnit RenderMultiColumnSet::columnGap() const
return static_cast<int>(style()->columnGap());
}
+unsigned RenderMultiColumnSet::columnCount() const
+{
+ if (!computedColumnHeight())
+ return 0;
+
+ // Our region 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();
+ return ceil(static_cast<float>(logicalHeightInColumns) / computedColumnHeight());
+}
+
LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
{
- LayoutUnit colLogicalWidth = columnWidth();
- LayoutUnit colLogicalHeight = columnHeight();
+ LayoutUnit colLogicalWidth = computedColumnWidth();
+ LayoutUnit colLogicalHeight = computedColumnHeight();
LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft();
int colGap = columnGap();
@@ -86,6 +108,81 @@ LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
}
+unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset) const
+{
+ LayoutRect portionRect(flowThreadPortionRect());
+ LayoutUnit flowThreadLogicalTop = isHorizontalWritingMode() ? portionRect.y() : portionRect.x();
+ LayoutUnit flowThreadLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX();
+
+ // Handle the offset being out of range.
+ if (offset < flowThreadLogicalTop)
+ return 0;
+ if (offset >= flowThreadLogicalBottom)
+ return columnCount() - 1;
+
+ // Just divide by the column height to determine the correct column.
+ return static_cast<float>(offset - flowThreadLogicalTop) / computedColumnHeight();
+}
+
+LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const
+{
+ LayoutRect portionRect = flowThreadPortionRect();
+ if (isHorizontalWritingMode())
+ portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * computedColumnHeight(), portionRect.width(), computedColumnHeight());
+ else
+ portionRect = LayoutRect(portionRect.x() + index * computedColumnHeight(), portionRect.y(), computedColumnHeight(), portionRect.height());
+ return portionRect;
+}
+
+LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, int colGap) const
+{
+ // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are
+ // unclipped at outside edges (i.e., the first and last column in the set), and they clip to half the column
+ // gap along interior edges.
+ //
+ // In the block direction, we will not clip overflow out of the top of the first column, or out of the bottom of
+ // the last column. This applies only to the true first column and last column across all column sets.
+ //
+ // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting
+ // mode that understands not to paint contents from a previous column in the overflow area of a following column.
+ // This problem applies to regions and pages as well and is not unique to columns.
+ bool isFirstColumn = !index;
+ bool isLastColumn = index == colCount - 1;
+ LayoutRect overflowRect(portionRect);
+ if (isHorizontalWritingMode()) {
+ if (isFirstColumn) {
+ // Shift to the logical left overflow of the flow thread to make sure it's all covered.
+ overflowRect.shiftXEdgeTo(min(flowThread()->visualOverflowRect().x(), portionRect.x()));
+ } else {
+ // Expand into half of the logical left column gap.
+ overflowRect.shiftXEdgeTo(portionRect.x() - colGap / 2);
+ }
+ if (isLastColumn) {
+ // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column.
+ overflowRect.shiftMaxXEdgeTo(max(flowThread()->visualOverflowRect().maxX(), portionRect.maxX()));
+ } else {
+ // Expand into half of the logical right column gap.
+ overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + colGap / 2);
+ }
+ } else {
+ if (isFirstColumn) {
+ // Shift to the logical left overflow of the flow thread to make sure it's all covered.
+ overflowRect.shiftYEdgeTo(min(flowThread()->visualOverflowRect().y(), portionRect.y()));
+ } else {
+ // Expand into half of the logical left column gap.
+ overflowRect.shiftYEdgeTo(portionRect.y() - colGap / 2);
+ }
+ if (isLastColumn) {
+ // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column.
+ overflowRect.shiftMaxYEdgeTo(max(flowThread()->visualOverflowRect().maxY(), portionRect.maxY()));
+ } else {
+ // Expand into half of the logical right column gap.
+ overflowRect.shiftMaxYEdgeTo(portionRect.maxY() + colGap / 2);
+ }
+ }
+ return overflowRectForFlowThreadPortion(overflowRect, isFirstRegion() && isFirstColumn, isLastRegion() && isLastColumn);
+}
+
void RenderMultiColumnSet::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// FIXME: RenderRegions are replaced elements right now and so they only paint in the foreground phase.
@@ -116,6 +213,8 @@ void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
return;
unsigned colCount = columnCount();
+ if (colCount <= 1)
+ return;
bool antialias = shouldAntialiasLines(paintInfo.context);
@@ -123,7 +222,7 @@ void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
LayoutUnit currLogicalLeftOffset = leftToRight ? ZERO_LAYOUT_UNIT : contentLogicalWidth();
LayoutUnit ruleAdd = borderAndPaddingLogicalLeft();
LayoutUnit ruleLogicalLeft = leftToRight ? ZERO_LAYOUT_UNIT : contentLogicalWidth();
- LayoutUnit inlineDirectionSize = columnWidth();
+ LayoutUnit inlineDirectionSize = computedColumnWidth();
BoxSide boxSide = isHorizontalWritingMode()
? leftToRight ? BSLeft : BSRight
: leftToRight ? BSTop : BSBottom;
@@ -152,14 +251,112 @@ void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPo
}
}
-void RenderMultiColumnSet::paintColumnContents(PaintInfo& /* paintInfo */, const LayoutPoint& /* paintOffset */)
+void RenderMultiColumnSet::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// For each rectangle, set it as the region rectangle and then let flow thread painting do the rest.
- // We make multiple calls to paintIntoRegion, changing the rectangles each time.
- if (!columnCount())
+ // We make multiple calls to paintFlowThreadPortionInRegion, changing the rectangles each time.
+ unsigned colCount = columnCount();
+ if (!colCount)
return;
+
+ LayoutUnit colGap = columnGap();
+ for (unsigned i = 0; i < colCount; i++) {
+ // First we get the column rect, which is in our local coordinate space, and we make it physical and apply
+ // the paint offset to it. That gives us the physical location that we want to paint the column at.
+ LayoutRect colRect = columnRectAt(i);
+ flipForWritingMode(colRect);
+ colRect.moveBy(paintOffset);
+
+ // Next we get the portion of the flow thread that corresponds to this column.
+ LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
+
+ // Now get the overflow rect that corresponds to the column.
+ LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
+
+ // Do the paint with the computed rects.
+ flowThread()->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPortion, flowThreadOverflowPortion, colRect.location());
+ }
+}
+
+bool RenderMultiColumnSet::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+ LayoutPoint adjustedLocation = accumulatedOffset + location();
+
+ // 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).
+ // FIXME: Once we support overflow, we need to intersect with that and not with the bounds rect.
+ LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
+ boundsRect.moveBy(adjustedLocation);
+ if (!visibleToHitTesting() || action != HitTestForeground || !locationInContainer.intersects(boundsRect))
+ return false;
+
+ // The point is in one specific column. Since columns can't overlap, we don't ever have to test
+ // multiple columns. Put the
+
+ // FIXME: It would be nice to jump right to the specific column by just doing math on the point. Since columns
+ // can't overlap, we shouldn't have to walk every column like this. The old column code walked all the columns, though,
+ // so this is no worse. We'd have to watch out for rect-based hit testing, though, which actually could overlap
+ // multiple columns.
+ LayoutUnit colGap = columnGap();
+ unsigned colCount = columnCount();
+ for (unsigned i = 0; i < colCount; i++) {
+ // First we get the column rect, which is in our local coordinate space, and we make it physical and apply
+ // the hit test offset to it. That gives us the physical location that we want to paint the column at.
+ LayoutRect colRect = columnRectAt(i);
+ flipForWritingMode(colRect);
+ colRect.moveBy(adjustedLocation);
+
+ // Next we get the portion of the flow thread that corresponds to this column.
+ LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
- // FIXME: Implement.
+ // Now get the overflow rect that corresponds to the column.
+ LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
+
+ // Do the hit test with the computed rects.
+ if (flowThread()->hitTestFlowThreadPortionInRegion(this, flowThreadPortion, flowThreadOverflowPortion, request, result, locationInContainer, colRect.location()))
+ return true;
+ }
+
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+ return !result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect);
+}
+
+void RenderMultiColumnSet::repaintFlowThreadContent(const LayoutRect& repaintRect, bool immediate) const
+{
+ // Figure out the start and end columns and only check within that range so that we don't walk the
+ // entire column set. Put the repaint rect into flow thread coordinates by flipping it first.
+ LayoutRect flowThreadRepaintRect(repaintRect);
+ flowThread()->flipForWritingMode(flowThreadRepaintRect);
+
+ // Now we can compare this rect with the flow thread portions owned by each column. First let's
+ // just see if the repaint rect intersects our flow thread portion at all.
+ LayoutRect clippedRect(flowThreadRepaintRect);
+ clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
+ if (clippedRect.isEmpty())
+ return;
+
+ // Now we know we intersect at least one column. Let's figure out the logical top and logical
+ // bottom of the area we're repainting.
+ LayoutUnit repaintLogicalTop = isHorizontalWritingMode() ? flowThreadRepaintRect.y() : flowThreadRepaintRect.x();
+ LayoutUnit repaintLogicalBottom = (isHorizontalWritingMode() ? flowThreadRepaintRect.maxY() : flowThreadRepaintRect.maxX()) - 1;
+
+ unsigned startColumn = columnIndexAtOffset(repaintLogicalTop);
+ unsigned endColumn = columnIndexAtOffset(repaintLogicalBottom);
+
+ LayoutUnit colGap = columnGap();
+ unsigned colCount = columnCount();
+ for (unsigned i = startColumn; i <= endColumn; i++) {
+ LayoutRect colRect = columnRectAt(i);
+
+ // Get the portion of the flow thread that corresponds to this column.
+ LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
+
+ // Now get the overflow rect that corresponds to the column.
+ LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
+
+ // Do a repaint for this specific column.
+ repaintFlowThreadContentRectangle(repaintRect, immediate, flowThreadPortion, flowThreadOverflowPortion, colRect.location());
+ }
}
const char* RenderMultiColumnSet::renderName() const
diff --git a/Source/WebCore/rendering/RenderMultiColumnSet.h b/Source/WebCore/rendering/RenderMultiColumnSet.h
index b9a9da054..a0d1c4536 100644
--- a/Source/WebCore/rendering/RenderMultiColumnSet.h
+++ b/Source/WebCore/rendering/RenderMultiColumnSet.h
@@ -47,18 +47,18 @@ public:
virtual bool isRenderMultiColumnSet() const OVERRIDE { return true; }
- unsigned columnCount() const { return m_columnCount; }
- LayoutUnit columnWidth() const { return m_columnWidth; }
- LayoutUnit columnHeight() const { return m_columnHeight; }
+ unsigned computedColumnCount() const { return m_computedColumnCount; }
+ LayoutUnit computedColumnWidth() const { return m_computedColumnWidth; }
+ LayoutUnit computedColumnHeight() const { return m_computedColumnHeight; }
- void setColumnWidthAndCount(LayoutUnit width, unsigned count)
+ void setComputedColumnWidthAndCount(LayoutUnit width, unsigned count)
{
- m_columnWidth = width;
- m_columnCount = count;
+ m_computedColumnWidth = width;
+ m_computedColumnCount = count;
}
- void setColumnHeight(LayoutUnit height)
+ void setComputedColumnHeight(LayoutUnit height)
{
- m_columnHeight = height;
+ m_computedColumnHeight = height;
}
private:
@@ -66,9 +66,17 @@ private:
virtual void computeLogicalHeight() OVERRIDE;
virtual void paintReplaced(PaintInfo&, const LayoutPoint& paintOffset) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual LayoutUnit logicalWidthForFlowThreadContent() const OVERRIDE { return m_columnWidth; }
- virtual LayoutUnit logicalHeightForFlowThreadContent() const OVERRIDE { return m_columnHeight; } // FIXME: Will be wrong once we have multiple sets.
+ 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; }
+
+ virtual void repaintFlowThreadContent(const LayoutRect& repaintRect, bool immediate) const OVERRIDE;
virtual const char* renderName() const;
@@ -76,11 +84,17 @@ private:
void paintColumnContents(PaintInfo&, const LayoutPoint& paintOffset);
LayoutUnit columnGap() const;
- LayoutRect columnRectAt( unsigned index) const;
+ LayoutRect columnRectAt(unsigned index) const;
+ unsigned columnCount() const;
+
+ LayoutRect flowThreadPortionRectAt(unsigned index) const;
+ LayoutRect flowThreadPortionOverflowRect(const LayoutRect& flowThreadPortion, unsigned index, unsigned colCount, int colGap) const;
+
+ unsigned columnIndexAtOffset(LayoutUnit) const;
- unsigned m_columnCount;
- LayoutUnit m_columnWidth;
- LayoutUnit m_columnHeight;
+ unsigned m_computedColumnCount;
+ LayoutUnit m_computedColumnWidth;
+ LayoutUnit m_computedColumnHeight;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.cpp b/Source/WebCore/rendering/RenderNamedFlowThread.cpp
index 5b02453e4..4e83cca9e 100644
--- a/Source/WebCore/rendering/RenderNamedFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderNamedFlowThread.cpp
@@ -38,18 +38,37 @@ RenderNamedFlowThread::RenderNamedFlowThread(Node* node, PassRefPtr<WebKitNamedF
, m_namedFlow(namedFlow)
, m_regionLayoutUpdateEventTimer(this, &RenderNamedFlowThread::regionLayoutUpdateEventTimerFired)
{
- m_namedFlow->setRenderer(this);
}
RenderNamedFlowThread::~RenderNamedFlowThread()
{
- m_namedFlow->setRenderer(0);
+ // 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();
+}
RenderObject* RenderNamedFlowThread::nextRendererForNode(Node* node) const
{
@@ -135,12 +154,45 @@ static bool compareRenderRegions(const RenderRegion* firstRegion, const RenderRe
ASSERT(firstRegion);
ASSERT(secondRegion);
- // If the regions have the same region-index, compare their position in dom.
- ASSERT(firstRegion->node());
- ASSERT(secondRegion->node());
+ ASSERT(firstRegion->generatingNode());
+ ASSERT(secondRegion->generatingNode());
+
+ // If the regions belong to different nodes, compare their position in the DOM.
+ if (firstRegion->generatingNode() != secondRegion->generatingNode()) {
+ unsigned short position = firstRegion->generatingNode()->compareDocumentPosition(secondRegion->generatingNode());
- unsigned short position = firstRegion->node()->compareDocumentPosition(secondRegion->node());
- return (position & Node::DOCUMENT_POSITION_FOLLOWING);
+ // 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;
}
void RenderNamedFlowThread::addRegionToThread(RenderRegion* renderRegion)
@@ -156,6 +208,8 @@ void RenderNamedFlowThread::addRegionToThread(RenderRegion* renderRegion)
m_regionList.insertBefore(it, renderRegion);
}
+ resetMarkForDestruction();
+
ASSERT(!renderRegion->isValid());
if (renderRegion->parentNamedFlowThread()) {
if (renderRegion->parentNamedFlowThread()->dependsOn(this)) {
@@ -188,10 +242,8 @@ void RenderNamedFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
removeDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
}
- if (canBeDestroyed()) {
- destroy();
- return;
- }
+ if (canBeDestroyed())
+ setMarkForDestruction();
// After removing all the regions in the flow the following layout needs to dispatch the regionLayoutUpdate event
if (m_regionList.isEmpty())
@@ -265,9 +317,12 @@ void RenderNamedFlowThread::pushDependencies(RenderNamedFlowThreadList& list)
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;
@@ -285,12 +340,13 @@ 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())
- destroy();
+ setMarkForDestruction();
}
const AtomicString& RenderNamedFlowThread::flowThreadName() const
@@ -298,14 +354,6 @@ const AtomicString& RenderNamedFlowThread::flowThreadName() const
return m_namedFlow->name();
}
-void RenderNamedFlowThread::willBeDestroyed()
-{
- if (!documentBeingDestroyed())
- view()->flowThreadController()->removeFlowThread(this);
-
- RenderFlowThread::willBeDestroyed();
-}
-
void RenderNamedFlowThread::dispatchRegionLayoutUpdateEvent()
{
RenderFlowThread::dispatchRegionLayoutUpdateEvent();
@@ -321,4 +369,28 @@ void RenderNamedFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderNamedF
m_namedFlow->dispatchRegionLayoutUpdateEvent();
}
+void RenderNamedFlowThread::setMarkForDestruction()
+{
+ if (m_namedFlow->flowState() == WebKitNamedFlow::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() == WebKitNamedFlow::FlowStateCreated)
+ return;
+
+ m_namedFlow->setRenderer(this);
+}
+
+bool RenderNamedFlowThread::isMarkedForDestruction() const
+{
+ // Flow threads in the "NULL" state can be destroyed.
+ return m_namedFlow->flowState() == WebKitNamedFlow::FlowStateNull;
+}
+
}
diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.h b/Source/WebCore/rendering/RenderNamedFlowThread.h
index 4101b771e..a8b8b5131 100644
--- a/Source/WebCore/rendering/RenderNamedFlowThread.h
+++ b/Source/WebCore/rendering/RenderNamedFlowThread.h
@@ -69,9 +69,11 @@ public:
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;
protected:
- virtual void willBeDestroyed() OVERRIDE;
+ void setMarkForDestruction();
+ void resetMarkForDestruction();
private:
virtual const char* renderName() const OVERRIDE;
@@ -85,6 +87,7 @@ private:
void checkInvalidRegions();
bool canBeDestroyed() const { return m_regionList.isEmpty() && m_contentNodes.isEmpty(); }
void regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*);
+ void clearContentNodes();
private:
// Observer flow threads have invalid regions that depend on the state of this thread
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 933a559c4..8bfd9f74d 100755
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -185,11 +185,9 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
case BOX:
case INLINE_BOX:
return new (arena) RenderDeprecatedFlexibleBox(node);
-#if ENABLE(CSS3_FLEXBOX)
case FLEX:
case INLINE_FLEX:
return new (arena) RenderFlexibleBox(node);
-#endif
case GRID:
case INLINE_GRID:
return new (arena) RenderGrid(node);
@@ -640,9 +638,9 @@ void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderOb
if (!container && !object->isRenderView())
return;
if (!last->isText() && last->style()->hasOutOfFlowPosition()) {
- bool willSkipRelativelyPositionedInlines = !object->isRenderBlock() || object->isAnonymousBlock() || object->isRenderFlowThreadContainer();
- // Skip relatively positioned inlines and anonymous blocks (and the flow threads container) to get to the enclosing RenderBlock.
- while (object && (!object->isRenderBlock() || object->isAnonymousBlock() || object->isRenderFlowThreadContainer()))
+ bool willSkipRelativelyPositionedInlines = !object->isRenderBlock() || object->isAnonymousBlock();
+ // Skip relatively positioned inlines and anonymous blocks to get to the enclosing RenderBlock.
+ while (object && (!object->isRenderBlock() || object->isAnonymousBlock()))
object = object->container();
if (!object || object->posChildNeedsLayout())
return;
@@ -1279,7 +1277,7 @@ RenderBoxModelObject* RenderObject::containerForRepaint() const
return repaintContainer;
}
-void RenderObject::repaintUsingContainer(RenderBoxModelObject* repaintContainer, const LayoutRect& r, bool immediate)
+void RenderObject::repaintUsingContainer(RenderBoxModelObject* repaintContainer, const LayoutRect& r, bool immediate) const
{
if (!repaintContainer) {
view()->repaintViewRectangle(r, immediate);
@@ -1322,7 +1320,7 @@ void RenderObject::repaintUsingContainer(RenderBoxModelObject* repaintContainer,
#endif
}
-void RenderObject::repaint(bool immediate)
+void RenderObject::repaint(bool immediate) const
{
// Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
RenderView* view;
@@ -1336,7 +1334,7 @@ void RenderObject::repaint(bool immediate)
repaintUsingContainer(repaintContainer ? repaintContainer : view, clippedOverflowRectForRepaint(repaintContainer), immediate);
}
-void RenderObject::repaintRectangle(const LayoutRect& r, bool immediate)
+void RenderObject::repaintRectangle(const LayoutRect& r, bool immediate) const
{
// Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
RenderView* view;
@@ -1853,7 +1851,7 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS
toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
- && (!newStyle->isFloating() && newStyle->position() != AbsolutePosition && newStyle->position() != FixedPosition)
+ && (!newStyle->isFloating() && !newStyle->hasOutOfFlowPosition())
&& parent() && (parent()->isBlockFlow() || parent()->isRenderInline());
// reset style flags
@@ -1861,6 +1859,7 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS
setFloating(false);
setPositioned(false);
setRelPositioned(false);
+ setStickyPositioned(false);
}
setHorizontalWritingMode(true);
setPaintBackground(false);
@@ -1966,9 +1965,9 @@ void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
newStyle->setColumnSpan(ColumnSpanAll);
}
- // Preserve the position style of anonymous block continuations as they can have relative position when
- // they contain block descendants of relative positioned inlines.
- if (child->isRelPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
+ // Preserve the position style of anonymous block continuations as they can have relative or sticky position when
+ // they contain block descendants of relative or sticky positioned inlines.
+ if (child->isInFlowPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
newStyle->setPosition(child->style()->position());
child->setStyle(newStyle.release());
@@ -2200,9 +2199,9 @@ LayoutRect RenderObject::localCaretRect(InlineBox*, int, LayoutUnit* extraWidthT
return LayoutRect();
}
-bool RenderObject::isRooted(RenderView** view)
+bool RenderObject::isRooted(RenderView** view) const
{
- RenderObject* o = this;
+ const RenderObject* o = this;
while (o->parent())
o = o->parent();
@@ -2210,7 +2209,7 @@ bool RenderObject::isRooted(RenderView** view)
return false;
if (view)
- *view = toRenderView(o);
+ *view = const_cast<RenderView*>(toRenderView(o));
return true;
}
@@ -2534,25 +2533,25 @@ bool RenderObject::isComposited() const
return hasLayer() && toRenderBoxModelObject(this)->layer()->isComposited();
}
-bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
+bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
{
bool inside = false;
if (hitTestFilter != HitTestSelf) {
// First test the foreground layer (lines and inlines).
- inside = nodeAtPoint(request, result, pointInContainer, accumulatedOffset, HitTestForeground);
+ inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestForeground);
// Test floats next.
if (!inside)
- inside = nodeAtPoint(request, result, pointInContainer, accumulatedOffset, HitTestFloat);
+ inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestFloat);
// Finally test to see if the mouse is in the background (within a child block's background).
if (!inside)
- inside = nodeAtPoint(request, result, pointInContainer, accumulatedOffset, HitTestChildBlockBackgrounds);
+ inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestChildBlockBackgrounds);
}
// See if the mouse is inside us but not any of our descendants
if (hitTestFilter != HitTestDescendants && !inside)
- inside = nodeAtPoint(request, result, pointInContainer, accumulatedOffset, HitTestBlockBackground);
+ inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestBlockBackground);
return inside;
}
@@ -2571,7 +2570,7 @@ void RenderObject::updateHitTestResult(HitTestResult& result, const LayoutPoint&
}
}
-bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& /*pointInContainer*/, const LayoutPoint& /*accumulatedOffset*/, HitTestAction)
+bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& /*locationInContainer*/, const LayoutPoint& /*accumulatedOffset*/, HitTestAction)
{
return false;
}
@@ -2898,10 +2897,10 @@ RenderBoxModelObject* RenderObject::offsetParent() const
// is one of the following HTML elements: td, th, or table.
// * Our own extension: if there is a difference in the effective zoom
- bool skipTables = isOutOfFlowPositioned() || isRelPositioned();
+ bool skipTables = isPositioned();
float currZoom = style()->effectiveZoom();
RenderObject* curr = parent();
- while (curr && (!curr->node() || (!curr->isOutOfFlowPositioned() && !curr->isRelPositioned() && !curr->isBody()))) {
+ while (curr && (!curr->node() || (!curr->isPositioned() && !curr->isBody()))) {
Node* element = curr->node();
if (!skipTables && element && (element->hasTagName(tableTag) || element->hasTagName(tdTag) || element->hasTagName(thTag)))
break;
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index 05ccea48d..b6aa16e19 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -46,7 +46,7 @@ class AffineTransform;
class AnimationController;
class Cursor;
class Document;
-class HitTestPoint;
+class HitTestLocation;
class HitTestResult;
class InlineBox;
class InlineFlowBox;
@@ -311,6 +311,9 @@ public:
virtual bool isBlockFlow() const { return false; }
virtual bool isBoxModelObject() const { return false; }
virtual bool isCounter() const { return false; }
+#if ENABLE(DIALOG_ELEMENT)
+ virtual bool isDialog() const { return false; }
+#endif
virtual bool isQuote() const { return false; }
#if ENABLE(DETAILS_ELEMENT)
@@ -369,7 +372,6 @@ public:
#endif
virtual bool isRenderFlowThread() const { return false; }
- virtual bool isRenderFlowThreadContainer() const { return false; }
virtual bool isRenderNamedFlowThread() const { return false; }
virtual bool isRenderMultiColumnBlock() const { return false; }
@@ -513,8 +515,10 @@ public:
bool isFloating() const { return m_bitfields.floating(); }
bool isOutOfFlowPositioned() const { return m_bitfields.positioned(); } // absolute or fixed positioning
- bool isInFlowPositioned() const { return m_bitfields.relPositioned(); } // relative positioning
+ bool isInFlowPositioned() const { return m_bitfields.relPositioned() || m_bitfields.stickyPositioned(); } // relative or sticky positioning
bool isRelPositioned() const { return m_bitfields.relPositioned(); } // relative positioning
+ bool isStickyPositioned() const { return m_bitfields.stickyPositioned(); }
+ bool isPositioned() const { return m_bitfields.positioned() || m_bitfields.relPositioned() || m_bitfields.stickyPositioned(); }
bool isText() const { return m_bitfields.isText(); }
bool isBox() const { return m_bitfields.isBox(); }
@@ -558,6 +562,7 @@ public:
bool hasTransform() const { return m_bitfields.hasTransform(); }
bool hasMask() const { return style() && style()->hasMask(); }
+ bool hasClipPath() const { return style() && style()->clipPath(); }
bool hasHiddenBackface() const { return style() && style()->backfaceVisibility() == BackfaceVisibilityHidden; }
#if ENABLE(CSS_FILTERS)
@@ -566,6 +571,12 @@ public:
bool hasFilter() const { return false; }
#endif
+#if ENABLE(CSS_COMPOSITING)
+ bool hasBlendMode() const { return style() && style()->hasBlendMode(); }
+#else
+ bool hasBlendMode() const { return false; }
+#endif
+
inline bool preservesNewline() const;
// The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
@@ -579,7 +590,7 @@ public:
RenderView* view() const;
// Returns true if this renderer is rooted, and optionally returns the hosting view (the root of the hierarchy).
- bool isRooted(RenderView** = 0);
+ bool isRooted(RenderView** = 0) const;
Node* node() const { return isAnonymous() ? 0 : m_node; }
@@ -621,6 +632,7 @@ public:
void setPositioned(bool b = true) { m_bitfields.setPositioned(b); }
void setRelPositioned(bool b = true) { m_bitfields.setRelPositioned(b); }
+ void setStickyPositioned(bool b = true) { m_bitfields.setStickyPositioned(b); }
void setFloating(bool b = true) { m_bitfields.setFloating(b); }
void setInline(bool b = true) { m_bitfields.setIsInline(b); }
void setHasBoxDecorations(bool b = true) { m_bitfields.setPaintBackground(b); }
@@ -657,9 +669,9 @@ public:
bool isComposited() const;
- bool hitTest(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
+ bool hitTest(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
virtual VisiblePosition positionForPoint(const LayoutPoint&);
VisiblePosition createVisiblePosition(int offset, EAffinity);
@@ -744,14 +756,14 @@ public:
RenderBoxModelObject* 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(RenderBoxModelObject* repaintContainer, const LayoutRect&, bool immediate = false);
+ void repaintUsingContainer(RenderBoxModelObject* repaintContainer, const LayoutRect&, bool immediate = false) const;
// Repaint the entire object. Called when, e.g., the color of a border changes, or when a border
// style changes.
- void repaint(bool immediate = false);
+ void repaint(bool immediate = false) const;
// Repaint a specific subrectangle within a given object. The rect |r| is in the object's coordinate space.
- void repaintRectangle(const LayoutRect&, bool immediate = false);
+ void repaintRectangle(const LayoutRect&, bool immediate = false) const;
// 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(RenderBoxModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = 0, const LayoutRect* newOutlineBoxPtr = 0);
@@ -903,6 +915,9 @@ public:
bool shouldUseTransformFromContainer(const RenderObject* container) const;
void getTransformFromContainer(const RenderObject* container, const LayoutSize& offsetInContainer, TransformationMatrix&) const;
+ // return true if this object requires a new stacking context
+ bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || hasBlendMode(); }
+
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&) { };
LayoutRect absoluteOutlineBounds() const
@@ -930,7 +945,7 @@ protected:
void paintFocusRing(GraphicsContext*, const LayoutPoint&, RenderStyle*);
void paintOutline(GraphicsContext*, const LayoutRect&);
void addPDFURLRect(GraphicsContext*, const LayoutRect&);
-
+
virtual LayoutRect viewRect() const;
void adjustRectForOutlineAndShadow(LayoutRect&) const;
@@ -990,6 +1005,7 @@ private:
, m_floating(false)
, m_positioned(false)
, m_relPositioned(false)
+ , m_stickyPositioned(false)
, m_paintBackground(false)
, m_isAnonymous(node == node->document())
, m_isText(false)
@@ -1024,6 +1040,7 @@ private:
ADD_BOOLEAN_BITFIELD(positioned, Positioned);
ADD_BOOLEAN_BITFIELD(relPositioned, RelPositioned);
+ ADD_BOOLEAN_BITFIELD(stickyPositioned, StickyPositioned);
ADD_BOOLEAN_BITFIELD(paintBackground, PaintBackground); // if the box has something to paint in the
// background painting phase (background, border, etc)
diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp
index 98a287627..247f7dda4 100644
--- a/Source/WebCore/rendering/RenderObjectChildList.cpp
+++ b/Source/WebCore/rendering/RenderObjectChildList.cpp
@@ -85,9 +85,6 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render
if (oldChild->isBox())
toRenderBox(oldChild)->deleteLineBoxWrapper();
- if (!owner->documentBeingDestroyed() && notifyRenderer)
- oldChild->willBeRemovedFromTree();
-
// If oldChild is the start or end of the selection, then clear the selection to
// avoid problems of invalid pointers.
// FIXME: The FrameSelection should be responsible for this when it
@@ -95,7 +92,13 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render
if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
owner->view()->clearSelection();
- // remove the child
+ if (!owner->documentBeingDestroyed() && notifyRenderer)
+ oldChild->willBeRemovedFromTree();
+
+ // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below.
+ // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure
+ // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling.
+
if (oldChild->previousSibling())
oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
if (oldChild->nextSibling())
@@ -337,6 +340,32 @@ static RenderObject* createRendererForBeforeAfterContent(RenderObject* owner, co
return renderer;
}
+static RenderObject* ensureBeforeAfterContainer(RenderObject* owner, PseudoId type, RenderStyle* pseudoElementStyle, Node* generatingNode, RenderObject* insertBefore)
+{
+ // Make a generated box that might be any display type now that we are able to drill down into children
+ // to find the original content properly.
+ RenderObject* generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
+ ASSERT(generatingNode); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
+ generatedContentContainer->setNode(generatingNode); // This allows access to the generatingNode.
+ generatedContentContainer->setStyle(pseudoElementStyle);
+ if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
+ // The generated content container is not allowed here -> abort.
+ generatedContentContainer->destroy();
+ return 0;
+ }
+
+ // When we don't have a first child and are part of a continuation chain,
+ // insertBefore is incorrectly set to zero above, which causes the :before
+ // child to end up at the end of continuation chain.
+ // See https://bugs.webkit.org/show_bug.cgi?id=78380.
+ if (!insertBefore && type == BEFORE && owner->virtualContinuation())
+ owner->addChildIgnoringContinuation(generatedContentContainer, 0);
+ else
+ owner->addChild(generatedContentContainer, insertBefore);
+
+ return generatedContentContainer;
+}
+
void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
{
// Double check that the document did in fact use generated content rules. Otherwise we should not have been called.
@@ -426,41 +455,30 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
insertBefore = insertBefore->nextSibling();
// Generated content consists of a single container that houses multiple children (specified
- // by the content property). This generated content container gets the pseudo-element style set on it.
+ // by the content property). This generated content container gets the pseudo-element style set on it.
+ // For pseudo-elements that are regions, the container is the RenderRegion.
RenderObject* generatedContentContainer = 0;
- // Walk our list of generated content and create render objects for each.
- for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
- RenderObject* renderer = createRendererForBeforeAfterContent(owner, content, pseudoElementStyle);
-
- if (renderer) {
- if (!generatedContentContainer) {
- // Make a generated box that might be any display type now that we are able to drill down into children
- // to find the original content properly.
- generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
- ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
- generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode.
- generatedContentContainer->setStyle(pseudoElementStyle);
- if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
- // The generated content container is not allowed here -> abort.
- generatedContentContainer->destroy();
- renderer->destroy();
- return;
+ if (!pseudoElementStyle->regionThread().isEmpty())
+ generatedContentContainer = ensureBeforeAfterContainer(owner, type, pseudoElementStyle, styledObject->node(), insertBefore);
+ else {
+ // Walk our list of generated content and create render objects for each.
+ for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
+ RenderObject* renderer = createRendererForBeforeAfterContent(owner, content, pseudoElementStyle);
+
+ if (renderer) {
+ if (!generatedContentContainer) {
+ generatedContentContainer = ensureBeforeAfterContainer(owner, type, pseudoElementStyle, styledObject->node(), insertBefore);
+ if (!generatedContentContainer) {
+ renderer->destroy();
+ return;
+ }
}
-
- // When we don't have a first child and are part of a continuation chain,
- // insertBefore is incorrectly set to zero above, which causes the :before
- // child to end up at the end of continuation chain.
- // See https://bugs.webkit.org/show_bug.cgi?id=78380.
- if (!insertBefore && type == BEFORE && owner->virtualContinuation())
- owner->addChildIgnoringContinuation(generatedContentContainer, 0);
+ if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
+ generatedContentContainer->addChild(renderer);
else
- owner->addChild(generatedContentContainer, insertBefore);
+ renderer->destroy();
}
- if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
- generatedContentContainer->addChild(renderer);
- else
- renderer->destroy();
}
}
diff --git a/Source/WebCore/rendering/RenderQuote.cpp b/Source/WebCore/rendering/RenderQuote.cpp
index 679e55ba4..da16df5aa 100644
--- a/Source/WebCore/rendering/RenderQuote.cpp
+++ b/Source/WebCore/rendering/RenderQuote.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "RenderQuote.h"
+#include "RenderView.h"
#include <wtf/text/AtomicString.h>
#define U(x) ((const UChar*)L##x)
@@ -242,6 +243,11 @@ PassRefPtr<StringImpl> RenderQuote::originalText() const
return StringImpl::empty();
}
+void RenderQuote::updateText()
+{
+ computePreferredLogicalWidths(0);
+}
+
void RenderQuote::computePreferredLogicalWidths(float lead)
{
if (!m_attached)
diff --git a/Source/WebCore/rendering/RenderQuote.h b/Source/WebCore/rendering/RenderQuote.h
index 7917fc12b..947f3a6f5 100644
--- a/Source/WebCore/rendering/RenderQuote.h
+++ b/Source/WebCore/rendering/RenderQuote.h
@@ -22,7 +22,6 @@
#ifndef RenderQuote_h
#define RenderQuote_h
-#include "Document.h"
#include "QuotesData.h"
#include "RenderStyle.h"
#include "RenderStyleConstants.h"
@@ -30,6 +29,8 @@
namespace WebCore {
+class Document;
+
class RenderQuote : public RenderText {
public:
RenderQuote(Document*, const QuoteType);
@@ -42,6 +43,8 @@ private:
virtual const char* renderName() const OVERRIDE { return "RenderQuote"; };
virtual bool isQuote() const OVERRIDE { return true; };
virtual PassRefPtr<StringImpl> originalText() const OVERRIDE;
+
+ virtual void updateText() OVERRIDE;
virtual void computePreferredLogicalWidths(float leadWidth) OVERRIDE;
// We don't override insertedIntoTree to call attachQuote() as it would be attached
diff --git a/Source/WebCore/rendering/RenderRegion.cpp b/Source/WebCore/rendering/RenderRegion.cpp
index dbdbe83f7..80c848bf4 100644
--- a/Source/WebCore/rendering/RenderRegion.cpp
+++ b/Source/WebCore/rendering/RenderRegion.cpp
@@ -52,25 +52,35 @@ RenderRegion::RenderRegion(Node* node, RenderFlowThread* flowThread)
{
}
-LayoutUnit RenderRegion::logicalWidthForFlowThreadContent() const
+LayoutUnit RenderRegion::pageLogicalWidth() const
{
return m_flowThread->isHorizontalWritingMode() ? contentWidth() : contentHeight();
}
-LayoutUnit RenderRegion::logicalHeightForFlowThreadContent() const
+LayoutUnit RenderRegion::pageLogicalHeight() const
{
return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
}
-LayoutRect RenderRegion::regionOversetRect() const
+LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const
+{
+ return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
+}
+
+LayoutRect RenderRegion::flowThreadPortionOverflowRect() const
+{
+ return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion());
+}
+
+LayoutRect RenderRegion::overflowRectForFlowThreadPortion(LayoutRect flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const
{
// FIXME: Would like to just use hasOverflowClip() but we aren't a block yet. When RenderRegion is eliminated and
// folded into RenderBlock, switch to hasOverflowClip().
bool clipX = style()->overflowX() != OVISIBLE;
bool clipY = style()->overflowY() != OVISIBLE;
- bool isLastRegionWithRegionOverflowBreak = (isLastRegion() && (style()->regionOverflow() == BreakRegionOverflow));
+ bool isLastRegionWithRegionOverflowBreak = (isLastPortion && (style()->regionOverflow() == BreakRegionOverflow));
if ((clipX && clipY) || !isValid() || !m_flowThread || isLastRegionWithRegionOverflowBreak)
- return regionRect();
+ return flowThreadPortionRect;
LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect();
@@ -78,22 +88,27 @@ LayoutRect RenderRegion::regionOversetRect() const
LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline);
LayoutRect clipRect;
if (m_flowThread->isHorizontalWritingMode()) {
- LayoutUnit minY = isFirstRegion() ? (flowThreadOverflow.y() - outlineSize) : regionRect().y();
- LayoutUnit maxY = isLastRegion() ? max(regionRect().maxY(), flowThreadOverflow.maxY()) + outlineSize : regionRect().maxY();
- LayoutUnit minX = clipX ? regionRect().x() : (flowThreadOverflow.x() - outlineSize);
- LayoutUnit maxX = clipX ? regionRect().maxX() : (flowThreadOverflow.maxX() + outlineSize);
+ LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect.y();
+ LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
+ LayoutUnit minX = clipX ? flowThreadPortionRect.x() : (flowThreadOverflow.x() - outlineSize);
+ LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : (flowThreadOverflow.maxX() + outlineSize);
clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
} else {
- LayoutUnit minX = isFirstRegion() ? (flowThreadOverflow.x() - outlineSize) : regionRect().x();
- LayoutUnit maxX = isLastRegion() ? max(regionRect().maxX(), flowThreadOverflow.maxX()) + outlineSize : regionRect().maxX();
- LayoutUnit minY = clipY ? regionRect().y() : (flowThreadOverflow.y() - outlineSize);
- LayoutUnit maxY = clipY ? regionRect().maxY() : (flowThreadOverflow.maxY() + outlineSize);
+ LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect.x();
+ LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
+ LayoutUnit minY = clipY ? flowThreadPortionRect.y() : (flowThreadOverflow.y() - outlineSize);
+ LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : (flowThreadOverflow.maxY() + outlineSize);
clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
}
return clipRect;
}
+LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
+{
+ return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
+}
+
bool RenderRegion::isFirstRegion() const
{
ASSERT(isValid() && m_flowThread);
@@ -113,12 +128,12 @@ void RenderRegion::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintO
return;
setRegionObjectsRegionStyle();
- m_flowThread->paintIntoRegion(paintInfo, this, LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
+ m_flowThread->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
restoreRegionObjectsOriginalStyle();
}
// Hit Testing
-bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
if (!isValid())
return false;
@@ -127,14 +142,15 @@ bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& res
// Check our bounds next. For this purpose always assume that we can only be hit in the
// foreground phase (which is true for replaced elements like images).
- LayoutRect boundsRect = borderBoxRectInRegion(pointInContainer.region());
+ // FIXME: Once we support overflow, we need to intersect with that and not with the bounds rect.
+ LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
boundsRect.moveBy(adjustedLocation);
- if (visibleToHitTesting() && action == HitTestForeground && pointInContainer.intersects(boundsRect)) {
+ if (visibleToHitTesting() && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
// Check the contents of the RenderFlowThread.
- if (m_flowThread && m_flowThread->hitTestRegion(this, request, result, pointInContainer, LayoutPoint(adjustedLocation.x() + borderLeft() + paddingLeft(), adjustedLocation.y() + borderTop() + paddingTop())))
+ if (m_flowThread && m_flowThread->hitTestFlowThreadPortionInRegion(this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), request, result, locationInContainer, LayoutPoint(adjustedLocation.x() + borderLeft() + paddingLeft(), adjustedLocation.y() + borderTop() + paddingTop())))
return true;
- updateHitTestResult(result, pointInContainer.point() - toLayoutSize(adjustedLocation));
- if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+ if (!result.addNodeToRectBasedTestResult(generatingNode(), request, locationInContainer, boundsRect))
return true;
}
@@ -145,6 +161,8 @@ void RenderRegion::checkRegionStyle()
{
ASSERT(m_flowThread);
bool customRegionStyle = false;
+
+ // FIXME: Region styling doesn't work for pseudo elements.
if (node()) {
Element* regionElement = static_cast<Element*>(node());
customRegionStyle = view()->document()->styleResolver()->checkRegionStyle(regionElement);
@@ -172,10 +190,10 @@ void RenderRegion::layout()
{
RenderReplaced::layout();
if (m_flowThread && isValid()) {
- LayoutRect oldRegionRect(regionRect());
+ LayoutRect oldRegionRect(flowThreadPortionRect());
if (!isHorizontalWritingMode())
oldRegionRect = oldRegionRect.transposedRect();
- if (oldRegionRect.width() != logicalWidthForFlowThreadContent() || oldRegionRect.height() != logicalHeightForFlowThreadContent())
+ if (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight())
m_flowThread->invalidateRegions();
}
@@ -191,6 +209,34 @@ void RenderRegion::layout()
// We'll need to expand RenderBoxRegionInfo to also hold left and right overflow values.
}
+void RenderRegion::repaintFlowThreadContent(const LayoutRect& repaintRect, bool immediate) const
+{
+ repaintFlowThreadContentRectangle(repaintRect, immediate, flowThreadPortionRect(), flowThreadPortionOverflowRect(), contentBoxRect().location());
+}
+
+void RenderRegion::repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, bool immediate, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& regionLocation) const
+{
+ // We only have to issue a repaint in this region if the region rect intersects the repaint rect.
+ LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
+ LayoutRect flippedFlowThreadPortionOverflowRect(flowThreadPortionOverflowRect);
+ flowThread()->flipForWritingMode(flippedFlowThreadPortionRect); // Put the region rects into physical coordinates.
+ flowThread()->flipForWritingMode(flippedFlowThreadPortionOverflowRect);
+
+ LayoutRect clippedRect(repaintRect);
+ clippedRect.intersect(flippedFlowThreadPortionOverflowRect);
+ if (clippedRect.isEmpty())
+ return;
+
+ // Put the region rect into the region's physical coordinate space.
+ clippedRect.setLocation(regionLocation + (clippedRect.location() - flippedFlowThreadPortionRect.location()));
+
+ // Now switch to the region's writing mode coordinate space and let it repaint itself.
+ flipForWritingMode(clippedRect);
+
+ // Issue the repaint.
+ repaintRectangle(clippedRect, immediate);
+}
+
void RenderRegion::installFlowThread()
{
ASSERT(view());
@@ -287,8 +333,8 @@ LayoutUnit RenderRegion::offsetFromLogicalTopOfFirstPage() const
if (!m_isValid || !m_flowThread)
return 0;
if (m_flowThread->isHorizontalWritingMode())
- return regionRect().y();
- return regionRect().x();
+ return flowThreadPortionRect().y();
+ return flowThreadPortionRect().x();
}
void RenderRegion::setRegionObjectsRegionStyle()
@@ -383,6 +429,7 @@ PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderObject* o
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()->styleResolver()->styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
diff --git a/Source/WebCore/rendering/RenderRegion.h b/Source/WebCore/rendering/RenderRegion.h
index 5f22a75a7..7c9b87fc0 100644
--- a/Source/WebCore/rendering/RenderRegion.h
+++ b/Source/WebCore/rendering/RenderRegion.h
@@ -47,13 +47,13 @@ public:
virtual bool isRenderRegion() const { return true; }
virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- void setRegionRect(const LayoutRect& rect) { m_regionRect = rect; }
- LayoutRect regionRect() const { return m_regionRect; }
- LayoutRect regionOversetRect() const;
+ void setFlowThreadPortionRect(const LayoutRect& rect) { m_flowThreadPortionRect = rect; }
+ LayoutRect flowThreadPortionRect() const { return m_flowThreadPortionRect; }
+ LayoutRect flowThreadPortionOverflowRect() const;
void attachRegion();
void detachRegion();
@@ -95,13 +95,37 @@ public:
RegionState regionState() const { return isValid() ? m_regionState : RegionUndefined; }
void setRegionState(RegionState regionState) { m_regionState = regionState; }
- virtual LayoutUnit logicalWidthForFlowThreadContent() const;
- virtual LayoutUnit logicalHeightForFlowThreadContent() const;
+ // 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.
+ virtual LayoutUnit pageLogicalWidth() const;
+ virtual LayoutUnit pageLogicalHeight() 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;
+
+ // 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, bool immediate) const;
protected:
void setRegionObjectsRegionStyle();
void restoreRegionObjectsOriginalStyle();
-
+
+ LayoutRect overflowRectForFlowThreadPortion(LayoutRect flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const;
+ void repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, bool immediate, const LayoutRect& flowThreadPortionRect,
+ const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& regionLocation) const;
+
private:
virtual const char* renderName() const { return "RenderRegion"; }
@@ -125,7 +149,7 @@ private:
// 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_regionRect;
+ 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
diff --git a/Source/WebCore/rendering/RenderRegionSet.cpp b/Source/WebCore/rendering/RenderRegionSet.cpp
index e9dca62a3..25b5cfa9c 100644
--- a/Source/WebCore/rendering/RenderRegionSet.cpp
+++ b/Source/WebCore/rendering/RenderRegionSet.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "RenderRegionSet.h"
+#include "RenderFlowThread.h"
+
namespace WebCore {
RenderRegionSet::RenderRegionSet(Node* node, RenderFlowThread* flowThread)
@@ -39,4 +41,23 @@ void RenderRegionSet::installFlowThread()
// 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/Source/WebCore/rendering/RenderRegionSet.h b/Source/WebCore/rendering/RenderRegionSet.h
index 3771f004e..e91eceecc 100644
--- a/Source/WebCore/rendering/RenderRegionSet.h
+++ b/Source/WebCore/rendering/RenderRegionSet.h
@@ -52,7 +52,11 @@ public:
private:
virtual void installFlowThread() OVERRIDE;
+ virtual void expandToEncompassFlowThreadContentsIfNeeded() OVERRIDE;
+
virtual const char* renderName() const = 0;
+
+ virtual bool isRenderRegionSet() const OVERRIDE { return true; }
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderScrollbar.h b/Source/WebCore/rendering/RenderScrollbar.h
index 61d980347..918eee0a9 100644
--- a/Source/WebCore/rendering/RenderScrollbar.h
+++ b/Source/WebCore/rendering/RenderScrollbar.h
@@ -26,7 +26,6 @@
#ifndef RenderScrollbar_h
#define RenderScrollbar_h
-#include "Node.h"
#include "RenderStyleConstants.h"
#include "Scrollbar.h"
#include <wtf/HashMap.h>
@@ -34,6 +33,7 @@
namespace WebCore {
class Frame;
+class Node;
class RenderBox;
class RenderScrollbarPart;
class RenderStyle;
diff --git a/Source/WebCore/rendering/RenderScrollbarPart.cpp b/Source/WebCore/rendering/RenderScrollbarPart.cpp
index 3d93fe828..f2ca8c640 100644
--- a/Source/WebCore/rendering/RenderScrollbarPart.cpp
+++ b/Source/WebCore/rendering/RenderScrollbarPart.cpp
@@ -91,7 +91,9 @@ void RenderScrollbarPart::computeScrollbarWidth()
if (!m_scrollbar->owningRenderer())
return;
RenderView* renderView = view();
- int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->borderLeft() - m_scrollbar->owningRenderer()->borderRight();
+ // 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);
@@ -107,7 +109,9 @@ void RenderScrollbarPart::computeScrollbarHeight()
if (!m_scrollbar->owningRenderer())
return;
RenderView* renderView = view();
- int visibleSize = m_scrollbar->owningRenderer()->height() - m_scrollbar->owningRenderer()->borderTop() - m_scrollbar->owningRenderer()->borderBottom();
+ // 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);
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index b5c308373..4f25944a6 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -117,10 +117,9 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
- if (child->isTableCaption()) {
- m_captions.append(toRenderTableCaption(child));
+ if (child->isTableCaption())
wrapInAnonymousSection = false;
- } else if (child->isRenderTableCol()) {
+ else if (child->isRenderTableCol()) {
m_hasColElements = true;
wrapInAnonymousSection = false;
} else if (child->isTableSection()) {
@@ -197,26 +196,34 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
section->addChild(child);
}
+void RenderTable::addCaption(const RenderTableCaption* caption)
+{
+ ASSERT(m_captions.find(caption) == notFound);
+ m_captions.append(const_cast<RenderTableCaption*>(caption));
+}
+
void RenderTable::removeCaption(const RenderTableCaption* oldCaption)
{
size_t index = m_captions.find(oldCaption);
ASSERT(index != notFound);
- m_captions.remove(index);
-
- // FIXME: The rest of this function is probably not needed since we have
- // implemented proper multiple captions support (see bug 58249).
- if (node())
- node()->setNeedsStyleRecalc();
+ if (index == notFound)
+ return;
- setNeedsSectionRecalc();
+ m_captions.remove(index);
}
void RenderTable::computeLogicalWidth()
{
recalcSectionsIfNeeded();
- if (isOutOfFlowPositioned())
- computePositionedLogicalWidth();
+ if (isOutOfFlowPositioned()) {
+ LogicalExtentComputedValues computedValues;
+ computePositionedLogicalWidth(computedValues);
+ setLogicalWidth(computedValues.m_extent);
+ setLogicalLeft(computedValues.m_position);
+ setMarginStart(computedValues.m_margins.m_start);
+ setMarginEnd(computedValues.m_margins.m_end);
+ }
RenderBlock* cb = containingBlock();
RenderView* renderView = view();
@@ -260,7 +267,13 @@ void RenderTable::computeLogicalWidth()
LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
if (avoidsFloats() && cb->containsFloats())
containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0, 0); // FIXME: Work with regions someday.
- computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth());
+ 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));
@@ -776,17 +789,12 @@ void RenderTable::recalcSections() const
m_foot = 0;
m_firstBody = 0;
m_hasColElements = false;
- m_captions.clear();
// We need to get valid pointers to caption, head, foot and first body again
RenderObject* nextSibling;
for (RenderObject* child = firstChild(); child; child = nextSibling) {
nextSibling = child->nextSibling();
switch (child->style()->display()) {
- case TABLE_CAPTION:
- if (child->isTableCaption())
- m_captions.append(toRenderTableCaption(child));
- break;
case TABLE_COLUMN:
case TABLE_COLUMN_GROUP:
m_hasColElements = true;
@@ -1269,17 +1277,17 @@ LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegi
return rect;
}
-bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
LayoutPoint adjustedLocation = accumulatedOffset + location();
// Check kids first.
- if (!hasOverflowClip() || pointInContainer.intersects(overflowClipRect(adjustedLocation, pointInContainer.region()))) {
+ if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region()))) {
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
- if (child->nodeAtPoint(request, result, pointInContainer, childPoint, action)) {
- updateHitTestResult(result, toLayoutPoint(pointInContainer.point() - childPoint));
+ if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
+ updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
return true;
}
}
@@ -1288,9 +1296,9 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Check our bounds next.
LayoutRect boundsRect(adjustedLocation, size());
- if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && pointInContainer.intersects(boundsRect)) {
- updateHitTestResult(result, flipForWritingMode(pointInContainer.point() - toLayoutSize(adjustedLocation)));
- if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
+ if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
+ updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
+ if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
return true;
}
diff --git a/Source/WebCore/rendering/RenderTable.h b/Source/WebCore/rendering/RenderTable.h
index bbafdb716..46073c539 100644
--- a/Source/WebCore/rendering/RenderTable.h
+++ b/Source/WebCore/rendering/RenderTable.h
@@ -231,6 +231,7 @@ public:
const BorderValue& tableStartBorderAdjoiningCell(const RenderTableCell*) const;
const BorderValue& tableEndBorderAdjoiningCell(const RenderTableCell*) const;
+ void addCaption(const RenderTableCaption*);
void removeCaption(const RenderTableCaption*);
protected:
@@ -249,7 +250,7 @@ private:
virtual void paintMask(PaintInfo&, const LayoutPoint&);
virtual void layout();
virtual void computePreferredLogicalWidths();
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
virtual LayoutUnit firstLineBoxBaseline() const OVERRIDE;
@@ -260,7 +261,7 @@ private:
virtual void setCellLogicalWidths();
- virtual void computeLogicalWidth();
+ virtual void computeLogicalWidth() OVERRIDE;
LayoutUnit convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth);
diff --git a/Source/WebCore/rendering/RenderTableCaption.cpp b/Source/WebCore/rendering/RenderTableCaption.cpp
index 9785f372d..df5194c97 100644
--- a/Source/WebCore/rendering/RenderTableCaption.cpp
+++ b/Source/WebCore/rendering/RenderTableCaption.cpp
@@ -39,6 +39,13 @@ LayoutUnit RenderTableCaption::containingBlockLogicalWidthForContent() const
return cb->logicalWidth();
}
+void RenderTableCaption::insertedIntoTree()
+{
+ RenderBlock::insertedIntoTree();
+
+ table()->addCaption(this);
+}
+
void RenderTableCaption::willBeRemovedFromTree()
{
RenderBlock::willBeRemovedFromTree();
diff --git a/Source/WebCore/rendering/RenderTableCaption.h b/Source/WebCore/rendering/RenderTableCaption.h
index b505ebe10..91edb9f6e 100644
--- a/Source/WebCore/rendering/RenderTableCaption.h
+++ b/Source/WebCore/rendering/RenderTableCaption.h
@@ -35,6 +35,7 @@ public:
private:
virtual bool isTableCaption() const OVERRIDE { return true; }
+ virtual void insertedIntoTree() OVERRIDE;
virtual void willBeRemovedFromTree() OVERRIDE;
RenderTable* table() const;
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp
index 0cefc75a8..05d0ad19a 100644
--- a/Source/WebCore/rendering/RenderTableCell.cpp
+++ b/Source/WebCore/rendering/RenderTableCell.cpp
@@ -52,16 +52,12 @@ RenderTableCell::RenderTableCell(Node* node)
{
}
-void RenderTableCell::willBeDestroyed()
+void RenderTableCell::willBeRemovedFromTree()
{
- RenderTableSection* recalcSection = parent() ? section() : 0;
+ RenderBlock::willBeRemovedFromTree();
- RenderBlock::willBeDestroyed();
-
- if (recalcSection) {
- recalcSection->setNeedsCellRecalc();
- recalcSection->removeCachedCollapsedBorders(this);
- }
+ section()->setNeedsCellRecalc();
+ section()->removeCachedCollapsedBorders(this);
}
unsigned RenderTableCell::colSpan() const
diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h
index 5d5b2764b..31ea56f59 100644
--- a/Source/WebCore/rendering/RenderTableCell.h
+++ b/Source/WebCore/rendering/RenderTableCell.h
@@ -173,9 +173,9 @@ private:
virtual bool isTableCell() const { return true; }
- virtual void willBeDestroyed();
+ virtual void willBeRemovedFromTree() OVERRIDE;
- virtual void computeLogicalWidth();
+ virtual void computeLogicalWidth() OVERRIDE;
virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
virtual void paintMask(PaintInfo&, const LayoutPoint&);
diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp
index 7dc05fa56..2b83faa5a 100644
--- a/Source/WebCore/rendering/RenderTableRow.cpp
+++ b/Source/WebCore/rendering/RenderTableRow.cpp
@@ -46,14 +46,11 @@ RenderTableRow::RenderTableRow(Node* node)
setInline(false); // our object is not Inline
}
-void RenderTableRow::willBeDestroyed()
+void RenderTableRow::willBeRemovedFromTree()
{
- RenderTableSection* recalcSection = section();
-
- RenderBox::willBeDestroyed();
-
- if (recalcSection)
- recalcSection->setNeedsCellRecalc();
+ RenderBox::willBeRemovedFromTree();
+
+ section()->setNeedsCellRecalc();
}
void RenderTableRow::updateBeforeAndAfterContent()
@@ -154,7 +151,7 @@ void RenderTableRow::layout()
cell->setChildNeedsLayout(true, MarkOnlyThis);
if (child->needsLayout()) {
- cell->computeBlockDirectionMargins(table());
+ cell->computeAndSetBlockDirectionMargins(table());
cell->layout();
}
}
@@ -195,7 +192,7 @@ LayoutRect RenderTableRow::clippedOverflowRectForRepaint(RenderBoxModelObject* r
}
// Hit Testing
-bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+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.
@@ -206,8 +203,8 @@ bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& r
// then we can remove this check.
if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer()) {
LayoutPoint cellPoint = flipForWritingModeForChild(toRenderTableCell(child), accumulatedOffset);
- if (child->nodeAtPoint(request, result, pointInContainer, cellPoint, action)) {
- updateHitTestResult(result, pointInContainer.point() - toLayoutSize(cellPoint));
+ if (child->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
return true;
}
}
diff --git a/Source/WebCore/rendering/RenderTableRow.h b/Source/WebCore/rendering/RenderTableRow.h
index afa838c12..0136c58a2 100644
--- a/Source/WebCore/rendering/RenderTableRow.h
+++ b/Source/WebCore/rendering/RenderTableRow.h
@@ -90,14 +90,14 @@ private:
virtual bool isTableRow() const { return true; }
- virtual void willBeDestroyed();
+ virtual void willBeRemovedFromTree() OVERRIDE;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
virtual void layout();
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
- virtual bool requiresLayer() const OVERRIDE { return isTransparent() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasMask() || hasFilter(); }
+ virtual bool requiresLayer() const OVERRIDE { return hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasClipPath() || createsGroup(); }
virtual void paint(PaintInfo&, const LayoutPoint&);
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index a906a2ef8..62379085d 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -189,12 +189,6 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
toRenderTableRow(child)->updateBeforeAndAfterContent();
}
-void RenderTableSection::removeChild(RenderObject* oldChild)
-{
- setNeedsCellRecalc();
- RenderBox::removeChild(oldChild);
-}
-
void RenderTableSection::ensureRows(unsigned numRows)
{
if (numRows <= m_grid.size())
@@ -585,9 +579,9 @@ void RenderTableSection::layoutRows()
}
}
- if (ListHashSet<RenderBox*>* percentHeightDescendants = cell->percentHeightDescendants()) {
- ListHashSet<RenderBox*>::iterator end = percentHeightDescendants->end();
- for (ListHashSet<RenderBox*>::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
+ if (TrackedRendererListHashSet* percentHeightDescendants = cell->percentHeightDescendants()) {
+ TrackedRendererListHashSet::iterator end = percentHeightDescendants->end();
+ for (TrackedRendererListHashSet::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
RenderBox* box = *it;
if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
continue;
@@ -1369,7 +1363,7 @@ void RenderTableSection::splitColumn(unsigned pos, unsigned first)
}
// Hit Testing
-bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+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())
@@ -1379,7 +1373,7 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul
// Just forward to our children always.
LayoutPoint adjustedLocation = accumulatedOffset + location();
- if (hasOverflowClip() && !pointInContainer.intersects(overflowClipRect(adjustedLocation, pointInContainer.region())))
+ if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region())))
return false;
if (hasOverflowingCell()) {
@@ -1390,8 +1384,8 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul
// then we can remove this check.
if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer()) {
LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
- if (child->nodeAtPoint(request, result, pointInContainer, childPoint, action)) {
- updateHitTestResult(result, toLayoutPoint(pointInContainer.point() - childPoint));
+ if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
+ updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
return true;
}
}
@@ -1401,7 +1395,7 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul
recalcCellsIfNeeded();
- LayoutRect hitTestRect = pointInContainer.boundingBox();
+ LayoutRect hitTestRect = locationInContainer.boundingBox();
hitTestRect.moveBy(-adjustedLocation);
LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(hitTestRect);
@@ -1421,8 +1415,8 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul
--i;
RenderTableCell* cell = current.cells[i];
LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation);
- if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, pointInContainer, cellPoint, action)) {
- updateHitTestResult(result, pointInContainer.point() - toLayoutSize(cellPoint));
+ if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
+ updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
return true;
}
}
diff --git a/Source/WebCore/rendering/RenderTableSection.h b/Source/WebCore/rendering/RenderTableSection.h
index 89bff39a0..7054938e9 100644
--- a/Source/WebCore/rendering/RenderTableSection.h
+++ b/Source/WebCore/rendering/RenderTableSection.h
@@ -210,14 +210,12 @@ private:
virtual void layout();
- virtual void removeChild(RenderObject* oldChild);
-
virtual void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&);
virtual void paintObject(PaintInfo&, const LayoutPoint&);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
void ensureRows(unsigned);
diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp
index 73e57754a..82b956993 100644
--- a/Source/WebCore/rendering/RenderText.cpp
+++ b/Source/WebCore/rendering/RenderText.cpp
@@ -1879,7 +1879,7 @@ int RenderText::nextOffset(int current) const
bool RenderText::computeCanUseSimpleFontCodePath() const
{
- if (isAllASCII())
+ if (isAllASCII() || m_text.is8Bit())
return true;
return Font::characterRangeCodePath(characters(), length()) == Font::Simple;
}
diff --git a/Source/WebCore/rendering/RenderText.h b/Source/WebCore/rendering/RenderText.h
index b96eca73f..6fc4c67a7 100644
--- a/Source/WebCore/rendering/RenderText.h
+++ b/Source/WebCore/rendering/RenderText.h
@@ -45,6 +45,12 @@ public:
virtual PassRefPtr<StringImpl> originalText() const;
+ void updateTextIfNeeded()
+ {
+ if (preferredLogicalWidthsDirty())
+ updateText();
+ }
+
void extractTextBox(InlineTextBox*);
void attachTextBox(InlineTextBox*);
void removeTextBox(InlineTextBox*);
@@ -139,6 +145,7 @@ protected:
virtual void styleWillChange(StyleDifference, const RenderStyle*) { }
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void updateText() { }
virtual void setTextInternal(PassRefPtr<StringImpl>);
virtual UChar previousCharacter() const;
@@ -156,7 +163,7 @@ private:
virtual void paint(PaintInfo&, const LayoutPoint&) { ASSERT_NOT_REACHED(); }
virtual void layout() { ASSERT_NOT_REACHED(); }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint&, const LayoutPoint&, HitTestAction) OVERRIDE { ASSERT_NOT_REACHED(); return false; }
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction) OVERRIDE { ASSERT_NOT_REACHED(); return false; }
void deleteTextBoxes();
bool containsOnlyWhitespace(unsigned from, unsigned len) const;
diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp
index 3bc25b897..cb7637db3 100644
--- a/Source/WebCore/rendering/RenderTextControl.cpp
+++ b/Source/WebCore/rendering/RenderTextControl.cpp
@@ -110,13 +110,18 @@ int RenderTextControl::textBlockWidth() const
{
Element* innerText = innerTextElement();
ASSERT(innerText);
- return width() - borderAndPaddingWidth() - innerText->renderBox()->paddingLeft() - innerText->renderBox()->paddingRight();
+
+ LayoutUnit unitWidth = width() - borderAndPaddingWidth();
+ if (innerText->renderer())
+ unitWidth -= innerText->renderBox()->paddingLeft() + innerText->renderBox()->paddingRight();
+
+ return unitWidth;
}
void RenderTextControl::updateFromElement()
{
Element* innerText = innerTextElement();
- if (innerText)
+ if (innerText && innerText->renderer())
updateUserModifyProperty(node(), innerText->renderer()->style());
}
@@ -143,13 +148,14 @@ void RenderTextControl::computeLogicalHeight()
{
HTMLElement* innerText = innerTextElement();
ASSERT(innerText);
- RenderBox* innerTextBox = innerText->renderBox();
- LayoutUnit nonContentHeight = innerTextBox->borderAndPaddingHeight() + innerTextBox->marginHeight();
- setHeight(computeControlHeight(innerTextBox->lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes), nonContentHeight) + borderAndPaddingHeight());
+ if (RenderBox* innerTextBox = innerText->renderBox()) {
+ LayoutUnit nonContentHeight = innerTextBox->borderAndPaddingHeight() + innerTextBox->marginHeight();
+ setHeight(computeControlHeight(innerTextBox->lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes), nonContentHeight) + borderAndPaddingHeight());
- // 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 (style()->overflowX() == OSCROLL || (style()->overflowX() == OAUTO && innerText->renderer()->style()->wordWrap() == NormalWordWrap))
- setHeight(height() + scrollbarThickness());
+ // 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 (style()->overflowX() == OSCROLL || (style()->overflowX() == OAUTO && innerText->renderer()->style()->overflowWrap() == NormalOverflowWrap))
+ setHeight(height() + scrollbarThickness());
+ }
RenderBlock::computeLogicalHeight();
}
@@ -157,6 +163,9 @@ void RenderTextControl::computeLogicalHeight()
void RenderTextControl::hitInnerTextElement(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
{
HTMLElement* innerText = innerTextElement();
+ if (!innerText->renderer())
+ return;
+
LayoutPoint adjustedLocation = accumulatedOffset + location();
LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerText->renderBox()->location());
if (hasOverflowClip())
@@ -257,8 +266,9 @@ void RenderTextControl::computePreferredLogicalWidths()
else {
// Use average character width. Matches IE.
AtomicString family = style()->font().family().family();
- RenderBox* innerTextRenderBox = innerTextElement()->renderBox();
- m_maxPreferredLogicalWidth = preferredContentWidth(getAvgCharWidth(family)) + innerTextRenderBox->paddingLeft() + innerTextRenderBox->paddingRight();
+ m_maxPreferredLogicalWidth = preferredContentWidth(getAvgCharWidth(family));
+ if (RenderBox* innerTextRenderBox = innerTextElement()->renderBox())
+ m_maxPreferredLogicalWidth += innerTextRenderBox->paddingLeft() + innerTextRenderBox->paddingRight();
}
if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h
index b8f1f3025..6d0e43af1 100644
--- a/Source/WebCore/rendering/RenderTextControl.h
+++ b/Source/WebCore/rendering/RenderTextControl.h
@@ -62,7 +62,7 @@ protected:
virtual RenderStyle* textBaseStyle() const = 0;
virtual void updateFromElement();
- virtual void computeLogicalHeight();
+ virtual void computeLogicalHeight() OVERRIDE;
virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren);
private:
diff --git a/Source/WebCore/rendering/RenderTextControlMultiLine.cpp b/Source/WebCore/rendering/RenderTextControlMultiLine.cpp
index 96997d0ed..be91de927 100644
--- a/Source/WebCore/rendering/RenderTextControlMultiLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -43,13 +43,13 @@ RenderTextControlMultiLine::~RenderTextControlMultiLine()
static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
}
-bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- if (!RenderTextControl::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, hitTestAction))
+ if (!RenderTextControl::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
return false;
if (result.innerNode() == node() || result.innerNode() == innerTextElement())
- hitInnerTextElement(result, pointInContainer.point(), accumulatedOffset);
+ hitInnerTextElement(result, locationInContainer.point(), accumulatedOffset);
return true;
}
diff --git a/Source/WebCore/rendering/RenderTextControlMultiLine.h b/Source/WebCore/rendering/RenderTextControlMultiLine.h
index 5c84a5910..a4539959a 100644
--- a/Source/WebCore/rendering/RenderTextControlMultiLine.h
+++ b/Source/WebCore/rendering/RenderTextControlMultiLine.h
@@ -34,7 +34,7 @@ public:
private:
virtual bool isTextArea() const { return true; }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual float getAvgCharWidth(AtomicString family);
virtual LayoutUnit preferredContentWidth(float charWidth) const;
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
index 665af32be..1484a2786 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -192,9 +192,9 @@ void RenderTextControlSingleLine::layout()
}
}
-bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- if (!RenderTextControl::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, hitTestAction))
+ if (!RenderTextControl::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
return false;
// Say that we hit the inner text element if
@@ -203,7 +203,7 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
// - we hit regions not in any decoration buttons.
HTMLElement* container = containerElement();
if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node() || (container && container == result.innerNode())) {
- LayoutPoint pointInParent = pointInContainer.point();
+ LayoutPoint pointInParent = locationInContainer.point();
if (container && innerBlockElement()) {
if (innerBlockElement()->renderBox())
pointInParent -= toLayoutSize(innerBlockElement()->renderBox()->location());
@@ -342,7 +342,7 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const
adjustInnerTextStyle(startStyle, textBlockStyle.get());
textBlockStyle->setWhiteSpace(PRE);
- textBlockStyle->setWordWrap(NormalWordWrap);
+ textBlockStyle->setOverflowWrap(NormalOverflowWrap);
textBlockStyle->setOverflowX(OHIDDEN);
textBlockStyle->setOverflowY(OHIDDEN);
textBlockStyle->setTextOverflow(textShouldBeTruncated() ? TextOverflowEllipsis : TextOverflowClip);
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.h b/Source/WebCore/rendering/RenderTextControlSingleLine.h
index c79f3dfec..af27bf758 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.h
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.h
@@ -56,7 +56,7 @@ private:
virtual void paint(PaintInfo&, const LayoutPoint&);
virtual void layout();
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual void autoscroll();
diff --git a/Source/WebCore/rendering/RenderTheme.cpp b/Source/WebCore/rendering/RenderTheme.cpp
index 934c4b2cf..66c37ec35 100644
--- a/Source/WebCore/rendering/RenderTheme.cpp
+++ b/Source/WebCore/rendering/RenderTheme.cpp
@@ -1004,21 +1004,34 @@ void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo,
IntSize tickSize = sliderTickSize();
float zoomFactor = o->style()->effectiveZoom();
FloatRect tickRect;
- int tickRegionMargin = (thumbSize.width() - tickSize.width()) / 2.0;
int tickRegionSideMargin = 0;
int tickRegionWidth = 0;
+ IntRect trackBounds;
+ RenderObject* trackRenderer = input->sliderTrackElement()->renderer();
+ // We can ignoring transforms because transform is handled by the graphics context.
+ if (trackRenderer)
+ trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
+ IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms();
+
+ // Make position relative to the transformed ancestor element.
+ trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
+ trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
+
if (isHorizontal) {
tickRect.setWidth(floor(tickSize.width() * zoomFactor));
tickRect.setHeight(floor(tickSize.height() * zoomFactor));
tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
- tickRegionSideMargin = rect.x() + tickRegionMargin;
- tickRegionWidth = rect.width() - tickRegionMargin * 2 - tickSize.width() * zoomFactor;
+ if (o->style()->isLeftToRightDirection())
+ tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
+ else
+ tickRegionSideMargin = trackBounds.x() - thumbSize.width() / 2.0;
+ tickRegionWidth = trackBounds.width();
} else {
tickRect.setWidth(floor(tickSize.height() * zoomFactor));
tickRect.setHeight(floor(tickSize.width() * zoomFactor));
tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
- tickRegionSideMargin = rect.y() + tickRegionMargin;
- tickRegionWidth = rect.height() - tickRegionMargin * 2 - tickSize.width() * zoomFactor;
+ tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
+ tickRegionWidth = trackBounds.height();
}
RefPtr<HTMLCollection> options = dataList->options();
GraphicsContextStateSaver stateSaver(*paintInfo.context);
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.h b/Source/WebCore/rendering/RenderThemeChromiumMac.h
index 5853a0661..cfd13df60 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.h
@@ -58,6 +58,7 @@ protected:
virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const;
virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
#endif
virtual bool usesTestModeFocusRingColor() const;
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.mm b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
index 9af2dbc4c..efb6174ec 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.mm
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -233,6 +233,11 @@ bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* object, co
{
return RenderMediaControlsChromium::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect);
}
+
+bool RenderThemeChromiumMac::paintMediaToggleClosedCaptionsButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaShowClosedCaptionsButton, object, paintInfo, rect);
+}
#endif
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
index 0a58af605..a38cf1be9 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -81,7 +81,7 @@ static const float defaultSearchFieldResultsButtonWidth = 18;
// sizes (e.g. 15px). So, for now we just use Arial.
const String& RenderThemeChromiumSkia::defaultGUIFont()
{
- DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
+ DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Arial")));
return fontFace;
}
@@ -131,6 +131,13 @@ bool RenderThemeChromiumSkia::supportsDataListUI(const AtomicString& type) const
return RenderThemeChromiumCommon::supportsDataListUI(type);
}
+#if ENABLE(VIDEO_TRACK)
+bool RenderThemeChromiumSkia::supportsClosedCaptioning() const
+{
+ return true;
+}
+#endif
+
Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
{
return Color(0x1e, 0x90, 0xff);
@@ -427,6 +434,18 @@ bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const
#endif
}
+bool RenderThemeChromiumSkia::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO_TRACK)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaShowClosedCaptionsButton, o, paintInfo, r);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
#if ENABLE(VIDEO)
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.h b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
index ee9b11c37..10dc70b41 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
@@ -54,6 +54,9 @@ class RenderThemeChromiumSkia : public RenderTheme {
virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
+#if ENABLE(VIDEO_TRACK)
+ virtual bool supportsClosedCaptioning() const OVERRIDE;
+#endif
// The platform selection color.
virtual Color platformActiveSelectionBackgroundColor() const;
virtual Color platformInactiveSelectionBackgroundColor() const;
@@ -95,6 +98,7 @@ class RenderThemeChromiumSkia : public RenderTheme {
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&);
diff --git a/Source/WebCore/rendering/RenderThemeWin.cpp b/Source/WebCore/rendering/RenderThemeWin.cpp
index 403dd98b1..810a1fca4 100644
--- a/Source/WebCore/rendering/RenderThemeWin.cpp
+++ b/Source/WebCore/rendering/RenderThemeWin.cpp
@@ -24,6 +24,7 @@
#include "CSSValueKeywords.h"
#include "Element.h"
+#include "FontMetrics.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "LocalWindowsContext.h"
diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp
index 8af6a2765..276366c0b 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/RenderTreeAsText.cpp
@@ -315,19 +315,16 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
if (box.borderTop() || box.borderRight() || box.borderBottom() || box.borderLeft()) {
ts << " [border:";
- BorderValue prevBorder;
- if (o.style()->borderTop() != prevBorder) {
- prevBorder = o.style()->borderTop();
- if (!box.borderTop())
- ts << " none";
- else {
- ts << " (" << box.borderTop() << "px ";
- printBorderStyle(ts, o.style()->borderTopStyle());
- Color col = o.style()->borderTopColor();
- if (!col.isValid())
- col = o.style()->color();
- ts << col.nameForRenderTreeAsText() << ")";
- }
+ BorderValue prevBorder = o.style()->borderTop();
+ if (!box.borderTop())
+ ts << " none";
+ else {
+ ts << " (" << box.borderTop() << "px ";
+ printBorderStyle(ts, o.style()->borderTopStyle());
+ Color col = o.style()->borderTopColor();
+ if (!col.isValid())
+ col = o.style()->color();
+ ts << col.nameForRenderTreeAsText() << ")";
}
if (o.style()->borderRight() != prevBorder) {
@@ -448,14 +445,14 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
ts << " id=\"" + static_cast<Element*>(node)->getIdAttribute() + "\"";
if (node->hasClass()) {
+ ts << " class=\"";
StyledElement* styledElement = static_cast<StyledElement*>(node);
- String classes;
for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
if (i > 0)
- classes += " ";
- classes += styledElement->classNames()[i];
+ ts << " ";
+ ts << styledElement->classNames()[i];
}
- ts << " class=\"" + classes + "\"";
+ ts << "\"";
}
}
}
@@ -702,12 +699,12 @@ static void writeRenderNamedFlowThreads(TextStream& ts, RenderView* renderView,
RenderRegion* renderRegion = *itRR;
writeIndent(ts, indent + 2);
ts << "RenderRegion";
- if (renderRegion->node()) {
- String tagName = getTagName(renderRegion->node());
+ if (renderRegion->generatingNode()) {
+ String tagName = getTagName(renderRegion->generatingNode());
if (!tagName.isEmpty())
ts << " {" << tagName << "}";
- if (renderRegion->node()->isElementNode() && renderRegion->node()->hasID()) {
- Element* element = static_cast<Element*>(renderRegion->node());
+ if (renderRegion->generatingNode()->isElementNode() && renderRegion->generatingNode()->hasID()) {
+ Element* element = static_cast<Element*>(renderRegion->generatingNode());
ts << " #" << element->idForStyleResolution();
}
if (renderRegion->hasCustomRegionStyle())
@@ -792,29 +789,36 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
static String nodePosition(Node* node)
{
- String result;
+ StringBuilder result;
Element* body = node->document()->body();
Node* parent;
for (Node* n = node; n; n = parent) {
parent = n->parentOrHostNode();
if (n != node)
- result += " of ";
+ result.appendLiteral(" of ");
if (parent) {
if (body && n == body) {
// We don't care what offset body may be in the document.
- result += "body";
+ result.appendLiteral("body");
break;
}
- if (n->isShadowRoot())
- result += "{" + getTagName(n) + "}";
- else
- result += "child " + String::number(n->nodeIndex()) + " {" + getTagName(n) + "}";
+ if (n->isShadowRoot()) {
+ result.append('{');
+ result.append(getTagName(n));
+ result.append('}');
+ } else {
+ result.appendLiteral("child ");
+ result.appendNumber(n->nodeIndex());
+ result.appendLiteral(" {");
+ result.append(getTagName(n));
+ result.append('}');
+ }
} else
- result += "document";
+ result.appendLiteral("document");
}
- return result;
+ return result.toString();
}
static void writeSelection(TextStream& ts, const RenderObject* o)
diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp
index 8cc34a330..c79c66426 100644
--- a/Source/WebCore/rendering/RenderView.cpp
+++ b/Source/WebCore/rendering/RenderView.cpp
@@ -248,6 +248,11 @@ void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
ASSERT(!needsLayout());
// RenderViews should never be called to paint with an offset not on device pixels.
ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
+
+ // This avoids painting garbage between columns if there is a column gap.
+ if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated)
+ paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor(), ColorSpaceDeviceRGB);
+
paintObject(paintInfo, paintOffset);
}
@@ -811,11 +816,6 @@ void RenderView::pushLayoutState(RenderObject* root)
m_layoutState = new (renderArena()) LayoutState(root);
}
-void RenderView::pushLayoutState(RenderFlowThread* flowThread, bool regionsChanged)
-{
- m_layoutState = new (renderArena()) LayoutState(m_layoutState, flowThread, regionsChanged);
-}
-
bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
{
RenderObject* o = renderer;
@@ -937,19 +937,4 @@ RenderBlock::IntervalArena* RenderView::intervalArena()
return m_intervalArena.get();
}
-void RenderView::setFixedPositionedObjectsNeedLayout()
-{
- ASSERT(m_frameView);
-
- ListHashSet<RenderBox*>* positionedObjects = this->positionedObjects();
- if (!positionedObjects)
- return;
-
- ListHashSet<RenderBox*>::const_iterator end = positionedObjects->end();
- for (ListHashSet<RenderBox*>::const_iterator it = positionedObjects->begin(); it != end; ++it) {
- RenderBox* currBox = *it;
- currBox->setNeedsLayout(true);
- }
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderView.h b/Source/WebCore/rendering/RenderView.h
index 296c629ec..4848ca9bb 100644
--- a/Source/WebCore/rendering/RenderView.h
+++ b/Source/WebCore/rendering/RenderView.h
@@ -193,8 +193,6 @@ public:
IntSize viewportSize() const { return document()->viewportSize(); }
- void setFixedPositionedObjectsNeedLayout();
-
void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; }
RenderQuote* renderQuoteHead() const { return m_renderQuoteHead; }
@@ -351,17 +349,7 @@ public:
, m_didCreateLayoutState(false)
{
}
-
- LayoutStateMaintainer(RenderView* view, RenderFlowThread* flowThread, bool regionsChanged)
- : m_view(view)
- , m_disabled(false)
- , m_didStart(false)
- , m_didEnd(false)
- , m_didCreateLayoutState(false)
- {
- push(flowThread, regionsChanged);
- }
-
+
~LayoutStateMaintainer()
{
ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop().
@@ -376,14 +364,6 @@ public:
m_view->disableLayoutState();
m_didStart = true;
}
-
- void push(RenderFlowThread* flowThread, bool regionsChanged)
- {
- ASSERT(!m_didStart);
- m_view->pushLayoutState(flowThread, regionsChanged);
- m_didCreateLayoutState = true;
- m_didStart = true;
- }
void pop()
{
diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp
index fc4f2f35a..9537edf5d 100644
--- a/Source/WebCore/rendering/RenderWidget.cpp
+++ b/Source/WebCore/rendering/RenderWidget.cpp
@@ -385,10 +385,10 @@ RenderWidget* RenderWidget::find(const Widget* widget)
return widgetRendererMap().get(widget);
}
-bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
bool hadResult = result.innerNode();
- bool inside = RenderReplaced::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, action);
+ bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
// Check to see if we are really over the widget itself (and not just in the border/padding area).
if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node())
diff --git a/Source/WebCore/rendering/RenderWidget.h b/Source/WebCore/rendering/RenderWidget.h
index b93ae7b5a..b7db3b809 100644
--- a/Source/WebCore/rendering/RenderWidget.h
+++ b/Source/WebCore/rendering/RenderWidget.h
@@ -60,7 +60,7 @@ protected:
virtual void layout();
virtual void paint(PaintInfo&, const LayoutPoint&);
virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
private:
virtual bool isWidget() const { return true; }
diff --git a/Source/WebCore/rendering/RenderingAllInOne.cpp b/Source/WebCore/rendering/RenderingAllInOne.cpp
index 1f0a4a38e..03bdd3f8b 100644
--- a/Source/WebCore/rendering/RenderingAllInOne.cpp
+++ b/Source/WebCore/rendering/RenderingAllInOne.cpp
@@ -51,6 +51,7 @@
#include "RenderCounter.cpp"
#include "RenderDeprecatedFlexibleBox.cpp"
#include "RenderDetailsMarker.cpp"
+#include "RenderDialog.cpp"
#include "RenderEmbeddedObject.cpp"
#include "RenderFieldset.cpp"
#include "RenderFileUploadControl.cpp"
diff --git a/Source/WebCore/rendering/RootInlineBox.cpp b/Source/WebCore/rendering/RootInlineBox.cpp
index 4313fa735..928fe667e 100644
--- a/Source/WebCore/rendering/RootInlineBox.cpp
+++ b/Source/WebCore/rendering/RootInlineBox.cpp
@@ -217,15 +217,15 @@ void RootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
#endif
}
-bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
if (hasEllipsisBox() && visibleToHitTesting()) {
- if (ellipsisBox()->nodeAtPoint(request, result, pointInContainer, accumulatedOffset, lineTop, lineBottom)) {
- renderer()->updateHitTestResult(result, pointInContainer.point() - toLayoutSize(accumulatedOffset));
+ if (ellipsisBox()->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
+ renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
return true;
}
}
- return InlineFlowBox::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, lineTop, lineBottom);
+ return InlineFlowBox::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom);
}
void RootInlineBox::adjustPosition(float dx, float dy)
diff --git a/Source/WebCore/rendering/RootInlineBox.h b/Source/WebCore/rendering/RootInlineBox.h
index 27c1afcea..525b29503 100644
--- a/Source/WebCore/rendering/RootInlineBox.h
+++ b/Source/WebCore/rendering/RootInlineBox.h
@@ -118,7 +118,7 @@ public:
#endif
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
using InlineBox::hasSelectedChildren;
using InlineBox::setHasSelectedChildren;
diff --git a/Source/WebCore/rendering/TextAutosizer.h b/Source/WebCore/rendering/TextAutosizer.h
index c8ade00f7..ae9fd8363 100644
--- a/Source/WebCore/rendering/TextAutosizer.h
+++ b/Source/WebCore/rendering/TextAutosizer.h
@@ -28,7 +28,7 @@
#if ENABLE(TEXT_AUTOSIZING)
-#include "LayoutTypes.h"
+#include "IntSize.h"
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
diff --git a/Source/WebCore/rendering/WrapShapeInfo.cpp b/Source/WebCore/rendering/WrapShapeInfo.cpp
new file mode 100644
index 000000000..8ef73c7fc
--- /dev/null
+++ b/Source/WebCore/rendering/WrapShapeInfo.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 "WrapShapeInfo.h"
+
+#if ENABLE(CSS_EXCLUSIONS)
+
+#include "NotImplemented.h"
+#include "RenderBlock.h"
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+typedef HashMap<const RenderBlock*, OwnPtr<WrapShapeInfo> > WrapShapeInfoMap;
+
+static WrapShapeInfoMap& wrapShapeInfoMap()
+{
+ DEFINE_STATIC_LOCAL(WrapShapeInfoMap, staticWrapShapeInfoMap, ());
+ return staticWrapShapeInfoMap;
+}
+
+WrapShapeInfo::WrapShapeInfo(RenderBlock* block)
+ : m_block(block)
+ , m_wrapShapeSizeDirty(true)
+{
+}
+
+WrapShapeInfo::~WrapShapeInfo()
+{
+}
+
+WrapShapeInfo* WrapShapeInfo::ensureWrapShapeInfoForRenderBlock(RenderBlock* block)
+{
+ WrapShapeInfoMap::AddResult result = wrapShapeInfoMap().add(block, create(block));
+ return result.iterator->second.get();
+}
+
+WrapShapeInfo* WrapShapeInfo::wrapShapeInfoForRenderBlock(const RenderBlock* block)
+{
+ ASSERT(block->style()->wrapShapeInside());
+ return wrapShapeInfoMap().get(block);
+}
+
+bool WrapShapeInfo::isWrapShapeInfoEnabledForRenderBlock(const RenderBlock* block)
+{
+ // FIXME: Bug 89705: Enable shape inside for vertical writing modes
+ if (!block->isHorizontalWritingMode())
+ return false;
+
+ // FIXME: Bug 89707: Enable shape inside for non-rectangular shapes
+ BasicShape* shape = block->style()->wrapShapeInside();
+ return (shape && shape->type() == BasicShape::BASIC_SHAPE_RECTANGLE);
+}
+
+void WrapShapeInfo::removeWrapShapeInfoForRenderBlock(const RenderBlock* block)
+{
+ if (!block->style() || !block->style()->wrapShapeInside())
+ return;
+ wrapShapeInfoMap().remove(block);
+}
+
+bool WrapShapeInfo::hasSegments() const
+{
+ // All line positions within a shape should have at least one segment
+ ASSERT(lineState() != LINE_INSIDE_SHAPE || m_segments.size());
+ return m_segments.size();
+}
+
+void WrapShapeInfo::computeShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight)
+{
+ if (!m_wrapShapeSizeDirty && logicalWidth == m_logicalWidth && logicalHeight == m_logicalHeight)
+ return;
+
+ m_wrapShapeSizeDirty = false;
+ m_logicalWidth = logicalWidth;
+ m_logicalHeight = logicalHeight;
+
+ // FIXME: Bug 89993: The wrap shape may come from the parent object
+ BasicShape* shape = m_block->style()->wrapShapeInside();
+
+ ASSERT(shape);
+
+ switch (shape->type()) {
+ case BasicShape::BASIC_SHAPE_RECTANGLE: {
+ BasicShapeRectangle* rect = static_cast<BasicShapeRectangle *>(shape);
+ m_shapeLeft = valueForLength(rect->x(), m_logicalWidth);
+ m_shapeWidth = valueForLength(rect->width(), m_logicalWidth);
+ m_shapeTop = valueForLength(rect->y(), m_logicalHeight);
+ m_shapeHeight = valueForLength(rect->height(), m_logicalHeight);
+ break;
+ }
+ // FIXME: Bug 89707: Enable shape inside for non-rectangular shapes
+ case BasicShape::BASIC_SHAPE_CIRCLE:
+ case BasicShape::BASIC_SHAPE_ELLIPSE:
+ case BasicShape::BASIC_SHAPE_POLYGON: {
+ notImplemented();
+ break;
+ }
+ }
+}
+
+bool WrapShapeInfo::computeSegmentsForLine(LayoutUnit lineTop)
+{
+ m_lineTop = lineTop;
+ m_segments.clear();
+ if (lineState() == LINE_INSIDE_SHAPE) {
+ LineSegment segment;
+ segment.logicalLeft = m_shapeLeft;
+ segment.logicalRight = m_shapeLeft + m_shapeWidth;
+ m_segments.append(segment);
+ }
+ return m_segments.size();
+}
+
+}
+#endif
diff --git a/Source/WebCore/rendering/WrapShapeInfo.h b/Source/WebCore/rendering/WrapShapeInfo.h
new file mode 100644
index 000000000..a8036d0bb
--- /dev/null
+++ b/Source/WebCore/rendering/WrapShapeInfo.h
@@ -0,0 +1,107 @@
+/*
+ * 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 WrapShapeInfo_h
+#define WrapShapeInfo_h
+
+#if ENABLE(CSS_EXCLUSIONS)
+
+#include "LayoutTypesInlineMethods.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderBlock;
+class WrapShapeInfo;
+
+struct LineSegment {
+ LayoutUnit logicalLeft;
+ LayoutUnit logicalRight;
+};
+
+typedef Vector<LineSegment> SegmentList;
+
+class WrapShapeInfo {
+public:
+ enum LineState {
+ LINE_BEFORE_SHAPE,
+ LINE_INSIDE_SHAPE,
+ LINE_AFTER_SHAPE
+ };
+
+ ~WrapShapeInfo();
+
+ static PassOwnPtr<WrapShapeInfo> create(RenderBlock* block) { return adoptPtr(new WrapShapeInfo(block)); }
+ static WrapShapeInfo* wrapShapeInfoForRenderBlock(const RenderBlock*);
+ static WrapShapeInfo* ensureWrapShapeInfoForRenderBlock(RenderBlock*);
+ static void removeWrapShapeInfoForRenderBlock(const RenderBlock*);
+ static bool isWrapShapeInfoEnabledForRenderBlock(const RenderBlock*);
+
+ LayoutUnit shapeTop() const { return m_shapeTop; }
+ bool hasSegments() const;
+ const SegmentList& segments() const
+ {
+ ASSERT(hasSegments());
+ return m_segments;
+ }
+ bool computeSegmentsForLine(LayoutUnit);
+ LineState lineState() const;
+ void computeShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight);
+ void dirtyWrapShapeSize() { m_wrapShapeSizeDirty = true; }
+
+private:
+ WrapShapeInfo(RenderBlock*);
+
+ RenderBlock* m_block;
+ LayoutUnit m_shapeLeft;
+ LayoutUnit m_shapeTop;
+ LayoutUnit m_shapeWidth;
+ LayoutUnit m_shapeHeight;
+
+ LayoutUnit m_lineTop;
+ LayoutUnit m_logicalWidth;
+ LayoutUnit m_logicalHeight;
+
+ SegmentList m_segments;
+ bool m_wrapShapeSizeDirty;
+};
+
+inline WrapShapeInfo::LineState WrapShapeInfo::lineState() const
+{
+ if (m_lineTop < m_shapeTop)
+ return LINE_BEFORE_SHAPE;
+ if (m_lineTop < m_shapeTop + m_shapeHeight)
+ return LINE_INSIDE_SHAPE;
+ return LINE_AFTER_SHAPE;
+}
+
+}
+#endif
+#endif
diff --git a/Source/WebCore/rendering/break_lines.cpp b/Source/WebCore/rendering/break_lines.cpp
index 4bba3ce7e..f1b5ca18f 100644
--- a/Source/WebCore/rendering/break_lines.cpp
+++ b/Source/WebCore/rendering/break_lines.cpp
@@ -38,7 +38,8 @@
namespace WebCore {
-static inline bool isBreakableSpace(UChar ch, bool treatNoBreakSpaceAsBreak)
+template<bool treatNoBreakSpaceAsBreak>
+static inline bool isBreakableSpace(UChar ch)
{
switch (ch) {
case ' ':
@@ -138,12 +139,16 @@ static inline bool shouldBreakAfter(UChar lastCh, UChar ch, UChar nextCh)
return false;
}
-static inline bool needsLineBreakIterator(UChar ch)
+template<bool treatNoBreakSpaceAsBreak>
+inline bool needsLineBreakIterator(UChar ch)
{
+ if (treatNoBreakSpaceAsBreak)
+ return ch > asciiLineBreakTableLastChar;
return ch > asciiLineBreakTableLastChar && ch != noBreakSpace;
}
-int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos, bool treatNoBreakSpaceAsBreak)
+template<bool treatNoBreakSpaceAsBreak>
+static inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos)
{
const UChar* str = lazyBreakIterator.string();
int len = lazyBreakIterator.length();
@@ -154,16 +159,16 @@ int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos, boo
for (int i = pos; i < len; i++) {
UChar ch = str[i];
- if (isBreakableSpace(ch, treatNoBreakSpaceAsBreak) || shouldBreakAfter(lastLastCh, lastCh, ch))
+ if (isBreakableSpace<treatNoBreakSpaceAsBreak>(ch) || shouldBreakAfter(lastLastCh, lastCh, ch))
return i;
- if (needsLineBreakIterator(ch) || needsLineBreakIterator(lastCh)) {
+ if (needsLineBreakIterator<treatNoBreakSpaceAsBreak>(ch) || needsLineBreakIterator<treatNoBreakSpaceAsBreak>(lastCh)) {
if (nextBreak < i && i) {
TextBreakIterator* breakIterator = lazyBreakIterator.get();
if (breakIterator)
nextBreak = textBreakFollowing(breakIterator, i - 1);
}
- if (i == nextBreak && !isBreakableSpace(lastCh, treatNoBreakSpaceAsBreak))
+ if (i == nextBreak && !isBreakableSpace<treatNoBreakSpaceAsBreak>(lastCh))
return i;
}
@@ -174,4 +179,14 @@ int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos, boo
return len;
}
+int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator& lazyBreakIterator, int pos)
+{
+ return nextBreakablePosition<false>(lazyBreakIterator, pos);
+}
+
+int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos)
+{
+ return nextBreakablePosition<true>(lazyBreakIterator, pos);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/break_lines.h b/Source/WebCore/rendering/break_lines.h
index 6600e524b..692363009 100644
--- a/Source/WebCore/rendering/break_lines.h
+++ b/Source/WebCore/rendering/break_lines.h
@@ -27,12 +27,17 @@ namespace WebCore {
class LazyLineBreakIterator;
-int nextBreakablePosition(LazyLineBreakIterator&, int pos, bool breakNBSP = false);
+int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator&, int pos);
+int nextBreakablePosition(LazyLineBreakIterator&, int pos);
-inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP = false)
+inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP)
{
- if (pos > nextBreakable)
- nextBreakable = nextBreakablePosition(lazyBreakIterator, pos, breakNBSP);
+ if (pos > nextBreakable) {
+ if (breakNBSP)
+ nextBreakable = nextBreakablePosition(lazyBreakIterator, pos);
+ else
+ nextBreakable = nextBreakablePositionIgnoringNBSP(lazyBreakIterator, pos);
+ }
return pos == nextBreakable;
}
diff --git a/Source/WebCore/rendering/style/BasicShapes.cpp b/Source/WebCore/rendering/style/BasicShapes.cpp
new file mode 100644
index 000000000..9b1245f66
--- /dev/null
+++ b/Source/WebCore/rendering/style/BasicShapes.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 "BasicShapes.h"
+#include "FloatRect.h"
+#include "LengthFunctions.h"
+#include "Path.h"
+
+namespace WebCore {
+
+void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox)
+{
+ 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(m_cornerRadiusX.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusX, boundingBox.width()),
+ m_cornerRadiusY.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusY, boundingBox.height())));
+}
+
+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);
+ path.addEllipse(FloatRect(centerX - radius + boundingBox.x(),
+ centerY - radius + boundingBox.y(),
+ radius * 2,
+ radius * 2));
+}
+
+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());
+ path.addEllipse(FloatRect(centerX - radiusX + boundingBox.x(),
+ centerY - radiusY + boundingBox.y(),
+ radiusX * 2,
+ radiusY * 2));
+}
+
+void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
+{
+ ASSERT(path.isEmpty());
+ ASSERT(!(m_values.size() % 2));
+ size_t length = m_values.size();
+
+ if (!length)
+ return;
+
+ path.moveTo(FloatPoint(floatValueForLength(m_values.at(0), boundingBox.width()) + boundingBox.x(),
+ floatValueForLength(m_values.at(1), boundingBox.width()) + boundingBox.y()));
+ for (size_t i = 2; i < length; i = i + 2) {
+ path.addLineTo(FloatPoint(floatValueForLength(m_values.at(i), boundingBox.width()) + boundingBox.x(),
+ floatValueForLength(m_values.at(i + 1), boundingBox.width()) + boundingBox.y()));
+ }
+ path.closeSubpath();
+}
+}
diff --git a/Source/WebCore/rendering/style/WrapShapes.h b/Source/WebCore/rendering/style/BasicShapes.h
index 86928b68c..ad1182676 100644
--- a/Source/WebCore/rendering/style/WrapShapes.h
+++ b/Source/WebCore/rendering/style/BasicShapes.h
@@ -27,46 +27,42 @@
* SUCH DAMAGE.
*/
-#ifndef WrapShapes_h
-#define WrapShapes_h
+#ifndef BasicShapes_h
+#define BasicShapes_h
#include "Length.h"
#include "WindRule.h"
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
namespace WebCore {
-class WrapShape : public WTF::RefCountedBase {
+class FloatRect;
+class Path;
+
+class BasicShape : public RefCounted<BasicShape> {
public:
+ virtual ~BasicShape() { }
+
enum Type {
- WRAP_SHAPE_RECTANGLE = 1,
- WRAP_SHAPE_CIRCLE = 2,
- WRAP_SHAPE_ELLIPSE = 3,
- WRAP_SHAPE_POLYGON = 4
+ BASIC_SHAPE_RECTANGLE = 1,
+ BASIC_SHAPE_CIRCLE = 2,
+ BASIC_SHAPE_ELLIPSE = 3,
+ BASIC_SHAPE_POLYGON = 4
};
-
- void deref()
- {
- if (derefBase())
- destroy();
- }
- Type type() const { return m_type; }
+ virtual void path(Path&, const FloatRect&) = 0;
+ virtual WindRule windRule() const { return RULE_NONZERO; }
+ virtual Type type() const = 0;
protected:
- WrapShape(Type type)
- : m_type(type)
- { }
-
-private:
- void destroy();
- Type m_type;
+ BasicShape() { }
};
-class WrapShapeRectangle : public WrapShape {
+class BasicShapeRectangle : public BasicShape {
public:
- static PassRefPtr<WrapShapeRectangle> create() { return adoptRef(new WrapShapeRectangle); }
+ static PassRefPtr<BasicShapeRectangle> create() { return adoptRef(new BasicShapeRectangle); }
Length x() const { return m_x; }
Length y() const { return m_y; }
@@ -81,11 +77,13 @@ public:
void setHeight(Length height) { m_height = height; }
void setCornerRadiusX(Length radiusX) { m_cornerRadiusX = radiusX; }
void setCornerRadiusY(Length radiusY) { m_cornerRadiusY = radiusY; }
-
+
+ virtual void path(Path&, const FloatRect&);
+
+ virtual Type type() const { return BASIC_SHAPE_RECTANGLE; }
private:
- WrapShapeRectangle()
- : WrapShape(WRAP_SHAPE_RECTANGLE)
- , m_cornerRadiusX(Undefined)
+ BasicShapeRectangle()
+ : m_cornerRadiusX(Undefined)
, m_cornerRadiusY(Undefined)
{ }
@@ -97,9 +95,9 @@ private:
Length m_cornerRadiusY;
};
-class WrapShapeCircle : public WrapShape {
+class BasicShapeCircle : public BasicShape {
public:
- static PassRefPtr<WrapShapeCircle> create() { return adoptRef(new WrapShapeCircle); }
+ static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); }
Length centerX() const { return m_centerX; }
Length centerY() const { return m_centerY; }
@@ -109,19 +107,20 @@ public:
void setCenterY(Length centerY) { m_centerY = centerY; }
void setRadius(Length radius) { m_radius = radius; }
+ virtual void path(Path&, const FloatRect&);
+
+ virtual Type type() const { return BASIC_SHAPE_CIRCLE; }
private:
- WrapShapeCircle()
- : WrapShape(WRAP_SHAPE_CIRCLE)
- { }
+ BasicShapeCircle() { }
Length m_centerX;
Length m_centerY;
Length m_radius;
};
-class WrapShapeEllipse : public WrapShape {
+class BasicShapeEllipse : public BasicShape {
public:
- static PassRefPtr<WrapShapeEllipse> create() { return adoptRef(new WrapShapeEllipse); }
+ static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); }
Length centerX() const { return m_centerX; }
Length centerY() const { return m_centerY; }
@@ -133,10 +132,11 @@ public:
void setRadiusX(Length radiusX) { m_radiusX = radiusX; }
void setRadiusY(Length radiusY) { m_radiusY = radiusY; }
+ virtual void path(Path&, const FloatRect&);
+
+ virtual Type type() const { return BASIC_SHAPE_ELLIPSE; }
private:
- WrapShapeEllipse()
- : WrapShape(WRAP_SHAPE_ELLIPSE)
- { }
+ BasicShapeEllipse() { }
Length m_centerX;
Length m_centerY;
@@ -144,11 +144,10 @@ private:
Length m_radiusY;
};
-class WrapShapePolygon : public WrapShape {
+class BasicShapePolygon : public BasicShape {
public:
- static PassRefPtr<WrapShapePolygon> create() { return adoptRef(new WrapShapePolygon); }
+ static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); }
- WindRule windRule() const { return m_windRule; }
const Vector<Length>& values() const { return m_values; }
Length getXAt(unsigned i) const { return m_values.at(2 * i); }
Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); }
@@ -156,10 +155,13 @@ public:
void setWindRule(WindRule windRule) { m_windRule = windRule; }
void appendPoint(Length x, Length y) { m_values.append(x); m_values.append(y); }
+ virtual void path(Path&, const FloatRect&);
+ virtual WindRule windRule() const { return m_windRule; }
+
+ virtual Type type() const { return BASIC_SHAPE_POLYGON; }
private:
- WrapShapePolygon()
- : WrapShape(WRAP_SHAPE_POLYGON)
- , m_windRule(RULE_NONZERO)
+ BasicShapePolygon()
+ : m_windRule(RULE_NONZERO)
{ }
WindRule m_windRule;
diff --git a/Source/WebCore/rendering/style/CounterDirectives.cpp b/Source/WebCore/rendering/style/CounterDirectives.cpp
index 34becba98..06d44ddf6 100644
--- a/Source/WebCore/rendering/style/CounterDirectives.cpp
+++ b/Source/WebCore/rendering/style/CounterDirectives.cpp
@@ -27,13 +27,10 @@ namespace WebCore {
bool operator==(const CounterDirectives& a, const CounterDirectives& b)
{
- if (a.m_reset != b.m_reset || a.m_increment != b.m_increment)
- return false;
- if (a.m_reset && a.m_resetValue != b.m_resetValue)
- return false;
- if (a.m_increment && a.m_incrementValue != b.m_incrementValue)
- return false;
- return true;
+ return a.isIncrement() == b.isIncrement()
+ && a.incrementValue() == b.incrementValue()
+ && a.isReset() == b.isReset()
+ && a.resetValue() == b.resetValue();
}
PassOwnPtr<CounterDirectiveMap> clone(const CounterDirectiveMap& counterDirectives)
diff --git a/Source/WebCore/rendering/style/CounterDirectives.h b/Source/WebCore/rendering/style/CounterDirectives.h
index 1bdcb9061..cf793bb8f 100644
--- a/Source/WebCore/rendering/style/CounterDirectives.h
+++ b/Source/WebCore/rendering/style/CounterDirectives.h
@@ -26,20 +26,75 @@
#define CounterDirectives_h
#include <wtf/HashMap.h>
+#include <wtf/MathExtras.h>
#include <wtf/RefPtr.h>
-#include <wtf/text/AtomicStringImpl.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
namespace WebCore {
-struct CounterDirectives {
+class CounterDirectives {
+public:
CounterDirectives()
- : m_reset(false)
- , m_increment(false)
+ : m_isResetSet(false)
+ , m_isIncrementSet(false)
+ , m_resetValue(0)
+ , m_incrementValue(0)
{
}
- bool m_reset;
- bool m_increment;
+ // FIXME: The code duplication here could possibly be replaced by using two
+ // maps, or by using a container that held two generic Directive objects.
+
+ bool isReset() const { return m_isResetSet; }
+ int resetValue() const { return m_resetValue; }
+ void setResetValue(int value)
+ {
+ m_resetValue = value;
+ m_isResetSet = true;
+ }
+ void clearReset()
+ {
+ m_resetValue = 0;
+ m_isResetSet = false;
+ }
+ void inheritReset(CounterDirectives& parent)
+ {
+ m_resetValue = parent.m_resetValue;
+ m_isResetSet = parent.m_isResetSet;
+ }
+
+ bool isIncrement() const { return m_isIncrementSet; }
+ int incrementValue() const { return m_incrementValue; }
+ void addIncrementValue(int value)
+ {
+ m_incrementValue = clampToInteger((double)m_incrementValue + value);
+ m_isIncrementSet = true;
+ }
+ void clearIncrement()
+ {
+ m_incrementValue = 0;
+ m_isIncrementSet = false;
+ }
+ void inheritIncrement(CounterDirectives& parent)
+ {
+ m_incrementValue = parent.m_incrementValue;
+ m_isIncrementSet = parent.m_isIncrementSet;
+ }
+
+ bool isDefined() const { return isReset() || isIncrement(); }
+
+ int combinedValue() const
+ {
+ ASSERT(m_isResetSet || !m_resetValue);
+ ASSERT(m_isIncrementSet || !m_incrementValue);
+ // FIXME: Shouldn't allow overflow here.
+ return m_resetValue + m_incrementValue;
+ }
+
+private:
+ bool m_isResetSet;
+ bool m_isIncrementSet;
int m_resetValue;
int m_incrementValue;
};
@@ -47,7 +102,7 @@ struct CounterDirectives {
bool operator==(const CounterDirectives&, const CounterDirectives&);
inline bool operator!=(const CounterDirectives& a, const CounterDirectives& b) { return !(a == b); }
-typedef HashMap<RefPtr<AtomicStringImpl>, CounterDirectives> CounterDirectiveMap;
+typedef HashMap<AtomicString, CounterDirectives> CounterDirectiveMap;
PassOwnPtr<CounterDirectiveMap> clone(const CounterDirectiveMap&);
diff --git a/Source/WebCore/rendering/style/DataRef.h b/Source/WebCore/rendering/style/DataRef.h
index c8d8072cb..91a78451d 100644
--- a/Source/WebCore/rendering/style/DataRef.h
+++ b/Source/WebCore/rendering/style/DataRef.h
@@ -62,6 +62,14 @@ public:
return m_data != o.m_data && *m_data != *o.m_data;
}
+ // Template helps us to write the implementation without MemoryInstrumentation.h include.
+ template<typename MemoryObjectInfo>
+ void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+ {
+ typename MemoryObjectInfo::ClassInfo info(memoryObjectInfo, this);
+ info.addInstrumentedMember(m_data);
+ }
+
private:
RefPtr<T> m_data;
};
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp
index b1b5faab0..f160d9ecc 100644
--- a/Source/WebCore/rendering/style/RenderStyle.cpp
+++ b/Source/WebCore/rendering/style/RenderStyle.cpp
@@ -28,7 +28,6 @@
#include "CSSPropertyNames.h"
#include "Font.h"
#include "FontSelector.h"
-#include "MemoryInstrumentation.h"
#include "QuotesData.h"
#include "RenderArena.h"
#include "RenderObject.h"
@@ -40,6 +39,7 @@
#if ENABLE(TOUCH_EVENTS)
#include "RenderTheme.h"
#endif
+#include "WebCoreMemoryInstrumentation.h"
#include <wtf/StdLibExtras.h>
#include <algorithm>
@@ -455,6 +455,11 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
return StyleDifferenceLayout;
#endif
+
+#if ENABLE(CSS_EXCLUSIONS)
+ if (rareNonInheritedData->m_wrapShapeInside != other->rareNonInheritedData->m_wrapShapeInside)
+ return StyleDifferenceLayout;
+#endif
}
if (rareInheritedData.get() != other->rareInheritedData.get()) {
@@ -463,7 +468,7 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
|| rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
|| rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
|| rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
- || rareInheritedData->wordWrap != other->rareInheritedData->wordWrap
+ || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
|| rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
|| rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak
|| rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
@@ -673,10 +678,13 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
// 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_wrapShapeInside != other->rareNonInheritedData->m_wrapShapeInside
- || rareNonInheritedData->m_wrapShapeOutside != other->rareNonInheritedData->m_wrapShapeOutside)
+ if (rareNonInheritedData->m_wrapShapeOutside != other->rareNonInheritedData->m_wrapShapeOutside)
+ return StyleDifferenceRepaint;
+
+ if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
return StyleDifferenceRepaint;
+
#if USE(ACCELERATED_COMPOSITING)
if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
@@ -774,9 +782,7 @@ void RenderStyle::setContent(const String& string, bool add)
// We attempt to merge with the last ContentData if possible.
if (lastContent->isText()) {
TextContentData* textContent = static_cast<TextContentData*>(lastContent);
- String text = textContent->text();
- text += string;
- textContent->setText(text);
+ textContent->setText(textContent->text() + string);
} else
lastContent->setNext(ContentData::create(string));
@@ -1030,6 +1036,13 @@ CounterDirectiveMap& RenderStyle::accessCounterDirectives()
return *map;
}
+const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
+{
+ if (const CounterDirectiveMap* directives = counterDirectives())
+ return directives->get(identifier);
+ return CounterDirectives();
+}
+
const AtomicString& RenderStyle::hyphenString() const
{
ASSERT(hyphens() != HyphensNone);
@@ -1329,40 +1342,40 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
EBorderStyle borderStyle = BNONE;
switch (colorProperty) {
case CSSPropertyBackgroundColor:
- return visitedLink ? rareNonInheritedData->m_visitedLinkBackgroundColor : backgroundColor(); // Background color doesn't fall back.
+ return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
case CSSPropertyBorderLeftColor:
- result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderLeftColor : borderLeftColor();
+ result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
borderStyle = borderLeftStyle();
break;
case CSSPropertyBorderRightColor:
- result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderRightColor : borderRightColor();
+ result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
borderStyle = borderRightStyle();
break;
case CSSPropertyBorderTopColor:
- result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderTopColor : borderTopColor();
+ result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
borderStyle = borderTopStyle();
break;
case CSSPropertyBorderBottomColor:
- result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderBottomColor : borderBottomColor();
+ result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
borderStyle = borderBottomStyle();
break;
case CSSPropertyColor:
- result = visitedLink ? inherited->visitedLinkColor : color();
+ result = visitedLink ? visitedLinkColor() : color();
break;
case CSSPropertyOutlineColor:
- result = visitedLink ? rareNonInheritedData->m_visitedLinkOutlineColor : outlineColor();
+ result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
break;
case CSSPropertyWebkitColumnRuleColor:
- result = visitedLink ? rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor : columnRuleColor();
+ result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
break;
case CSSPropertyWebkitTextEmphasisColor:
- result = visitedLink ? rareInheritedData->visitedLinkTextEmphasisColor : textEmphasisColor();
+ result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
break;
case CSSPropertyWebkitTextFillColor:
- result = visitedLink ? rareInheritedData->visitedLinkTextFillColor : textFillColor();
+ result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
break;
case CSSPropertyWebkitTextStrokeColor:
- result = visitedLink ? rareInheritedData->visitedLinkTextStrokeColor : textStrokeColor();
+ result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
break;
default:
ASSERT_NOT_REACHED();
@@ -1373,7 +1386,7 @@ Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) c
if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
result.setRGB(238, 238, 238);
else
- result = visitedLink ? inherited->visitedLinkColor : color();
+ result = visitedLink ? visitedLinkColor() : color();
}
return result;
}
@@ -1591,7 +1604,7 @@ LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
- MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS);
+ MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
info.addMember(m_box);
info.addMember(visual);
// FIXME: m_background contains RefPtr<StyleImage> that might need to be instrumented.
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 2378c7a72..c50785295 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -34,10 +34,10 @@
#include "ColorSpace.h"
#include "CounterDirectives.h"
#include "DataRef.h"
-#include "FillLayer.h"
#include "FontBaseline.h"
#include "FontDescription.h"
#include "GraphicsTypes.h"
+#include "LayoutTypesInlineMethods.h"
#include "Length.h"
#include "LengthBox.h"
#include "LengthFunctions.h"
@@ -74,7 +74,6 @@
#include <wtf/Vector.h>
#if ENABLE(CSS_FILTERS)
-#include "FilterOperations.h"
#include "StyleFilterData.h"
#endif
@@ -101,6 +100,10 @@ namespace WebCore {
using std::max;
+#if ENABLE(CSS_FILTERS)
+class FilterOperations;
+#endif
+
class BorderData;
class CounterContent;
class CursorList;
@@ -511,6 +514,7 @@ public:
EPosition position() const { return static_cast<EPosition>(noninherited_flags._position); }
bool hasOutOfFlowPosition() const { return position() == AbsolutePosition || position() == FixedPosition; }
bool hasInFlowPosition() const { return position() == RelativePosition || position() == StickyPosition; }
+ 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(); }
@@ -683,7 +687,7 @@ public:
bool breakWords() const
{
- return wordBreak() == BreakWordBreak || wordWrap() == BreakWordWrap;
+ return wordBreak() == BreakWordBreak || overflowWrap() == BreakOverflowWrap;
}
EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(m_background->background().repeatX()); }
@@ -838,7 +842,7 @@ public:
EMarginCollapse marginBeforeCollapse() const { return static_cast<EMarginCollapse>(rareNonInheritedData->marginBeforeCollapse); }
EMarginCollapse marginAfterCollapse() const { return static_cast<EMarginCollapse>(rareNonInheritedData->marginAfterCollapse); }
EWordBreak wordBreak() const { return static_cast<EWordBreak>(rareInheritedData->wordBreak); }
- EWordWrap wordWrap() const { return static_cast<EWordWrap>(rareInheritedData->wordWrap); }
+ EOverflowWrap overflowWrap() const { return static_cast<EOverflowWrap>(rareInheritedData->overflowWrap); }
ENBSPMode nbspMode() const { return static_cast<ENBSPMode>(rareInheritedData->nbspMode); }
EKHTMLLineBreak khtmlLineBreak() const { return static_cast<EKHTMLLineBreak>(rareInheritedData->khtmlLineBreak); }
const AtomicString& highlight() const { return rareInheritedData->highlight; }
@@ -988,7 +992,7 @@ public:
#if ENABLE(CSS_COMPOSITING)
BlendMode blendMode() const { return static_cast<BlendMode>(rareNonInheritedData->m_effectiveBlendMode); }
void setBlendMode(BlendMode v) { rareNonInheritedData.access()->m_effectiveBlendMode = v; }
- bool hasBlendMode() const { return static_cast<BlendMode>(rareNonInheritedData->m_effectiveBlendMode) == BlendModeNormal; }
+ bool hasBlendMode() const { return static_cast<BlendMode>(rareNonInheritedData->m_effectiveBlendMode) != BlendModeNormal; }
#else
bool hasBlendMode() const { return false; }
#endif
@@ -1301,7 +1305,7 @@ public:
void setMarginBeforeCollapse(EMarginCollapse c) { SET_VAR(rareNonInheritedData, marginBeforeCollapse, c); }
void setMarginAfterCollapse(EMarginCollapse c) { SET_VAR(rareNonInheritedData, marginAfterCollapse, c); }
void setWordBreak(EWordBreak b) { SET_VAR(rareInheritedData, wordBreak, b); }
- void setWordWrap(EWordWrap b) { SET_VAR(rareInheritedData, wordWrap, b); }
+ void setOverflowWrap(EOverflowWrap b) { SET_VAR(rareInheritedData, overflowWrap, b); }
void setNBSPMode(ENBSPMode b) { SET_VAR(rareInheritedData, nbspMode, b); }
void setKHTMLLineBreak(EKHTMLLineBreak b) { SET_VAR(rareInheritedData, khtmlLineBreak, b); }
void setHighlight(const AtomicString& h) { SET_VAR(rareInheritedData, highlight, h); }
@@ -1445,22 +1449,31 @@ public:
void setKerning(SVGLength k) { accessSVGStyle()->setKerning(k); }
#endif
- void setWrapShapeInside(PassRefPtr<WrapShape> shape)
+ void setWrapShapeInside(PassRefPtr<BasicShape> shape)
{
if (rareNonInheritedData->m_wrapShapeInside != shape)
rareNonInheritedData.access()->m_wrapShapeInside = shape;
}
- WrapShape* wrapShapeInside() const { return rareNonInheritedData->m_wrapShapeInside.get(); }
+ BasicShape* wrapShapeInside() const { return rareNonInheritedData->m_wrapShapeInside.get(); }
- void setWrapShapeOutside(PassRefPtr<WrapShape> shape)
+ void setWrapShapeOutside(PassRefPtr<BasicShape> shape)
{
if (rareNonInheritedData->m_wrapShapeOutside != shape)
rareNonInheritedData.access()->m_wrapShapeOutside = shape;
}
- WrapShape* wrapShapeOutside() const { return rareNonInheritedData->m_wrapShapeOutside.get(); }
+ BasicShape* wrapShapeOutside() const { return rareNonInheritedData->m_wrapShapeOutside.get(); }
+
+ static BasicShape* initialWrapShapeInside() { return 0; }
+ static BasicShape* initialWrapShapeOutside() { return 0; }
+
+ void setClipPath(PassRefPtr<BasicShape> shape)
+ {
+ if (rareNonInheritedData->m_clipPath != shape)
+ rareNonInheritedData.access()->m_clipPath = shape;
+ }
+ BasicShape* clipPath() const { return rareNonInheritedData->m_clipPath.get(); }
- static WrapShape* initialWrapShapeInside() { return 0; }
- static WrapShape* initialWrapShapeOutside() { return 0; }
+ static BasicShape* initialClipPath() { return 0; }
Length wrapPadding() const { return rareNonInheritedData->m_wrapPadding; }
void setWrapPadding(Length wrapPadding) { SET_VAR(rareNonInheritedData, m_wrapPadding, wrapPadding); }
@@ -1481,6 +1494,7 @@ public:
const CounterDirectiveMap* counterDirectives() const;
CounterDirectiveMap& accessCounterDirectives();
+ const CounterDirectives getCounterDirectives(const AtomicString& identifier) const;
QuotesData* quotes() const { return rareInheritedData->quotes.get(); }
void setQuotes(PassRefPtr<QuotesData>);
@@ -1630,7 +1644,7 @@ public:
static EMarginCollapse initialMarginBeforeCollapse() { return MCOLLAPSE; }
static EMarginCollapse initialMarginAfterCollapse() { return MCOLLAPSE; }
static EWordBreak initialWordBreak() { return NormalWordBreak; }
- static EWordWrap initialWordWrap() { return NormalWordWrap; }
+ static EOverflowWrap initialOverflowWrap() { return NormalOverflowWrap; }
static ENBSPMode initialNBSPMode() { return NBNORMAL; }
static EKHTMLLineBreak initialKHTMLLineBreak() { return LBNORMAL; }
static const AtomicString& initialHighlight() { return nullAtom; }
@@ -1754,10 +1768,7 @@ private:
bool isDisplayReplacedType(EDisplay display) const
{
- return display == INLINE_BLOCK || display == INLINE_BOX
-#if ENABLE(CSS3_FLEXBOX)
- || display == INLINE_FLEX
-#endif
+ return display == INLINE_BLOCK || display == INLINE_BOX || display == INLINE_FLEX
|| display == INLINE_TABLE || display == INLINE_GRID;
}
diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h
index 6d967cba3..3cdfd59d0 100644
--- a/Source/WebCore/rendering/style/RenderStyleConstants.h
+++ b/Source/WebCore/rendering/style/RenderStyleConstants.h
@@ -202,8 +202,8 @@ enum EWordBreak {
NormalWordBreak, BreakAllWordBreak, BreakWordBreak
};
-enum EWordWrap {
- NormalWordWrap, BreakWordWrap
+enum EOverflowWrap {
+ NormalOverflowWrap, BreakOverflowWrap
};
enum ENBSPMode {
@@ -415,9 +415,7 @@ enum EDisplay {
TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW,
TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL,
TABLE_CAPTION, BOX, INLINE_BOX,
-#if ENABLE(CSS3_FLEXBOX)
FLEX, INLINE_FLEX,
-#endif
GRID, INLINE_GRID,
NONE
};
diff --git a/Source/WebCore/rendering/style/ShadowData.cpp b/Source/WebCore/rendering/style/ShadowData.cpp
index f30d87f2b..d2a1cd270 100644
--- a/Source/WebCore/rendering/style/ShadowData.cpp
+++ b/Source/WebCore/rendering/style/ShadowData.cpp
@@ -22,6 +22,8 @@
#include "config.h"
#include "ShadowData.h"
+#include "LayoutTypesInlineMethods.h"
+
using namespace std;
namespace WebCore {
diff --git a/Source/WebCore/rendering/style/ShadowData.h b/Source/WebCore/rendering/style/ShadowData.h
index b8df95d88..1518edd93 100644
--- a/Source/WebCore/rendering/style/ShadowData.h
+++ b/Source/WebCore/rendering/style/ShadowData.h
@@ -26,6 +26,7 @@
#define ShadowData_h
#include "Color.h"
+#include "FloatRect.h"
#include "LayoutTypes.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
diff --git a/Source/WebCore/rendering/style/StyleDashboardRegion.h b/Source/WebCore/rendering/style/StyleDashboardRegion.h
index 552fdeb82..e591154e6 100644
--- a/Source/WebCore/rendering/style/StyleDashboardRegion.h
+++ b/Source/WebCore/rendering/style/StyleDashboardRegion.h
@@ -27,7 +27,7 @@
#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION)
#include "LengthBox.h"
-#include "PlatformString.h"
+#include <wtf/text/WTFString.h>
namespace WebCore {
diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
index 62fe5b89f..ea666d589 100644
--- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -23,11 +23,11 @@
#include "StyleRareInheritedData.h"
#include "CursorList.h"
-#include "MemoryInstrumentation.h"
#include "QuotesData.h"
#include "RenderStyle.h"
#include "RenderStyleConstants.h"
#include "ShadowData.h"
+#include "WebCoreMemoryInstrumentation.h"
namespace WebCore {
@@ -69,7 +69,7 @@ StyleRareInheritedData::StyleRareInheritedData()
, textSecurity(RenderStyle::initialTextSecurity())
, userModify(READ_ONLY)
, wordBreak(RenderStyle::initialWordBreak())
- , wordWrap(RenderStyle::initialWordWrap())
+ , overflowWrap(RenderStyle::initialOverflowWrap())
, nbspMode(NBNORMAL)
, khtmlLineBreak(LBNORMAL)
, textSizeAdjust(RenderStyle::initialTextSizeAdjust())
@@ -131,7 +131,7 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
, textSecurity(o.textSecurity)
, userModify(o.userModify)
, wordBreak(o.wordBreak)
- , wordWrap(o.wordWrap)
+ , overflowWrap(o.overflowWrap)
, nbspMode(o.nbspMode)
, khtmlLineBreak(o.khtmlLineBreak)
, textSizeAdjust(o.textSizeAdjust)
@@ -212,7 +212,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& textSecurity == o.textSecurity
&& userModify == o.userModify
&& wordBreak == o.wordBreak
- && wordWrap == o.wordWrap
+ && overflowWrap == o.overflowWrap
&& nbspMode == o.nbspMode
&& khtmlLineBreak == o.khtmlLineBreak
#if ENABLE(OVERFLOW_SCROLLING)
@@ -264,7 +264,7 @@ bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData&
void StyleRareInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
- MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS);
+ MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
info.addMember(textShadow);
info.addInstrumentedMember(highlight);
info.addMember(cursorData);
diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h
index 39e096ea4..60b4ff6d9 100644
--- a/Source/WebCore/rendering/style/StyleRareInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h
@@ -84,7 +84,7 @@ public:
unsigned textSecurity : 2; // ETextSecurity
unsigned userModify : 2; // EUserModify (editing)
unsigned wordBreak : 2; // EWordBreak
- unsigned wordWrap : 1; // EWordWrap
+ unsigned overflowWrap : 1; // EOverflowWrap
unsigned nbspMode : 1; // ENBSPMode
unsigned khtmlLineBreak : 1; // EKHTMLLineBreak
unsigned textSizeAdjust : 1; // An Apple extension.
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index 5b800d0ac..811bfa1fe 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -23,7 +23,6 @@
#include "StyleRareNonInheritedData.h"
#include "ContentData.h"
-#include "MemoryInstrumentation.h"
#include "RenderCounter.h"
#include "RenderStyle.h"
#include "ShadowData.h"
@@ -31,6 +30,7 @@
#include "StyleTransformData.h"
#include "StyleImage.h"
#include "StyleResolver.h"
+#include "WebCoreMemoryInstrumentation.h"
namespace WebCore {
@@ -48,6 +48,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, m_wrapShapeOutside(RenderStyle::initialWrapShapeOutside())
, m_wrapMargin(RenderStyle::initialWrapMargin())
, m_wrapPadding(RenderStyle::initialWrapPadding())
+ , m_clipPath(RenderStyle::initialClipPath())
, m_visitedLinkBackgroundColor(RenderStyle::initialBackgroundColor())
, m_order(RenderStyle::initialOrder())
, m_flowThread(RenderStyle::initialFlowThread())
@@ -118,6 +119,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_wrapShapeOutside(o.m_wrapShapeOutside)
, m_wrapMargin(o.m_wrapMargin)
, m_wrapPadding(o.m_wrapPadding)
+ , m_clipPath(o.m_clipPath)
, m_visitedLinkBackgroundColor(o.m_visitedLinkBackgroundColor)
, m_visitedLinkOutlineColor(o.m_visitedLinkOutlineColor)
, m_visitedLinkBorderLeftColor(o.m_visitedLinkBorderLeftColor)
@@ -199,6 +201,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_wrapShapeOutside == o.m_wrapShapeOutside
&& m_wrapMargin == o.m_wrapMargin
&& m_wrapPadding == o.m_wrapPadding
+ && m_clipPath == o.m_clipPath
&& m_visitedLinkBackgroundColor == o.m_visitedLinkBackgroundColor
&& m_visitedLinkOutlineColor == o.m_visitedLinkOutlineColor
&& m_visitedLinkBorderLeftColor == o.m_visitedLinkBorderLeftColor
@@ -301,7 +304,7 @@ bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInher
void StyleRareNonInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
- MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS);
+ MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
#if ENABLE(DASHBOARD_SUPPORT)
info.addVector(m_dashboardRegions);
#endif
@@ -323,6 +326,7 @@ void StyleRareNonInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObject
info.addMember(m_transitions);
info.addMember(m_wrapShapeInside);
info.addMember(m_wrapShapeOutside);
+ info.addMember(m_clipPath);
info.addInstrumentedMember(m_flowThread);
info.addInstrumentedMember(m_regionThread);
}
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
index e6f4a18be..251ffa319 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -25,13 +25,13 @@
#ifndef StyleRareNonInheritedData_h
#define StyleRareNonInheritedData_h
+#include "BasicShapes.h"
#include "CounterDirectives.h"
#include "CursorData.h"
#include "DataRef.h"
#include "FillLayer.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
-#include "WrapShapes.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
@@ -134,11 +134,13 @@ public:
LengthSize m_pageSize;
- RefPtr<WrapShape> m_wrapShapeInside;
- RefPtr<WrapShape> m_wrapShapeOutside;
+ RefPtr<BasicShape> m_wrapShapeInside;
+ RefPtr<BasicShape> m_wrapShapeOutside;
Length m_wrapMargin;
Length m_wrapPadding;
-
+
+ RefPtr<BasicShape> m_clipPath;
+
Color m_visitedLinkBackgroundColor;
Color m_visitedLinkOutlineColor;
Color m_visitedLinkBorderLeftColor;
diff --git a/Source/WebCore/rendering/style/WrapShapes.cpp b/Source/WebCore/rendering/style/WrapShapes.cpp
deleted file mode 100644
index 61a2c9fbf..000000000
--- a/Source/WebCore/rendering/style/WrapShapes.cpp
+++ /dev/null
@@ -1,55 +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 "WrapShapes.h"
-
-namespace WebCore {
-
-void WrapShape::destroy()
-{
- switch (m_type) {
- case WRAP_SHAPE_RECTANGLE:
- delete static_cast<WrapShapeRectangle*>(this);
- return;
- case WRAP_SHAPE_CIRCLE:
- delete static_cast<WrapShapeCircle*>(this);
- return;
- case WRAP_SHAPE_ELLIPSE:
- delete static_cast<WrapShapeEllipse*>(this);
- return;
- case WRAP_SHAPE_POLYGON:
- delete static_cast<WrapShapePolygon*>(this);
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
-}
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
index 8f842ee21..acc0c6d36 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
@@ -178,13 +178,13 @@ bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, Hit
return false;
// FOs establish a stacking context, so we need to hit-test all layers.
- HitTestPoint hitTestPoint(roundedLayoutPoint(localPoint));
- return RenderBlock::nodeAtPoint(request, result, hitTestPoint, LayoutPoint(), HitTestForeground)
- || RenderBlock::nodeAtPoint(request, result, hitTestPoint, LayoutPoint(), HitTestFloat)
- || RenderBlock::nodeAtPoint(request, result, hitTestPoint, LayoutPoint(), HitTestChildBlockBackgrounds);
+ HitTestLocation hitTestLocation(roundedLayoutPoint(localPoint));
+ return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestForeground)
+ || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestFloat)
+ || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds);
}
-bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint&, const LayoutPoint&, HitTestAction)
+bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
{
ASSERT_NOT_REACHED();
return false;
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
index 7e52e00c2..0d65d5741 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
@@ -51,7 +51,7 @@ public:
virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(FloatPoint(), m_viewport.size()); }
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual bool isSVGForeignObject() const { return true; }
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip | SnapOffsetForTransforms, bool* wasFixed = 0) const OVERRIDE;
@@ -59,8 +59,8 @@ public:
virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
private:
- virtual void computeLogicalWidth();
- virtual void computeLogicalHeight();
+ virtual void computeLogicalWidth() OVERRIDE;
+ virtual void computeLogicalHeight() OVERRIDE;
virtual const AffineTransform& localToParentTransform() const;
virtual AffineTransform localTransform() const { return m_localTransform; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
index 082bf487e..d44a93da4 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
@@ -111,7 +111,7 @@ void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyl
SVGResourcesCache::clientStyleChanged(this, diff, style());
}
-bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint&, const LayoutPoint&, HitTestAction)
+bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
{
ASSERT_NOT_REACHED();
return false;
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
index a28376625..a99dd9da7 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
@@ -71,7 +71,7 @@ protected:
private:
// This method should never be called, SVG uses a different nodeAtPoint method
- bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
};
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h
index faa225892..26fbc6f93 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h
@@ -22,7 +22,6 @@
#if ENABLE(SVG)
#include "FloatRect.h"
-#include "RenderObject.h"
#include "RenderSVGResourceContainer.h"
#include "SVGMarkerElement.h"
#include "SVGStyledElement.h"
@@ -32,6 +31,7 @@
namespace WebCore {
class AffineTransform;
+class RenderObject;
class RenderSVGResourceMarker : public RenderSVGResourceContainer {
public:
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
index 5d56b5ce7..f7115d926 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
@@ -415,9 +415,9 @@ void RenderSVGRoot::updateCachedBoundaries()
m_repaintBoundingBox.inflate(borderAndPaddingWidth());
}
-bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- LayoutPoint pointInParent = pointInContainer.point() - toLayoutSize(accumulatedOffset);
+ LayoutPoint pointInParent = locationInContainer.point() - toLayoutSize(accumulatedOffset);
LayoutPoint pointInBorderBox = pointInParent - toLayoutSize(location());
// Only test SVG content if the point is in our content box.
@@ -429,7 +429,7 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
// FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet.
if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
updateHitTestResult(result, pointInBorderBox);
- if (!result.addNodeToRectBasedTestResult(child->node(), pointInContainer))
+ if (!result.addNodeToRectBasedTestResult(child->node(), request, locationInContainer))
return true;
}
}
@@ -442,9 +442,9 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
// 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 (pointInContainer.intersects(boundsRect)) {
+ if (locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, pointInBorderBox);
- if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
+ if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
return true;
}
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h
index a0566b134..cddd311fd 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h
@@ -90,7 +90,7 @@ private:
virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; }
virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const;
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp
index de2f0165c..2945fe48b 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp
@@ -451,15 +451,15 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul
if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
return false;
- HitTestPoint hitTestPoint(LayoutPoint(flooredIntPoint(localPoint)));
- return RenderBlock::nodeAtPoint(request, result, hitTestPoint, LayoutPoint(), hitTestAction);
+ HitTestLocation hitTestLocation(LayoutPoint(flooredIntPoint(localPoint)));
+ return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), hitTestAction);
}
}
return false;
}
-bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint&, const LayoutPoint&, HitTestAction)
+bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
{
ASSERT_NOT_REACHED();
return false;
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 0a0c2856b..cd2e38f79 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -62,7 +62,7 @@ private:
virtual bool isSVGText() const { return true; }
virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ 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 VisiblePosition positionForPoint(const LayoutPoint&);
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
index 47bb63de2..7864d4ee8 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
@@ -701,7 +701,7 @@ FloatRect SVGInlineTextBox::calculateBoundaries() const
return textRect;
}
-bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit)
+bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit)
{
// FIXME: integrate with InlineTextBox::nodeAtPoint better.
ASSERT(!isLineBreak());
@@ -714,9 +714,9 @@ bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult&
FloatPoint boxOrigin(x(), y());
boxOrigin.moveBy(accumulatedOffset);
FloatRect rect(boxOrigin, size());
- if (pointInContainer.intersects(rect)) {
- renderer()->updateHitTestResult(result, pointInContainer.point() - toLayoutSize(accumulatedOffset));
- if (!result.addNodeToRectBasedTestResult(renderer()->node(), pointInContainer, rect))
+ if (locationInContainer.intersects(rect)) {
+ renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+ if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
return true;
}
}
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.h b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
index a4e03d828..ef399c724 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.h
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
@@ -79,7 +79,7 @@ private:
void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition);
void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
private:
float m_logicalHeight;
diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
index e2adb3063..6e3cd2dcb 100644
--- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
@@ -27,6 +27,7 @@
#if ENABLE(SVG)
#include "SVGRenderingContext.h"
+#include "BasicShapes.h"
#include "Frame.h"
#include "FrameView.h"
#include "RenderSVGResource.h"
@@ -122,6 +123,15 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
}
}
+ BasicShape* clipShape = style->clipPath();
+ if (clipShape) {
+ // FIXME: Investigate if it is better to store and update a Path object in RenderStyle.
+ // https://bugs.webkit.org/show_bug.cgi?id=95619
+ Path clipPath;
+ clipShape->path(clipPath, object->objectBoundingBox());
+ m_paintInfo->context->clipPath(clipPath, clipShape->windRule());
+ }
+
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(m_object);
if (!resources) {
#if ENABLE(FILTERS)
@@ -139,7 +149,8 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
}
}
- if (RenderSVGResourceClipper* clipper = resources->clipper()) {
+ RenderSVGResourceClipper* clipper = resources->clipper();
+ if (!clipShape && clipper) {
if (!clipper->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
return;
}
@@ -205,14 +216,10 @@ bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const A
GraphicsContext* imageContext = image->context();
ASSERT(imageContext);
- // This is done in absolute coordinates.
- imageContext->translate(-paintRect.x(), -paintRect.y());
-
- imageContext->concatCTM(absoluteTransform);
-
- // This happens in local coordinates.
imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
static_cast<float>(clampedSize.height()) / paintRect.height()));
+ imageContext->translate(-paintRect.x(), -paintRect.y());
+ imageContext->concatCTM(absoluteTransform);
imageBuffer = image.release();
return true;
diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.h b/Source/WebCore/rendering/svg/SVGRenderingContext.h
index 5d38ce495..c88168968 100644
--- a/Source/WebCore/rendering/svg/SVGRenderingContext.h
+++ b/Source/WebCore/rendering/svg/SVGRenderingContext.h
@@ -27,7 +27,6 @@
#if ENABLE(SVG)
#include "ImageBuffer.h"
-#include "LayoutTypes.h"
#include "PaintInfo.h"
namespace WebCore {
diff --git a/Source/WebCore/rendering/svg/SVGTextMetrics.cpp b/Source/WebCore/rendering/svg/SVGTextMetrics.cpp
index d6cbe4c50..99bfbd4d3 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetrics.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextMetrics.cpp
@@ -56,7 +56,7 @@ SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun&
m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor;
m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;
- m_glyph.unicodeString = String(run.characters(), length);
+ m_glyph.unicodeString = run.is8Bit() ? String(run.characters8(), length) : String(run.characters16(), length);
m_glyph.isValid = true;
ASSERT(length >= 0);
diff --git a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
index 5ac85cbbe..ff9ca3073 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
@@ -30,7 +30,7 @@ namespace WebCore {
SVGTextMetricsBuilder::SVGTextMetricsBuilder()
: m_text(0)
- , m_run(0, 0)
+ , m_run(static_cast<const UChar*>(0), 0)
, m_textPosition(0)
, m_isComplexText(false)
, m_totalWidth(0)
@@ -148,7 +148,7 @@ void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, Measu
int surrogatePairCharacters = 0;
while (advance()) {
- const UChar* currentCharacter = m_run.data(m_textPosition);
+ const UChar* currentCharacter = m_run.data16(m_textPosition);
if (*currentCharacter == ' ' && !preserveWhiteSpace && (!data->lastCharacter || *data->lastCharacter == ' ')) {
if (data->processRenderer)
textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));