summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-22 09:09:45 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-22 09:10:13 +0100
commit470286ecfe79d59df14944e5b5d34630fc739391 (patch)
tree43983212872e06cebefd2ae474418fa2908ca54c /Source/WebCore/rendering
parent23037105e948c2065da5a937d3a2396b0ff45c1e (diff)
downloadqtwebkit-470286ecfe79d59df14944e5b5d34630fc739391.tar.gz
Imported WebKit commit e89504fa9195b2063b2530961d4b73dd08de3242 (http://svn.webkit.org/repository/webkit/trunk@135485)
Change-Id: I03774e5ac79721c13ffa30d152537a74d0b12e66 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'Source/WebCore/rendering')
-rw-r--r--Source/WebCore/rendering/ExclusionPolygon.cpp28
-rw-r--r--Source/WebCore/rendering/ExclusionPolygon.h4
-rw-r--r--Source/WebCore/rendering/ExclusionShape.cpp3
-rw-r--r--Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp7
-rw-r--r--Source/WebCore/rendering/FilterEffectRenderer.cpp8
-rw-r--r--Source/WebCore/rendering/FixedTableLayout.cpp2
-rw-r--r--Source/WebCore/rendering/HitTestResult.cpp18
-rw-r--r--Source/WebCore/rendering/HitTestResult.h25
-rw-r--r--Source/WebCore/rendering/LayoutState.h2
-rw-r--r--Source/WebCore/rendering/RenderBlock.cpp4
-rw-r--r--Source/WebCore/rendering/RenderBlock.h3
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp80
-rw-r--r--Source/WebCore/rendering/RenderBox.h6
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.cpp77
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h17
-rw-r--r--Source/WebCore/rendering/RenderEmbeddedObject.h4
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp17
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.h2
-rw-r--r--Source/WebCore/rendering/RenderFlowThread.cpp8
-rw-r--r--Source/WebCore/rendering/RenderGeometryMap.cpp160
-rw-r--r--Source/WebCore/rendering/RenderGeometryMap.h26
-rw-r--r--Source/WebCore/rendering/RenderGrid.cpp34
-rw-r--r--Source/WebCore/rendering/RenderGrid.h1
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp2
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp786
-rw-r--r--Source/WebCore/rendering/RenderLayer.h139
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp41
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.h2
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp24
-rw-r--r--Source/WebCore/rendering/RenderLayerFilterInfo.cpp2
-rw-r--r--Source/WebCore/rendering/RenderMediaControls.cpp4
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.cpp2
-rw-r--r--Source/WebCore/rendering/RenderObject.cpp10
-rw-r--r--Source/WebCore/rendering/RenderObject.h2
-rw-r--r--Source/WebCore/rendering/RenderRegion.cpp1
-rw-r--r--Source/WebCore/rendering/RenderReplica.cpp12
-rw-r--r--Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp66
-rw-r--r--Source/WebCore/rendering/RenderSnapshottedPlugIn.h7
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTextControlMultiLine.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTextControlSingleLine.cpp4
-rw-r--r--Source/WebCore/rendering/RenderTheme.h3
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumCommon.cpp12
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumDefault.cpp389
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumDefault.h109
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumFontProvider.cpp55
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumFontProvider.h50
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumFontProviderLinux.cpp69
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumFontProviderWin.cpp192
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.h4
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.mm6
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.cpp42
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.h200
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumWin.cpp140
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumWin.h6
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.h186
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.mm1868
-rw-r--r--Source/WebCore/rendering/RenderThemeMacShared.h227
-rw-r--r--Source/WebCore/rendering/RenderThemeMacShared.mm1835
-rw-r--r--Source/WebCore/rendering/RenderThemeWin.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTreeAsText.cpp2
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp1
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLBlock.h10
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp13
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFenced.h6
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFraction.h1
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp5
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLOperator.h7
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRoot.h1
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h1
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSubSup.h2
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h1
-rw-r--r--Source/WebCore/rendering/style/BasicShapes.cpp79
-rw-r--r--Source/WebCore/rendering/style/BasicShapes.h16
-rw-r--r--Source/WebCore/rendering/style/ExclusionShapeValue.h69
-rw-r--r--Source/WebCore/rendering/style/GridPosition.h79
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.cpp4
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.h50
-rw-r--r--Source/WebCore/rendering/style/RenderStyleConstants.h6
-rw-r--r--Source/WebCore/rendering/style/StyleGridItemData.h9
-rw-r--r--Source/WebCore/rendering/style/StyleRareInheritedData.cpp9
-rw-r--r--Source/WebCore/rendering/style/StyleRareInheritedData.h3
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp12
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.h9
-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/SVGRenderSupport.cpp10
87 files changed, 4482 insertions, 2966 deletions
diff --git a/Source/WebCore/rendering/ExclusionPolygon.cpp b/Source/WebCore/rendering/ExclusionPolygon.cpp
index efb6acddb..21beac1ec 100644
--- a/Source/WebCore/rendering/ExclusionPolygon.cpp
+++ b/Source/WebCore/rendering/ExclusionPolygon.cpp
@@ -190,13 +190,13 @@ static inline bool getVertexIntersectionVertices(const EdgeIntersection& interse
if ((intersection.type == VertexMinY && (thisEdge.vertex1().y() < thisEdge.vertex2().y()))
|| (intersection.type == VertexMaxY && (thisEdge.vertex1().y() > thisEdge.vertex2().y()))) {
- prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex2);
+ prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex1);
thisVertex = polygon.vertexAt(thisEdge.vertexIndex1);
nextVertex = polygon.vertexAt(thisEdge.vertexIndex2);
} else {
prevVertex = polygon.vertexAt(thisEdge.vertexIndex1);
thisVertex = polygon.vertexAt(thisEdge.vertexIndex2);
- nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex1);
+ nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex2);
}
return true;
@@ -219,7 +219,7 @@ static bool compareEdgeIntersectionX(const EdgeIntersection& intersection1, cons
return (x1 == x2) ? intersection1.type < intersection2.type : x1 < x2;
}
-void ExclusionPolygon::computeXIntersections(float y, Vector<ExclusionInterval>& result) const
+void ExclusionPolygon::computeXIntersections(float y, bool isMinY, Vector<ExclusionInterval>& result) const
{
Vector<ExclusionPolygon::EdgeInterval> overlappingEdges;
m_edgeTree.allOverlaps(ExclusionPolygon::EdgeInterval(y, y, 0), overlappingEdges);
@@ -265,19 +265,19 @@ void ExclusionPolygon::computeXIntersections(float y, Vector<ExclusionInterval>&
}
if (evenOddCrossing) {
- bool edgeCrossing = false;
- if (thisIntersection.type == Normal || !inside || index == intersections.size() - 1)
- edgeCrossing = true;
- else {
+ bool edgeCrossing = thisIntersection.type == Normal;
+ if (!edgeCrossing) {
FloatPoint prevVertex;
FloatPoint thisVertex;
FloatPoint nextVertex;
if (getVertexIntersectionVertices(thisIntersection, prevVertex, thisVertex, nextVertex)) {
- if (prevVertex.y() == y)
- edgeCrossing = (thisVertex.x() > prevVertex.x()) ? nextVertex.y() > y : nextVertex.y() < y;
+ if (nextVertex.y() == y)
+ edgeCrossing = (isMinY) ? prevVertex.y() > y : prevVertex.y() < y;
+ else if (prevVertex.y() == y)
+ edgeCrossing = (isMinY) ? nextVertex.y() > y : nextVertex.y() < y;
else
- edgeCrossing = (nextVertex.y() != y);
+ edgeCrossing = true;
}
}
if (edgeCrossing)
@@ -331,8 +331,8 @@ void ExclusionPolygon::getExcludedIntervals(float logicalTop, float logicalHeigh
float y2 = maxYForLogicalLine(logicalTop, logicalHeight);
Vector<ExclusionInterval> y1XIntervals, y2XIntervals;
- computeXIntersections(y1, y1XIntervals);
- computeXIntersections(y2, y2XIntervals);
+ computeXIntersections(y1, true, y1XIntervals);
+ computeXIntersections(y2, false, y2XIntervals);
Vector<ExclusionInterval> mergedIntervals;
mergeExclusionIntervals(y1XIntervals, y2XIntervals, mergedIntervals);
@@ -358,8 +358,8 @@ void ExclusionPolygon::getIncludedIntervals(float logicalTop, float logicalHeigh
float y2 = maxYForLogicalLine(logicalTop, logicalHeight);
Vector<ExclusionInterval> y1XIntervals, y2XIntervals;
- computeXIntersections(y1, y1XIntervals);
- computeXIntersections(y2, y2XIntervals);
+ computeXIntersections(y1, true, y1XIntervals);
+ computeXIntersections(y2, false, y2XIntervals);
Vector<ExclusionInterval> commonIntervals;
intersectExclusionIntervals(y1XIntervals, y2XIntervals, commonIntervals);
diff --git a/Source/WebCore/rendering/ExclusionPolygon.h b/Source/WebCore/rendering/ExclusionPolygon.h
index ce7a23c0d..647eb172e 100644
--- a/Source/WebCore/rendering/ExclusionPolygon.h
+++ b/Source/WebCore/rendering/ExclusionPolygon.h
@@ -68,7 +68,7 @@ public:
virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
private:
- void computeXIntersections(float y, Vector<ExclusionInterval>&) const;
+ void computeXIntersections(float y, bool isMinY, Vector<ExclusionInterval>&) const;
void computeEdgeIntersections(float minY, float maxY, Vector<ExclusionInterval>&) const;
unsigned findNextEdgeVertexIndex(unsigned vertexIndex1, bool clockwise) const;
@@ -102,7 +102,7 @@ struct ExclusionPolygonEdge {
const ExclusionPolygonEdge& previousEdge() const
{
ASSERT(polygon && polygon->numberOfEdges() > 1);
- return polygon->edgeAt((edgeIndex + polygon->numberOfEdges() - 2) % polygon->numberOfEdges());
+ return polygon->edgeAt((edgeIndex + polygon->numberOfEdges() - 1) % polygon->numberOfEdges());
}
const ExclusionPolygonEdge& nextEdge() const
diff --git a/Source/WebCore/rendering/ExclusionShape.cpp b/Source/WebCore/rendering/ExclusionShape.cpp
index f5d85b2ec..5e0ea8bf1 100644
--- a/Source/WebCore/rendering/ExclusionShape.cpp
+++ b/Source/WebCore/rendering/ExclusionShape.cpp
@@ -70,8 +70,7 @@ static PassOwnPtr<ExclusionShape> createExclusionPolygon(PassOwnPtr<Vector<Float
PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode)
{
- if (!basicShape)
- return nullptr;
+ ASSERT(basicShape);
bool horizontalWritingMode = isHorizontalWritingMode(writingMode);
float boxWidth = horizontalWritingMode ? logicalBoxWidth : logicalBoxHeight;
diff --git a/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp b/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp
index b7830f10e..934e3f299 100644
--- a/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp
+++ b/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp
@@ -72,7 +72,8 @@ ExclusionShapeInsideInfo* ExclusionShapeInsideInfo::exclusionShapeInsideInfoForR
bool ExclusionShapeInsideInfo::isExclusionShapeInsideInfoEnabledForRenderBlock(const RenderBlock* block)
{
// FIXME: Bug 89707: Enable shape inside for non-rectangular shapes
- BasicShape* shape = block->style()->shapeInside();
+ ExclusionShapeValue* shapeValue = block->style()->shapeInside();
+ BasicShape* shape = (shapeValue && shapeValue->type() == ExclusionShapeValue::SHAPE) ? shapeValue->shape() : 0;
return shape && (shape->type() == BasicShape::BASIC_SHAPE_RECTANGLE || shape->type() == BasicShape::BASIC_SHAPE_POLYGON);
}
@@ -93,7 +94,9 @@ void ExclusionShapeInsideInfo::computeShapeSize(LayoutUnit logicalWidth, LayoutU
m_logicalHeight = logicalHeight;
// FIXME: Bug 89993: The wrap shape may come from the parent object
- BasicShape* shape = m_block->style()->shapeInside();
+ ExclusionShapeValue* shapeValue = m_block->style()->shapeInside();
+ BasicShape* shape = (shapeValue && shapeValue->type() == ExclusionShapeValue::SHAPE) ? shapeValue->shape() : 0;
+
ASSERT(shape);
m_shape = ExclusionShape::createExclusionShape(shape, logicalWidth, logicalHeight, m_block->style()->writingMode());
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.cpp b/Source/WebCore/rendering/FilterEffectRenderer.cpp
index 772bcdb33..e53d338be 100644
--- a/Source/WebCore/rendering/FilterEffectRenderer.cpp
+++ b/Source/WebCore/rendering/FilterEffectRenderer.cpp
@@ -122,10 +122,10 @@ GraphicsContext* FilterEffectRenderer::inputContext()
return sourceImage() ? sourceImage()->context() : 0;
}
-PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(Document* document, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* op)
+PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(Document* document, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation)
{
#if ENABLE(SVG)
- CachedSVGDocumentReference* cachedSVGDocumentReference = static_cast<CachedSVGDocumentReference*>(op->data());
+ CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference();
CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0;
// If we have an SVG document, this is an external reference. Otherwise
@@ -136,7 +136,7 @@ PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(Document* do
if (!document)
return 0;
- Element* filter = document->getElementById(op->fragment());
+ Element* filter = document->getElementById(filterOperation->fragment());
if (!filter)
return 0;
@@ -171,7 +171,7 @@ PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(Document* do
#else
UNUSED_PARAM(document);
UNUSED_PARAM(previousEffect);
- UNUSED_PARAM(op);
+ UNUSED_PARAM(filterOperation);
return 0;
#endif
}
diff --git a/Source/WebCore/rendering/FixedTableLayout.cpp b/Source/WebCore/rendering/FixedTableLayout.cpp
index 2a08ad6b5..e75764ac7 100644
--- a/Source/WebCore/rendering/FixedTableLayout.cpp
+++ b/Source/WebCore/rendering/FixedTableLayout.cpp
@@ -199,7 +199,7 @@ void FixedTableLayout::computePreferredLogicalWidths(LayoutUnit& minWidth, Layou
// In this example, the two inner tables should be as large as the outer table.
// We can achieve this effect by making the maxwidth of fixed tables with percentage
// widths be infinite.
- if (m_table->document()->inQuirksMode() && m_table->style()->logicalWidth().isPercent() && maxWidth < tableMaxWidth)
+ if (m_table->style()->logicalWidth().isPercent() && maxWidth < tableMaxWidth)
maxWidth = tableMaxWidth;
}
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp
index cc390568c..8553d6f5d 100644
--- a/Source/WebCore/rendering/HitTestResult.cpp
+++ b/Source/WebCore/rendering/HitTestResult.cpp
@@ -197,19 +197,23 @@ HitTestResult::HitTestResult() : HitTestLocation()
{
}
-HitTestResult::HitTestResult(const LayoutPoint& point) : HitTestLocation(point)
+HitTestResult::HitTestResult(const LayoutPoint& point)
+ : HitTestLocation(point)
+ , m_pointInMainFrame(point)
, m_isOverWidget(false)
{
}
HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
: HitTestLocation(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding)
+ , m_pointInMainFrame(centerPoint)
, m_isOverWidget(false)
{
}
HitTestResult::HitTestResult(const HitTestLocation& other)
: HitTestLocation(other)
+ , m_pointInMainFrame(point())
, m_isOverWidget(false)
{
}
@@ -218,6 +222,7 @@ HitTestResult::HitTestResult(const HitTestResult& other)
: HitTestLocation(other)
, m_innerNode(other.innerNode())
, m_innerNonSharedNode(other.innerNonSharedNode())
+ , m_pointInMainFrame(other.m_pointInMainFrame)
, m_localPoint(other.localPoint())
, m_innerURLElement(other.URLElement())
, m_scrollbar(other.scrollbar())
@@ -236,6 +241,7 @@ HitTestResult& HitTestResult::operator=(const HitTestResult& other)
HitTestLocation::operator=(other);
m_innerNode = other.innerNode();
m_innerNonSharedNode = other.innerNonSharedNode();
+ m_pointInMainFrame = other.m_pointInMainFrame;
m_localPoint = other.localPoint();
m_innerURLElement = other.URLElement();
m_scrollbar = other.scrollbar();
@@ -279,6 +285,15 @@ void HitTestResult::setScrollbar(Scrollbar* s)
m_scrollbar = s;
}
+Frame* HitTestResult::innerNodeFrame() const
+{
+ if (m_innerNonSharedNode)
+ return m_innerNonSharedNode->document()->frame();
+ if (m_innerNode)
+ return m_innerNode->document()->frame();
+ return 0;
+}
+
Frame* HitTestResult::targetFrame() const
{
if (!m_innerURLElement)
@@ -746,6 +761,7 @@ void HitTestResult::append(const HitTestResult& other)
m_innerNode = other.innerNode();
m_innerNonSharedNode = other.innerNonSharedNode();
m_localPoint = other.localPoint();
+ m_pointInMainFrame = other.m_pointInMainFrame;
m_innerURLElement = other.URLElement();
m_scrollbar = other.scrollbar();
m_isOverWidget = other.isOverWidget();
diff --git a/Source/WebCore/rendering/HitTestResult.h b/Source/WebCore/rendering/HitTestResult.h
index 7b3c19e5c..b219a97dc 100644
--- a/Source/WebCore/rendering/HitTestResult.h
+++ b/Source/WebCore/rendering/HitTestResult.h
@@ -60,7 +60,7 @@ public:
~HitTestLocation();
HitTestLocation& operator=(const HitTestLocation&);
- LayoutPoint point() const { return m_point; }
+ const LayoutPoint& point() const { return m_point; }
IntPoint roundedPoint() const { return roundedIntPoint(m_point); }
RenderRegion* region() const { return m_region; }
@@ -100,7 +100,8 @@ private:
bool m_isRectilinear;
};
-class HitTestResult : public HitTestLocation {
+// FIXME: HitTestResult should not be a HitTestLocation, but instead have a HitTestLocation. See https://bugs.webkit.org/show_bug.cgi?id=101590
+class HitTestResult : protected HitTestLocation {
public:
typedef ListHashSet<RefPtr<Node> > NodeSet;
@@ -115,18 +116,33 @@ public:
Node* innerNode() const { return m_innerNode.get(); }
Node* innerNonSharedNode() const { return m_innerNonSharedNode.get(); }
- LayoutPoint localPoint() const { return m_localPoint; }
Element* URLElement() const { return m_innerURLElement.get(); }
Scrollbar* scrollbar() const { return m_scrollbar.get(); }
bool isOverWidget() const { return m_isOverWidget; }
+ // Forwarded from HitTestLocation
+ bool isRectBasedTest() const { return HitTestLocation::isRectBasedTest(); }
+
+ // The hit-tested point in the coordinates of the main frame.
+ const LayoutPoint& pointInMainFrame() const { return m_pointInMainFrame; }
+ IntPoint roundedPointInMainFrame() const { return roundedIntPoint(pointInMainFrame()); }
+ void setPointInMainFrame(const LayoutPoint& p) { m_pointInMainFrame = p; }
+
+ // The hit-tested point in the coordinates of the innerNode frame, the frame containing innerNode.
+ const LayoutPoint& pointInInnerNodeFrame() const { return HitTestLocation::point(); }
+ IntPoint roundedPointInInnerNodeFrame() const { return roundedIntPoint(pointInInnerNodeFrame()); }
+ Frame* innerNodeFrame() const;
+
+ // The hit-tested point in the coordinates of the inner node.
+ const LayoutPoint& localPoint() const { return m_localPoint; }
+ void setLocalPoint(const LayoutPoint& p) { m_localPoint = p; }
+
void setToNonShadowAncestor();
const HitTestLocation& hitTestLocation() const { return *this; }
void setInnerNode(Node*);
void setInnerNonSharedNode(Node*);
- void setLocalPoint(const LayoutPoint& p) { m_localPoint = p; }
void setURLElement(Element*);
void setScrollbar(Scrollbar*);
void setIsOverWidget(bool b) { m_isOverWidget = b; }
@@ -185,6 +201,7 @@ private:
RefPtr<Node> m_innerNode;
RefPtr<Node> m_innerNonSharedNode;
+ LayoutPoint m_pointInMainFrame; // The hit-tested point in main-frame coordinates.
LayoutPoint m_localPoint; // A point in the local coordinate space of m_innerNonSharedNode's renderer. Allows us to efficiently
// determine where inside the renderer we hit on subsequent operations.
RefPtr<Element> m_innerURLElement;
diff --git a/Source/WebCore/rendering/LayoutState.h b/Source/WebCore/rendering/LayoutState.h
index 16e01005f..38571f91d 100644
--- a/Source/WebCore/rendering/LayoutState.h
+++ b/Source/WebCore/rendering/LayoutState.h
@@ -129,6 +129,8 @@ public:
ExclusionShapeInsideInfo* m_exclusionShapeInsideInfo;
#endif
+ // FIXME: Distinguish between the layout clip rect and the paint clip rect which may be larger,
+ // e.g., because of composited scrolling.
LayoutRect m_clipRect;
// x/y offset from container. Includes relative positioning and scroll offsets.
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 982b09519..84f7b3c61 100644
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -1398,7 +1398,7 @@ void RenderBlock::layout()
}
#if ENABLE(CSS_EXCLUSIONS)
-void RenderBlock::updateExclusionShapeInsideInfoAfterStyleChange(const BasicShape* shapeInside, const BasicShape* oldShapeInside)
+void RenderBlock::updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue* shapeInside, const ExclusionShapeValue* oldShapeInside)
{
// FIXME: A future optimization would do a deep comparison for equality.
if (shapeInside == oldShapeInside)
@@ -2758,7 +2758,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
// FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
// paints the root's background.
if (!isRoot()) {
- LayoutRect overflowBox = visualOverflowRect();
+ LayoutRect overflowBox = overflowRectForPaintRejection();
flipForWritingMode(overflowBox);
overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
overflowBox.moveBy(adjustedPaintOffset);
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index 55a001f61..a5566ed77 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -36,6 +36,7 @@
#if ENABLE(CSS_EXCLUSIONS)
#include "ExclusionShapeInsideInfo.h"
+#include "ExclusionShapeValue.h"
#endif
namespace WebCore {
@@ -521,7 +522,7 @@ protected:
private:
#if ENABLE(CSS_EXCLUSIONS)
void computeExclusionShapeSize();
- void updateExclusionShapeInsideInfoAfterStyleChange(const BasicShape*, const BasicShape* oldWrapShape);
+ void updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue*, const ExclusionShapeValue* oldExclusionShape);
#endif
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index f2fb378f8..654d5ff83 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -448,16 +448,16 @@ FloatQuad RenderBox::absoluteContentQuad() const
return localToAbsoluteQuad(FloatRect(rect));
}
-LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, LayoutPoint* cachedOffsetToRepaintContainer) const
+LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const
{
LayoutRect box = borderBoundingBox();
adjustRectForOutlineAndShadow(box);
- FloatQuad containerRelativeQuad = FloatRect(box);
- if (cachedOffsetToRepaintContainer)
- containerRelativeQuad.move(cachedOffsetToRepaintContainer->x(), cachedOffsetToRepaintContainer->y());
+ FloatQuad containerRelativeQuad;
+ if (geometryMap)
+ containerRelativeQuad = geometryMap->mapToContainer(box, repaintContainer);
else
- containerRelativeQuad = localToContainerQuad(containerRelativeQuad, repaintContainer);
+ containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
box = containerRelativeQuad.enclosingBoundingBox();
@@ -617,6 +617,11 @@ bool RenderBox::canBeProgramaticallyScrolled() const
return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->rendererIsEditable()))) || (node() && node()->isDocumentNode());
}
+bool RenderBox::usesCompositedScrolling() const
+{
+ return hasOverflowClip() && hasLayer() && layer()->usesCompositedScrolling();
+}
+
void RenderBox::autoscroll()
{
if (layer())
@@ -652,6 +657,10 @@ void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect)
{
paintRect.move(-scrolledContentOffset()); // For overflow:auto/scroll/hidden.
+ // Do not clip scroll layer contents to reduce the number of repaints while scrolling.
+ if (usesCompositedScrolling())
+ return;
+
// height() is inaccurate if we're in the middle of a layout of this RenderBox, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
@@ -821,11 +830,8 @@ BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsCo
FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
if (borderObscuresBackgroundEdge(contextScaling))
return BackgroundBleedShrinkBackground;
-
- // FIXME: there is one more strategy possible, for opaque backgrounds and
- // translucent borders. In that case we could avoid using a transparency layer,
- // and paint the border first, and then paint the background clipped to the
- // inside of the border.
+ if (!style->hasAppearance() && borderObscuresBackground() && backgroundIsSingleOpaqueLayer())
+ return BackgroundBleedBackgroundOverBorder;
return BackgroundBleedUseTransparencyLayer;
}
@@ -859,12 +865,15 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
paintInfo.context->addRoundedRectClip(border);
paintInfo.context->beginTransparencyLayer(1);
}
-
+
// If we have a native theme appearance, paint that before painting our background.
// The theme will tell us whether or not we should also paint the CSS background.
IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, snappedPaintRect);
if (!themePainted) {
+ if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
+ paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
+
paintBackground(paintInfo, paintRect, bleedAvoidance);
if (style()->hasAppearance())
@@ -873,7 +882,7 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
paintBoxShadow(paintInfo, paintRect, style(), Inset);
// The theme will tell us whether or not we should also paint the CSS border.
- if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder())
+ if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder())
paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
@@ -894,6 +903,25 @@ void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& pa
}
}
+bool RenderBox::backgroundIsSingleOpaqueLayer() const
+{
+ const FillLayer* fillLayer = style()->backgroundLayers();
+ if (!fillLayer || fillLayer->next() || fillLayer->clip() != BorderFillBox || fillLayer->composite() != CompositeSourceOver)
+ return false;
+
+ // Clipped with local scrolling
+ if (hasOverflowClip() && fillLayer->attachment() == LocalBackgroundAttachment)
+ return false;
+
+ Color bgColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+ if (bgColor.isValid() && bgColor.alpha() == 255)
+ return true;
+
+ // FIXME: return true if a background image is present and is opaque
+
+ return false;
+}
+
void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask || paintInfo.context->paintingDisabled())
@@ -1355,6 +1383,8 @@ const RenderObject* RenderBox::pushMappingToContainer(const RenderLayerModelObje
bool offsetDependsOnPoint = false;
LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+ if (geometryMap.mapCoordinatesFlags() & SnapOffsetForTransforms)
+ containerOffset = roundedIntSize(containerOffset);
if (container->isRenderFlowThread())
offsetDependsOnPoint = true;
@@ -1566,7 +1596,7 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
// We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box
// in the parent's coordinate space that encloses us.
- if (layer() && layer()->transform()) {
+ if (hasLayer() && layer()->transform()) {
fixed = position == FixedPosition;
rect = layer()->transform()->mapRect(pixelSnappedIntRect(rect));
topLeft = rect.location();
@@ -1584,14 +1614,11 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
topLeft += layer()->offsetForInFlowPosition();
}
- if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) {
- RenderBlock* cb = toRenderBlock(o);
- if (cb->hasColumns()) {
- LayoutRect repaintRect(topLeft, rect.size());
- cb->adjustRectForColumns(repaintRect);
- topLeft = repaintRect.location();
- rect = repaintRect;
- }
+ if (position != AbsolutePosition && position != FixedPosition && o->hasColumns() && o->isBlockFlow()) {
+ LayoutRect repaintRect(topLeft, rect.size());
+ toRenderBlock(o)->adjustRectForColumns(repaintRect);
+ topLeft = repaintRect.location();
+ rect = repaintRect;
}
// FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
@@ -3928,6 +3955,17 @@ LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle)
return rect;
}
+LayoutRect RenderBox::overflowRectForPaintRejection() const
+{
+ LayoutRect overflowRect = visualOverflowRect();
+ if (!m_overflow || !usesCompositedScrolling())
+ return overflowRect;
+
+ overflowRect.unite(layoutOverflowRect());
+ overflowRect.move(-scrolledContentOffset());
+ return overflowRect;
+}
+
LayoutUnit RenderBox::offsetLeft() const
{
return adjustedPositionRelativeToOffsetParent(topLeftLocation()).x();
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index e5d1c8306..156b72921 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -154,7 +154,7 @@ public:
LayoutRect computedCSSContentBoxRect() const { return LayoutRect(borderLeft() + computedCSSPaddingLeft(), borderTop() + computedCSSPaddingTop(), clientWidth() - computedCSSPaddingLeft() - computedCSSPaddingRight(), clientHeight() - computedCSSPaddingTop() - computedCSSPaddingBottom()); }
// Bounds of the outline box in absolute coords. Respects transforms
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, LayoutPoint* cachedOffsetToRepaintContainer) const OVERRIDE;
+ virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap*) const OVERRIDE;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&);
// Use this with caution! No type checking is done!
@@ -175,6 +175,8 @@ public:
virtual LayoutRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : borderBoxRect(); }
LayoutUnit logicalLeftVisualOverflow() const { return style()->isHorizontalWritingMode() ? visualOverflowRect().x() : visualOverflowRect().y(); }
LayoutUnit logicalRightVisualOverflow() const { return style()->isHorizontalWritingMode() ? visualOverflowRect().maxX() : visualOverflowRect().maxY(); }
+
+ LayoutRect overflowRectForPaintRejection() const;
void addLayoutOverflow(const LayoutRect&);
void addVisualOverflow(const LayoutRect&);
@@ -433,6 +435,7 @@ public:
bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || hasAutoHorizontalScrollbar()); }
bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || hasAutoVerticalScrollbar()); }
+ bool usesCompositedScrolling() const;
bool hasUnsplittableScrollingOverflow() const;
bool isUnsplittableForPagination() const;
@@ -567,6 +570,7 @@ protected:
void paintMaskImages(const PaintInfo&, const LayoutRect&);
BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
+ bool backgroundIsSingleOpaqueLayer() const;
#if PLATFORM(MAC)
void paintCustomHighlight(const LayoutPoint&, const AtomicString& type, bool behindText);
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index 1277a7c7f..f9a994f4d 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "RenderBoxModelObject.h"
-#include "FilterOperations.h"
#include "GraphicsContext.h"
#include "HTMLFrameOwnerElement.h"
#include "HTMLNames.h"
@@ -647,7 +646,7 @@ LayoutUnit RenderBoxModelObject::computedCSSPaddingEnd() const
}
RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, InlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
- bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
RenderView* renderView = view();
RoundedRect border = style()->getRoundedBorderFor(borderRect, renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
@@ -691,17 +690,31 @@ void RenderBoxModelObject::clipRoundedInnerRect(GraphicsContext * context, const
}
}
-static LayoutRect backgroundRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance)
+static LayoutRect shrinkRectByOnePixel(GraphicsContext* context, const LayoutRect& rect)
{
- if (bleedAvoidance != BackgroundBleedShrinkBackground)
- return borderRect;
-
- // We shrink the rectangle by one pixel on each side because the bleed is one pixel maximum.
+ LayoutRect shrunkRect = rect;
AffineTransform transform = context->getCTM();
- LayoutRect adjustedRect = borderRect;
- adjustedRect.inflateX(-static_cast<LayoutUnit>(ceil(1 / transform.xScale())));
- adjustedRect.inflateY(-static_cast<LayoutUnit>(ceil(1 / transform.yScale())));
- return adjustedRect;
+ shrunkRect.inflateX(-static_cast<LayoutUnit>(ceil(1 / transform.xScale())));
+ shrunkRect.inflateY(-static_cast<LayoutUnit>(ceil(1 / transform.yScale())));
+ return shrunkRect;
+}
+
+LayoutRect RenderBoxModelObject::borderInnerRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& rect, BackgroundBleedAvoidance bleedAvoidance) const
+{
+ // We shrink the rectangle by one pixel on each side to make it fully overlap the anti-aliased background border
+ return (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? shrinkRectByOnePixel(context, rect) : rect;
+}
+
+RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+ if (bleedAvoidance == BackgroundBleedShrinkBackground) {
+ // We shrink the rectangle by one pixel on each side because the bleed is one pixel maximum.
+ return getBackgroundRoundedRect(shrinkRectByOnePixel(context, borderRect), box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
+ }
+ if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
+ return style()->getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+
+ return getBackgroundRoundedRect(borderRect, box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
}
static void applyBoxShadowForBackground(GraphicsContext* context, RenderStyle* style)
@@ -773,7 +786,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
applyBoxShadowForBackground(context, style());
if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
- RoundedRect border = getBackgroundRoundedRect(backgroundRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance), box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
+ RoundedRect border = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge);
context->fillRoundedRect(border, bgColor, style()->colorSpace());
} else
context->fillRect(pixelSnappedIntRect(rect), bgColor, style()->colorSpace());
@@ -785,8 +798,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidance == BackgroundBleedUseTransparencyLayer);
GraphicsContextStateSaver clipToBorderStateSaver(*context, clipToBorderRadius);
if (clipToBorderRadius) {
- LayoutRect adjustedRect = isBorderFill ? backgroundRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance) : rect;
- RoundedRect border = getBackgroundRoundedRect(adjustedRect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
+ RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
// Clip to the padding or content boxes as necessary.
if (bgLayer->clip() == ContentFillBox) {
@@ -1729,8 +1741,8 @@ static IntRect calculateSideRect(const RoundedRect& outerBorder, const BorderEdg
}
void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
- const BorderEdge edges[], BorderEdgeFlags edgeSet, BackgroundBleedAvoidance bleedAvoidance,
- bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+ const IntPoint& innerBorderAdjustment, const BorderEdge edges[], BorderEdgeFlags edgeSet, BackgroundBleedAvoidance bleedAvoidance,
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
{
bool renderRadii = outerBorder.isRounded();
@@ -1738,9 +1750,14 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
if (renderRadii)
roundedPath.addRoundedRect(outerBorder);
+ // The inner border adjustment for bleed avoidance mode BackgroundBleedBackgroundOverBorder
+ // is only applied to sideRect, which is okay since BackgroundBleedBackgroundOverBorder
+ // is only to be used for solid borders and the shape of the border painted by drawBoxSideFromPath
+ // only depends on sideRect when painting solid borders.
+
if (edges[BSTop].shouldRender() && includesEdge(edgeSet, BSTop)) {
IntRect sideRect = outerBorder.rect();
- sideRect.setHeight(edges[BSTop].width);
+ sideRect.setHeight(edges[BSTop].width + innerBorderAdjustment.y());
bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].style) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorder.radii().topRight()));
paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
@@ -1748,7 +1765,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) {
IntRect sideRect = outerBorder.rect();
- sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width);
+ sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width - innerBorderAdjustment.y());
bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().bottomRight()));
paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
@@ -1756,7 +1773,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) {
IntRect sideRect = outerBorder.rect();
- sideRect.setWidth(edges[BSLeft].width);
+ sideRect.setWidth(edges[BSLeft].width + innerBorderAdjustment.x());
bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().topLeft()));
paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
@@ -1764,17 +1781,16 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) {
IntRect sideRect = outerBorder.rect();
- sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width);
+ sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width - innerBorderAdjustment.x());
bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight].style) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), innerBorder.radii().topRight()));
paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
}
}
-void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
- const BorderEdge edges[], BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
+void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment,
+ const BorderEdge edges[], BorderEdgeFlags edgesToDraw, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
{
- BorderEdgeFlags edgesToDraw = AllBorderEdges;
while (edgesToDraw) {
// Find undrawn edges sharing a color.
Color commonColor;
@@ -1802,7 +1818,7 @@ void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphics
commonColor = Color(commonColor.red(), commonColor.green(), commonColor.blue());
}
- paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, commonColorEdgeSet, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor);
+ paintBorderSides(graphicsContext, style, outerBorder, innerBorder, innerBorderAdjustment, edges, commonColorEdgeSet, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor);
if (useTransparencyLayer)
graphicsContext->endTransparencyLayer();
@@ -1825,7 +1841,7 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
BorderEdge edges[4];
getBorderEdgeInfo(edges, style, includeLogicalLeftEdge, includeLogicalRightEdge);
RoundedRect outerBorder = style->getRoundedBorderFor(rect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
- RoundedRect innerBorder = style->getRoundedInnerBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedRect innerBorder = style->getRoundedInnerBorderFor(borderInnerRectAdjustedForBleedAvoidance(graphicsContext, rect, bleedAvoidance), includeLogicalLeftEdge, includeLogicalRightEdge);
bool haveAlphaColor = false;
bool haveAllSolidEdges = true;
@@ -1833,9 +1849,14 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
int numEdgesVisible = 4;
bool allEdgesShareColor = true;
int firstVisibleEdge = -1;
+ BorderEdgeFlags edgesToDraw = 0;
for (int i = BSTop; i <= BSLeft; ++i) {
const BorderEdge& currEdge = edges[i];
+
+ if (edges[i].shouldRender())
+ edgesToDraw |= edgeFlagForSide(static_cast<BoxSide>(i));
+
if (currEdge.presentButInvisible()) {
--numEdgesVisible;
allEdgesShareColor = false;
@@ -1961,10 +1982,12 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
// If only one edge visible antialiasing doesn't create seams
bool antialias = shouldAntialiasLines(graphicsContext) || numEdgesVisible == 1;
+ RoundedRect unadjustedInnerBorder = (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? style->getRoundedInnerBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge) : innerBorder;
+ IntPoint innerBorderAdjustment(innerBorder.rect().x() - unadjustedInnerBorder.rect().x(), innerBorder.rect().y() - unadjustedInnerBorder.rect().y());
if (haveAlphaColor)
- paintTranslucentBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+ paintTranslucentBorderSides(graphicsContext, style, outerBorder, unadjustedInnerBorder, innerBorderAdjustment, edges, edgesToDraw, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
else
- paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+ paintBorderSides(graphicsContext, style, outerBorder, unadjustedInnerBorder, innerBorderAdjustment, edges, edgesToDraw, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
}
void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, const LayoutRect& borderRect, const Path& borderPath, const BorderEdge edges[],
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index 1cfe4123e..eea0d6893 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -38,7 +38,8 @@ typedef unsigned BorderEdgeFlags;
enum BackgroundBleedAvoidance {
BackgroundBleedNone,
BackgroundBleedShrinkBackground,
- BackgroundBleedUseTransparencyLayer
+ BackgroundBleedUseTransparencyLayer,
+ BackgroundBleedBackgroundOverBorder
};
enum ContentChangeType {
@@ -151,7 +152,7 @@ public:
bool paintNinePieceImage(GraphicsContext*, const LayoutRect&, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
-
+
virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox* = 0) const;
// Overridden by subclasses to determine line height and baseline position.
@@ -233,6 +234,8 @@ protected:
void getBorderEdgeInfo(class BorderEdge[], const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
bool borderObscuresBackground() const;
+ RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox*, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+ LayoutRect borderInnerRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance) const;
bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const LayoutSize&);
@@ -285,7 +288,7 @@ private:
IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
- bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
void clipBorderSidePolygon(GraphicsContext*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
@@ -294,11 +297,11 @@ private:
void paintOneBorderSide(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
const IntRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[],
const Path*, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0);
- void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
- const class BorderEdge[], BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
+ void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment,
+ const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
void paintBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
- const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance,
- bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
+ const IntPoint& innerBorderAdjustment, const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance,
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
void drawBoxSideFromPath(GraphicsContext*, const LayoutRect&, const Path&, const class BorderEdge[],
float thickness, float drawThickness, BoxSide, const RenderStyle*,
Color, EBorderStyle, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.h b/Source/WebCore/rendering/RenderEmbeddedObject.h
index 133f34d92..ef09ebb4d 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.h
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.h
@@ -68,6 +68,9 @@ protected:
RenderObjectChildList* children() { return &m_children; }
#endif
+protected:
+ virtual void layout() OVERRIDE;
+
private:
virtual const char* renderName() const { return "RenderEmbeddedObject"; }
virtual bool isEmbeddedObject() const { return true; }
@@ -76,7 +79,6 @@ private:
virtual bool requiresLayer() const;
#endif
- virtual void layout();
virtual void viewCleared();
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 2e08a5cdf..e11d865f1 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -132,7 +132,7 @@ struct RenderFlexibleBox::Violation {
RenderFlexibleBox::RenderFlexibleBox(Node* node)
: RenderBlock(node)
- , m_numberOfChildrenOnFirstLine(0)
+ , m_numberOfInFlowChildrenOnFirstLine(-1)
{
setChildrenInline(false); // All of our children must be block-level.
}
@@ -254,11 +254,11 @@ int RenderFlexibleBox::firstLineBoxBaseline() const
{
ASSERT(m_orderIterator);
- if (isWritingModeRoot() || !m_numberOfChildrenOnFirstLine)
+ if (isWritingModeRoot() || m_numberOfInFlowChildrenOnFirstLine <= 0)
return -1;
RenderBox* baselineChild = 0;
- RenderBox* child = m_orderIterator->first();
- for (size_t childNumber = 0; childNumber < m_numberOfChildrenOnFirstLine; ++childNumber, child = m_orderIterator->next()) {
+ int childNumber = 0;
+ for (RenderBox* child = m_orderIterator->first(); child; child = m_orderIterator->next()) {
if (child->isOutOfFlowPositioned())
continue;
if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child)) {
@@ -267,6 +267,10 @@ int RenderFlexibleBox::firstLineBoxBaseline() const
}
if (!baselineChild)
baselineChild = child;
+
+ ++childNumber;
+ if (childNumber == m_numberOfInFlowChildrenOnFirstLine)
+ break;
}
if (!baselineChild)
@@ -320,6 +324,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
setLogicalHeight(0);
updateLogicalWidth();
+ m_numberOfInFlowChildrenOnFirstLine = -1;
m_overflow.clear();
RenderBlock::startDelayUpdateScrollInfo();
@@ -386,8 +391,6 @@ void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(OrderIterator&
flipForWrapReverse(iterator, lineContexts, crossAxisStartEdge);
}
- m_numberOfChildrenOnFirstLine = lineContexts.isEmpty() ? 0 : lineContexts[0].numberOfChildren;
-
// direction:rtl + flex-direction:column means the cross-axis direction is flipped.
flipForRightToLeftColumn(iterator);
}
@@ -1132,6 +1135,8 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons
layoutColumnReverse(children, crossAxisOffset, availableFreeSpace);
}
+ if (m_numberOfInFlowChildrenOnFirstLine == -1)
+ m_numberOfInFlowChildrenOnFirstLine = seenInFlowPositionedChildren;
lineContexts.append(LineContext(crossAxisOffset, maxChildCrossAxisExtent, children.size(), maxAscent));
crossAxisOffset += maxChildCrossAxisExtent;
}
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h
index acbdba928..98eafca7c 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.h
+++ b/Source/WebCore/rendering/RenderFlexibleBox.h
@@ -146,7 +146,7 @@ private:
void flipForWrapReverse(OrderIterator&, const WTF::Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
OwnPtr<OrderIterator> m_orderIterator;
- size_t m_numberOfChildrenOnFirstLine;
+ int m_numberOfInFlowChildrenOnFirstLine;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp
index ce182cd06..13809b00d 100644
--- a/Source/WebCore/rendering/RenderFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderFlowThread.cpp
@@ -856,7 +856,7 @@ bool RenderFlowThread::addForcedRegionBreak(LayoutUnit offsetBreakInFlowThread,
RenderRegionList::iterator regionIter = m_regionList.find(region);
ASSERT(regionIter != m_regionList.end());
- for (; (regionIter != m_regionList.end()) && (currentRegionOffsetInFlowThread < offsetBreakInFlowThread); ++regionIter) {
+ for (; regionIter != m_regionList.end(); ++regionIter) {
RenderRegion* region = *regionIter;
if (region->needsOverrideLogicalContentHeightComputation()) {
mapToUse.set(breakChild, region);
@@ -871,6 +871,12 @@ bool RenderFlowThread::addForcedRegionBreak(LayoutUnit offsetBreakInFlowThread,
currentRegionOffsetInFlowThread += regionOverrideLogicalContentHeight;
} else
currentRegionOffsetInFlowThread += isHorizontalWritingMode() ? region->flowThreadPortionRect().height() : region->flowThreadPortionRect().width();
+
+ // If the current offset if greater than the break offset, bail out and skip the current region.
+ if (currentRegionOffsetInFlowThread >= offsetBreakInFlowThread) {
+ ++regionIter;
+ break;
+ }
}
// The remaining auto logical height regions in the chain that were unable to receive content
diff --git a/Source/WebCore/rendering/RenderGeometryMap.cpp b/Source/WebCore/rendering/RenderGeometryMap.cpp
index 5a6a69d9d..74434895f 100644
--- a/Source/WebCore/rendering/RenderGeometryMap.cpp
+++ b/Source/WebCore/rendering/RenderGeometryMap.cpp
@@ -33,11 +33,12 @@
namespace WebCore {
-RenderGeometryMap::RenderGeometryMap()
+RenderGeometryMap::RenderGeometryMap(MapCoordinatesFlags flags)
: m_insertionPosition(notFound)
, m_nonUniformStepsCount(0)
, m_transformedStepsCount(0)
, m_fixedStepsCount(0)
+ , m_mapCoordinatesFlags(flags)
{
}
@@ -45,62 +46,30 @@ RenderGeometryMap::~RenderGeometryMap()
{
}
-FloatPoint RenderGeometryMap::absolutePoint(const FloatPoint& p) const
-{
- FloatPoint result;
-
- if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep())
- result = p + m_accumulatedOffset;
- else {
- TransformState transformState(TransformState::ApplyTransformDirection, p);
- mapToAbsolute(transformState);
- result = transformState.lastPlanarPoint();
- }
-
-#if !ASSERT_DISABLED
- FloatPoint rendererMappedResult = m_mapping.last().m_renderer->localToAbsolute(p, UseTransforms | SnapOffsetForTransforms);
- ASSERT(rendererMappedResult == result);
-#endif
-
- return result;
-}
-
-FloatRect RenderGeometryMap::absoluteRect(const FloatRect& rect) const
-{
- FloatRect result;
-
- if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep()) {
- result = rect;
- result.move(m_accumulatedOffset);
- } else {
- TransformState transformState(TransformState::ApplyTransformDirection, rect.center(), rect);
- mapToAbsolute(transformState);
- result = transformState.lastPlanarQuad().boundingBox();
- }
-
-#if !ASSERT_DISABLED
- FloatRect rendererMappedResult = m_mapping.last().m_renderer->localToAbsoluteQuad(rect).boundingBox();
- // Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>.
- // Taking FloatQuad bounds avoids spurious assertions because of that.
- ASSERT(enclosingIntRect(rendererMappedResult) == enclosingIntRect(FloatQuad(result).boundingBox()));
-#endif
-
- return result;
-}
-
-void RenderGeometryMap::mapToAbsolute(TransformState& transformState) const
+void RenderGeometryMap::mapToContainer(TransformState& transformState, const RenderLayerModelObject* container) const
{
// If the mapping includes something like columns, we have to go via renderers.
if (hasNonUniformStep()) {
- m_mapping.last().m_renderer->mapLocalToContainer(0, transformState, UseTransforms | ApplyContainerFlip | SnapOffsetForTransforms);
+ m_mapping.last().m_renderer->mapLocalToContainer(container, transformState, ApplyContainerFlip | m_mapCoordinatesFlags);
return;
}
bool inFixed = false;
+#if !ASSERT_DISABLED
+ bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_renderer == container);
+#endif
for (int i = m_mapping.size() - 1; i >= 0; --i) {
const RenderGeometryMapStep& currentStep = m_mapping[i];
+ // If container is the RenderView (step 0) we want to apply its scroll offset.
+ if (i > 0 && currentStep.m_renderer == container) {
+#if !ASSERT_DISABLED
+ foundContainer = true;
+#endif
+ break;
+ }
+
// If this box has a transform, it acts as a fixed position container
// for fixed descendants, which prevents the propagation of 'fixed'
// unless the layer itself is also fixed position.
@@ -110,7 +79,8 @@ void RenderGeometryMap::mapToAbsolute(TransformState& transformState) const
inFixed = true;
if (!i) {
- if (currentStep.m_transform)
+ // A null container indicates mapping through the RenderView, so including its transform (the page scale).
+ if (!container && currentStep.m_transform)
transformState.applyTransform(*currentStep.m_transform.get());
// The root gets special treatment for fixed position
@@ -125,9 +95,57 @@ void RenderGeometryMap::mapToAbsolute(TransformState& transformState) const
}
}
+ ASSERT(foundContainer);
transformState.flatten();
}
+FloatPoint RenderGeometryMap::mapToContainer(const FloatPoint& p, const RenderLayerModelObject* container) const
+{
+ FloatPoint result;
+
+ if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() && (!container || (m_mapping.size() && container == m_mapping[0].m_renderer)))
+ result = p + m_accumulatedOffset;
+ else {
+ TransformState transformState(TransformState::ApplyTransformDirection, p);
+ mapToContainer(transformState, container);
+ result = transformState.lastPlanarPoint();
+ }
+
+#if !ASSERT_DISABLED
+ FloatPoint rendererMappedResult = m_mapping.last().m_renderer->localToAbsolute(p, m_mapCoordinatesFlags);
+ ASSERT(roundedIntPoint(rendererMappedResult) == roundedIntPoint(result));
+// if (roundedIntPoint(rendererMappedResult) != roundedIntPoint(result))
+// fprintf(stderr, "Mismatched point\n");
+#endif
+
+ return result;
+}
+
+FloatQuad RenderGeometryMap::mapToContainer(const FloatRect& rect, const RenderLayerModelObject* container) const
+{
+ FloatRect result;
+
+ if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() && (!container || (m_mapping.size() && container == m_mapping[0].m_renderer))) {
+ result = rect;
+ result.move(m_accumulatedOffset);
+ } else {
+ TransformState transformState(TransformState::ApplyTransformDirection, rect.center(), rect);
+ mapToContainer(transformState, container);
+ result = transformState.lastPlanarQuad().boundingBox();
+ }
+
+#if !ASSERT_DISABLED
+ FloatRect rendererMappedResult = m_mapping.last().m_renderer->localToContainerQuad(rect, container, m_mapCoordinatesFlags).boundingBox();
+ // Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>.
+ // Taking FloatQuad bounds avoids spurious assertions because of that.
+ ASSERT(enclosingIntRect(rendererMappedResult) == enclosingIntRect(FloatQuad(result).boundingBox()));
+// if (enclosingIntRect(rendererMappedResult) != enclosingIntRect(FloatQuad(result).boundingBox()))
+// fprintf(stderr, "Mismatched rects\n");
+#endif
+
+ return result;
+}
+
void RenderGeometryMap::pushMappingsToAncestor(const RenderObject* renderer, const RenderLayerModelObject* ancestorRenderer)
{
// We need to push mappings in reverse order here, so do insertions rather than appends.
@@ -139,19 +157,23 @@ void RenderGeometryMap::pushMappingsToAncestor(const RenderObject* renderer, con
ASSERT(m_mapping.isEmpty() || m_mapping[0].m_renderer->isRenderView());
}
-static bool canMapViaLayer(const RenderLayer* layer)
+static bool canMapBetweenRenderers(const RenderObject* renderer, const RenderObject* ancestor)
{
- RenderStyle* style = layer->renderer()->style();
- if (style->position() == FixedPosition || style->isFlippedBlocksWritingMode())
- return false;
-
- if (layer->renderer()->hasColumns() || layer->renderer()->hasTransform())
- return false;
-
-#if ENABLE(SVG)
- if (layer->renderer()->isSVGRoot())
- return false;
-#endif
+ for (const RenderObject* current = renderer; ; current = current->parent()) {
+ const RenderStyle* style = current->style();
+ if (style->position() == FixedPosition || style->isFlippedBlocksWritingMode())
+ return false;
+
+ if (current->hasColumns() || current->hasTransform() || current->isRenderFlowThread())
+ return false;
+
+ #if ENABLE(SVG)
+ if (current->isSVGRoot())
+ return false;
+ #endif
+ if (current == ancestor)
+ break;
+ }
return true;
}
@@ -160,15 +182,23 @@ void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const R
{
const RenderObject* renderer = layer->renderer();
- // The simple case can be handled fast in the layer tree.
- bool canConvertInLayerTree = ancestorLayer ? canMapViaLayer(ancestorLayer) : false;
- for (const RenderLayer* current = layer; current != ancestorLayer && canConvertInLayerTree; current = current->parent())
- canConvertInLayerTree = canMapViaLayer(current);
+ // We have to visit all the renderers to detect flipped blocks. This might defeat the gains
+ // from mapping via layers.
+ bool canConvertInLayerTree = ancestorLayer ? canMapBetweenRenderers(layer->renderer(), ancestorLayer->renderer()) : false;
+
+// fprintf(stderr, "RenderGeometryMap::pushMappingsToAncestor from layer %p to layer %p, canConvertInLayerTree=%d\n", layer, ancestorLayer, canConvertInLayerTree);
if (canConvertInLayerTree) {
- TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
LayoutPoint layerOffset;
layer->convertToLayerCoords(ancestorLayer, layerOffset);
+
+ // The RenderView must be pushed first.
+ if (!m_mapping.size()) {
+ ASSERT(ancestorLayer->renderer()->isRenderView());
+ pushMappingsToAncestor(ancestorLayer->renderer(), 0);
+ }
+
+ TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
push(renderer, toLayoutSize(layerOffset), /*accumulatingTransform*/ true, /*isNonUniform*/ false, /*isFixedPosition*/ false, /*hasTransform*/ false);
return;
}
@@ -178,6 +208,8 @@ void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const R
void RenderGeometryMap::push(const RenderObject* renderer, const LayoutSize& offsetFromContainer, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
{
+// fprintf(stderr, "RenderGeometryMap::push %p %d,%d isNonUniform=%d\n", renderer, offsetFromContainer.width().toInt(), offsetFromContainer.height().toInt(), isNonUniform);
+
ASSERT(m_insertionPosition != notFound);
m_mapping.insert(m_insertionPosition, RenderGeometryMapStep(renderer, accumulatingTransform, isNonUniform, isFixedPosition, hasTransform));
diff --git a/Source/WebCore/rendering/RenderGeometryMap.h b/Source/WebCore/rendering/RenderGeometryMap.h
index 15dc884d3..bab106f1d 100644
--- a/Source/WebCore/rendering/RenderGeometryMap.h
+++ b/Source/WebCore/rendering/RenderGeometryMap.h
@@ -30,6 +30,7 @@
#include "FloatQuad.h"
#include "IntSize.h"
#include "LayoutSize.h"
+#include "RenderObject.h"
#include "TransformationMatrix.h"
#include <wtf/OwnPtr.h>
@@ -37,7 +38,6 @@ namespace WebCore {
class RenderLayer;
class RenderLayerModelObject;
-class RenderObject;
class RenderView;
class TransformState;
@@ -74,11 +74,26 @@ struct RenderGeometryMapStep {
class RenderGeometryMap {
WTF_MAKE_NONCOPYABLE(RenderGeometryMap);
public:
- RenderGeometryMap();
+ RenderGeometryMap(MapCoordinatesFlags = UseTransforms | SnapOffsetForTransforms);
~RenderGeometryMap();
- FloatPoint absolutePoint(const FloatPoint&) const;
- FloatRect absoluteRect(const FloatRect&) const;
+ MapCoordinatesFlags mapCoordinatesFlags() const { return m_mapCoordinatesFlags; }
+
+ FloatPoint absolutePoint(const FloatPoint& p) const
+ {
+ return mapToContainer(p, 0);
+ }
+
+ FloatRect absoluteRect(const FloatRect& rect) const
+ {
+ return mapToContainer(rect, 0).boundingBox();
+ }
+
+ // Map to a container. Will assert that the container has been pushed onto this map.
+ // A null container maps through the RenderView (including its scale transform, if any).
+ // If the container is the RenderView, the scroll offset is applied, but not the scale.
+ FloatPoint mapToContainer(const FloatPoint&, const RenderLayerModelObject*) const;
+ FloatQuad mapToContainer(const FloatRect&, const RenderLayerModelObject*) const;
// Called by code walking the renderer or layer trees.
void pushMappingsToAncestor(const RenderLayer*, const RenderLayer* ancestorLayer);
@@ -97,7 +112,7 @@ public:
void pushView(const RenderView*, const LayoutSize& scrollOffset, const TransformationMatrix* = 0);
private:
- void mapToAbsolute(TransformState&) const;
+ void mapToContainer(TransformState&, const RenderLayerModelObject* container = 0) const;
void stepInserted(const RenderGeometryMapStep&);
void stepRemoved(const RenderGeometryMapStep&);
@@ -114,6 +129,7 @@ private:
int m_fixedStepsCount;
RenderGeometryMapSteps m_mapping;
LayoutSize m_accumulatedOffset;
+ MapCoordinatesFlags m_mapCoordinatesFlags;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderGrid.cpp b/Source/WebCore/rendering/RenderGrid.cpp
index 6e293cc0c..e520581b9 100644
--- a/Source/WebCore/rendering/RenderGrid.cpp
+++ b/Source/WebCore/rendering/RenderGrid.cpp
@@ -175,23 +175,33 @@ void RenderGrid::layoutGridItems()
setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);
}
-LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
+size_t RenderGrid::resolveGridPosition(const GridPosition& position) const
{
- Length column = child->style()->gridItemColumn();
- Length row = child->style()->gridItemRow();
-
- // FIXME: What does a non-positive integer mean for a column/row?
- if (!column.isPositive() || !row.isPositive())
- return LayoutPoint();
-
// FIXME: Handle other values for grid-{row,column} like ranges or line names.
- if (!column.isFixed() || !row.isFixed())
- return LayoutPoint();
+ switch (position.type()) {
+ case IntegerPosition:
+ // FIXME: What does a non-positive integer mean for a column/row?
+ if (!position.isPositive())
+ return 0;
+
+ return position.integerPosition() - 1;
+ case AutoPosition:
+ // FIXME: We should follow 'grid-auto-flow' for resolution.
+ // Until then, we use the 'grid-auto-flow: none' behavior (which is the default)
+ // and resolve 'auto' as the first row / column.
+ return 0;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
- size_t columnTrack = static_cast<size_t>(column.intValue()) - 1;
- size_t rowTrack = static_cast<size_t>(row.intValue()) - 1;
+LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
+{
+ size_t columnTrack = resolveGridPosition(child->style()->gridItemColumn());
+ size_t rowTrack = resolveGridPosition(child->style()->gridItemRow());
LayoutPoint offset;
+ // FIXME: |columnTrack| and |rowTrack| should be smaller than our column / row count.
for (size_t i = 0; i < columnTrack && i < columnTracks.size(); ++i)
offset.setX(offset.x() + columnTracks[i].m_usedBreadth);
for (size_t i = 0; i < rowTrack && i < rowTracks.size(); ++i)
diff --git a/Source/WebCore/rendering/RenderGrid.h b/Source/WebCore/rendering/RenderGrid.h
index e5017fae0..340c64851 100644
--- a/Source/WebCore/rendering/RenderGrid.h
+++ b/Source/WebCore/rendering/RenderGrid.h
@@ -50,6 +50,7 @@ private:
void layoutGridItems();
LayoutPoint findChildLogicalPosition(RenderBox*, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks);
+ size_t resolveGridPosition(const GridPosition&) const;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 2a8fe8823..4e27e6d99 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -1182,6 +1182,8 @@ const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelO
bool offsetDependsOnPoint = false;
LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+ if (geometryMap.mapCoordinatesFlags() & SnapOffsetForTransforms)
+ containerOffset = roundedIntSize(containerOffset);
bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
if (shouldUseTransformFromContainer(container)) {
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index fcd52fd15..4e67cd571 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
*
* Portions are Copyright (C) 1998 Netscape Communications Corporation.
*
@@ -77,6 +77,7 @@
#include "PlatformMouseEvent.h"
#include "RenderArena.h"
#include "RenderFlowThread.h"
+#include "RenderGeometryMap.h"
#include "RenderInline.h"
#include "RenderMarquee.h"
#include "RenderReplica.h"
@@ -90,6 +91,7 @@
#include "ScrollAnimator.h"
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
+#include "ScrollingCoordinator.h"
#include "Settings.h"
#include "SourceGraphic.h"
#include "StylePropertySet.h"
@@ -261,7 +263,8 @@ RenderLayer::~RenderLayer()
#if USE(ACCELERATED_COMPOSITING)
RenderLayerCompositor* RenderLayer::compositor() const
{
- ASSERT(renderer()->view());
+ if (!renderer()->view())
+ return 0;
return renderer()->view()->compositor();
}
@@ -334,55 +337,34 @@ LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
return offset;
}
-void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerPositionsFlags flags)
+void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags)
{
-#if !ASSERT_DISABLED
- if (offsetFromRoot) {
- bool hasLayerOffset;
- LayoutPoint computedOffsetFromRoot = computeOffsetFromRoot(hasLayerOffset);
- ASSERT(hasLayerOffset);
- ASSERT(*offsetFromRoot == computedOffsetFromRoot);
- }
-#endif
+ RenderGeometryMap geometryMap(UseTransforms);
+ if (this != rootLayer)
+ geometryMap.pushMappingsToAncestor(parent(), 0);
+ updateLayerPositions(&geometryMap, flags);
+}
+void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLayerPositionsFlags flags)
+{
updateLayerPosition(); // For relpositioned layers or non-positioned layers,
// we need to keep in sync, since we may have shifted relative
// to our parent layer.
- LayoutPoint oldOffsetFromRoot;
- if (offsetFromRoot) {
- // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation
- if (!canUseConvertToLayerCoords())
- offsetFromRoot = 0; // If our cached offset is invalid make sure it's not passed to any of our children
+ if (geometryMap)
+ geometryMap->pushMappingsToAncestor(this, parent());
+
+ if (hasOverflowControls()) {
+ LayoutPoint offsetFromRoot;
+ if (geometryMap)
+ offsetFromRoot = LayoutPoint(geometryMap->absolutePoint(FloatPoint()));
else {
- oldOffsetFromRoot = *offsetFromRoot;
- // Frequently our parent layer's renderer will be the same as our renderer's containing block. In that case,
- // we just update the cache using our offset to our parent (which is m_topLeft). Otherwise, regenerated cached
- // offsets to the root from the render tree.
- if (!m_parent || m_parent->renderer() == renderer()->containingBlock())
- offsetFromRoot->move(m_topLeft.x(), m_topLeft.y()); // Fast case
- else {
- LayoutPoint offset;
- convertToLayerCoords(root(), offset);
- *offsetFromRoot = offset;
- }
+ // FIXME: It looks suspicious to call convertToLayerCoords here
+ // as canUseConvertToLayerCoords may be true for an ancestor layer.
+ convertToLayerCoords(root(), offsetFromRoot);
}
+ positionOverflowControls(toSize(roundedIntPoint(offsetFromRoot)));
}
- LayoutPoint offset;
- if (offsetFromRoot) {
- offset = *offsetFromRoot;
-#ifndef NDEBUG
- LayoutPoint computedOffsetFromRoot;
- convertToLayerCoords(root(), computedOffsetFromRoot);
- ASSERT(offset == computedOffsetFromRoot);
-#endif
- } else {
- // FIXME: It looks suspicious to call convertToLayerCoords here
- // as canUseConvertToLayerCoords may be true for an ancestor layer.
- convertToLayerCoords(root(), offset);
- }
- positionOverflowControls(toSize(roundedIntPoint(offset)));
-
updateDescendantDependentFlags();
if (flags & UpdatePagination)
@@ -401,7 +383,8 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP
RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint();
LayoutRect oldRepaintRect = m_repaintRect;
LayoutRect oldOutlineBox = m_outlineBox;
- computeRepaintRects(offsetFromRoot);
+ computeRepaintRects(repaintContainer, geometryMap);
+
// FIXME: Should ASSERT that value calculated for m_outlineBox using the cached offset is the same
// as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
if (flags & CheckForRepaint) {
@@ -434,7 +417,7 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP
flags |= UpdatePagination;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositions(offsetFromRoot, flags);
+ child->updateLayerPositions(geometryMap, flags);
#if USE(ACCELERATED_COMPOSITING)
if ((flags & UpdateCompositingLayers) && isComposited())
@@ -450,8 +433,8 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP
m_updatingMarqueePosition = oldUpdatingMarqueePosition;
}
- if (offsetFromRoot)
- *offsetFromRoot = oldOffsetFromRoot;
+ if (geometryMap)
+ geometryMap->popMappingsToAncestor(parent());
}
LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
@@ -491,13 +474,12 @@ void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
}
}
-void RenderLayer::computeRepaintRects(LayoutPoint* offsetFromRoot)
+void RenderLayer::computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
{
ASSERT(!m_visibleContentStatusDirty);
- RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint();
m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
- m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, offsetFromRoot);
+ m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, geometryMap);
}
@@ -505,7 +487,8 @@ void RenderLayer::computeRepaintRectsIncludingDescendants()
{
// FIXME: computeRepaintRects() has to walk up the parent chain for every layer to compute the rects.
// We should make this more efficient.
- computeRepaintRects();
+ // FIXME: it's wrong to call this when layout is not up-to-date, which we do.
+ computeRepaintRects(renderer()->containerForRepaint());
for (RenderLayer* layer = firstChild(); layer; layer = layer->nextSibling())
layer->computeRepaintRectsIncludingDescendants();
@@ -520,7 +503,16 @@ void RenderLayer::clearRepaintRects()
m_outlineBox = IntRect();
}
-void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags flags)
+void RenderLayer::updateLayerPositionsAfterScroll()
+{
+ RenderGeometryMap geometryMap(UseTransforms);
+ RenderView* view = renderer()->view();
+ if (this != view->layer())
+ geometryMap.pushMappingsToAncestor(parent(), 0);
+ updateLayerPositionsAfterScroll(&geometryMap);
+}
+
+void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap, UpdateLayerPositionsAfterScrollFlags flags)
{
// FIXME: This shouldn't be needed, but there are some corner cases where
// these flags are still dirty. Update so that the check below is valid.
@@ -534,21 +526,25 @@ void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrol
updateLayerPosition();
+ if (geometryMap)
+ geometryMap->pushMappingsToAncestor(this, parent());
+
if ((flags & HasSeenViewportConstrainedAncestor) || renderer()->style()->hasViewportConstrainedPosition()) {
// FIXME: Is it worth passing the offsetFromRoot around like in updateLayerPositions?
- computeRepaintRects();
+ // FIXME: We could track the repaint container as we walk down the tree.
+ computeRepaintRects(renderer()->containerForRepaint(), geometryMap);
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.
- computeRepaintRects();
+ computeRepaintRects(renderer()->containerForRepaint(), geometryMap);
}
if (renderer()->hasOverflowClip())
flags |= HasSeenAncestorWithOverflowClip;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositionsAfterScroll(flags);
+ child->updateLayerPositionsAfterScroll(geometryMap, flags);
// We don't update our reflection as scrolling is a translation which does not change the size()
// of an object, thus RenderReplica will still repaint itself properly as the layer position was
@@ -560,6 +556,9 @@ void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrol
m_marquee->updateMarqueePosition();
m_updatingMarqueePosition = oldUpdatingMarqueePosition;
}
+
+ if (geometryMap)
+ geometryMap->popMappingsToAncestor(parent());
}
#if ENABLE(CSS_COMPOSITING)
@@ -702,7 +701,7 @@ void RenderLayer::setHasVisibleContent()
m_visibleContentStatusDirty = false;
m_hasVisibleContent = true;
- computeRepaintRects();
+ computeRepaintRects(renderer()->containerForRepaint());
if (!isNormalFlowOnly()) {
// We don't collect invisible layers in z-order lists if we are not in compositing mode.
// As we became visible, we need to dirty our stacking contexts ancestors to be properly
@@ -848,7 +847,7 @@ void RenderLayer::updateLayerPosition()
{
LayoutPoint localPoint;
LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
- if (renderer()->isRenderInline()) {
+ if (renderer()->isInline() && renderer()->isRenderInline()) {
RenderInline* inlineFlow = toRenderInline(renderer());
IntRect lineBox = inlineFlow->linesBoundingBox();
setSize(lineBox.size());
@@ -1114,7 +1113,7 @@ void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect,
// If we have at least one custom shader, we need to update the whole bounding box of the layer, because the
// shader can address any ouput pixel.
// Note: This is only for output rect, so there's no need to expand the dirty source rect.
- rectForRepaint.unite(calculateLayerBounds(this, this));
+ rectForRepaint.unite(calculateLayerBounds(this));
}
#endif
@@ -1423,8 +1422,6 @@ void RenderLayer::removeOnlyThisLayer()
clearClipRectsIncludingDescendants();
RenderLayer* nextSib = nextSibling();
- bool hasLayerOffset;
- const LayoutPoint offsetFromRootBeforeMove = computeOffsetFromRoot(hasLayerOffset);
// Remove the child reflection layer before moving other child layers.
// The reflection layer should not be moved to the parent.
@@ -1438,10 +1435,9 @@ void RenderLayer::removeOnlyThisLayer()
removeChild(current);
m_parent->addChild(current, nextSib);
current->setRepaintStatus(NeedsFullRepaint);
- LayoutPoint offsetFromRoot = offsetFromRootBeforeMove;
// updateLayerPositions depends on hasLayer() already being false for proper layout.
ASSERT(!renderer()->hasLayer());
- current->updateLayerPositions(hasLayerOffset ? &offsetFromRoot : 0);
+ current->updateLayerPositions(0); // FIXME: use geometry map.
current = next;
}
@@ -1483,36 +1479,37 @@ void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLa
roundedRect = pixelSnappedIntRect(rect);
}
-void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
+// Returns the layer reached on the walk up towards the ancestor.
+static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, LayoutPoint& location)
{
- if (ancestorLayer == this)
- return;
+ ASSERT(ancestorLayer != layer);
- EPosition position = renderer()->style()->position();
+ const RenderLayerModelObject* renderer = layer->renderer();
+ EPosition position = renderer->style()->position();
// FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
// may need to be revisited in a future patch.
// If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
// since localToAbsolute maps the coordinates from named flow to regions coordinates and regions can be
// positioned in a completely different place in the viewport (RenderView).
- if (position == FixedPosition && !renderer()->inRenderFlowThread() && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
+ if (position == FixedPosition && !renderer->inRenderFlowThread() && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) {
// If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
// localToAbsolute() on the RenderView.
- FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), IsFixed);
+ FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), IsFixed);
location += LayoutSize(absPos.x(), absPos.y());
- return;
+ return ancestorLayer;
}
// For the fixed positioned elements inside a render flow thread, we should also skip the code path below
// Otherwise, for the case of ancestorLayer == rootLayer and fixed positioned element child of a transformed
// element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer.
- if (position == FixedPosition && !renderer()->inRenderFlowThread()) {
+ if (position == FixedPosition && !renderer->inRenderFlowThread()) {
// For a fixed layers, we need to walk up to the root to see if there's a fixed position container
// (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
// so we should always find the ancestor at or before we find the fixed position container.
RenderLayer* fixedPositionContainerLayer = 0;
bool foundAncestor = false;
- for (RenderLayer* currLayer = parent(); currLayer; currLayer = currLayer->parent()) {
+ for (RenderLayer* currLayer = layer->parent(); currLayer; currLayer = currLayer->parent()) {
if (currLayer == ancestorLayer)
foundAncestor = true;
@@ -1527,20 +1524,20 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutP
if (fixedPositionContainerLayer != ancestorLayer) {
LayoutPoint fixedContainerCoords;
- convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
+ layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
LayoutPoint ancestorCoords;
ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
location += (fixedContainerCoords - ancestorCoords);
- return;
+ return ancestorLayer;
}
}
RenderLayer* parentLayer;
if (position == AbsolutePosition || position == FixedPosition) {
// Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
- parentLayer = parent();
+ parentLayer = layer->parent();
bool foundAncestorFirst = false;
while (parentLayer) {
// RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0).
@@ -1559,8 +1556,8 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutP
// We should not reach RenderView layer past the RenderFlowThread layer for any
// children of the RenderFlowThread.
- if (renderer()->inRenderFlowThread() && !renderer()->isRenderFlowThread())
- ASSERT(parentLayer != renderer()->view()->layer());
+ if (renderer->inRenderFlowThread() && !renderer->isRenderFlowThread())
+ ASSERT(parentLayer != renderer->view()->layer());
if (foundAncestorFirst) {
// Found ancestorLayer before the abs. positioned container, so compute offset of both relative
@@ -1568,23 +1565,32 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutP
RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
LayoutPoint thisCoords;
- convertToLayerCoords(positionedAncestor, thisCoords);
+ layer->convertToLayerCoords(positionedAncestor, thisCoords);
LayoutPoint ancestorCoords;
ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
location += (thisCoords - ancestorCoords);
- return;
+ return ancestorLayer;
}
} else
- parentLayer = parent();
+ parentLayer = layer->parent();
if (!parentLayer)
- return;
+ return 0;
- parentLayer->convertToLayerCoords(ancestorLayer, location);
+ location += toSize(layer->location());
+ return parentLayer;
+}
- location += toSize(m_topLeft);
+void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
+{
+ if (ancestorLayer == this)
+ return;
+
+ const RenderLayer* currLayer = this;
+ while (currLayer && currLayer != ancestorLayer)
+ currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, location);
}
void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const
@@ -1729,29 +1735,32 @@ void RenderLayer::scrollTo(int x, int y)
Frame* frame = renderer()->frame();
InspectorInstrumentation::willScrollLayer(frame);
- // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
- // We don't update compositing layers, because we need to do a deep update from the compositing ancestor.
- updateLayerPositionsAfterScroll();
-
RenderView* view = renderer()->view();
// We should have a RenderView if we're trying to scroll.
ASSERT(view);
- if (view) {
- // Update regions, scrolling may change the clip of a particular region.
+
+ // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
+ // We don't update compositing layers, because we need to do a deep update from the compositing ancestor.
+ bool inLayout = view ? view->frameView()->isInLayout() : false;
+ if (!inLayout) {
+ // If we're in the middle of layout, we'll just update layers once layout has finished.
+ updateLayerPositionsAfterScroll();
+ if (view) {
+ // Update regions, scrolling may change the clip of a particular region.
#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
- view->frameView()->updateAnnotatedRegions();
+ view->frameView()->updateAnnotatedRegions();
#endif
+ view->updateWidgetPositions();
+ }
- view->updateWidgetPositions();
- }
-
- if (!m_updatingMarqueePosition) {
- // Avoid updating compositing layers if, higher on the stack, we're already updating layer
- // positions. Updating layer positions requires a full walk of up-to-date RenderLayers, and
- // in this case we're still updating their positions; we'll update compositing layers later
- // when that completes.
- updateCompositingLayersAfterScroll();
+ if (!m_updatingMarqueePosition) {
+ // Avoid updating compositing layers if, higher on the stack, we're already updating layer
+ // positions. Updating layer positions requires a full walk of up-to-date RenderLayers, and
+ // in this case we're still updating their positions; we'll update compositing layers later
+ // when that completes.
+ updateCompositingLayersAfterScroll();
+ }
}
RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint();
@@ -1885,27 +1894,10 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignm
frameView->resumeScheduledEvents();
}
-#if USE(ACCELERATED_COMPOSITING)
-static FrameView* frameViewFromLayer(const RenderLayer* layer)
-{
- Frame* frame = layer->renderer()->frame();
- if (!frame)
- return 0;
-
- return frame->view();
-}
-#endif
-
void RenderLayer::updateCompositingLayersAfterScroll()
{
#if USE(ACCELERATED_COMPOSITING)
if (compositor()->inCompositingMode()) {
- // If we're in the middle of layout, we'll just update compositiong once layout has finished.
- if (FrameView* frameView = frameViewFromLayer(this)) {
- if (frameView->isInLayout())
- return;
- }
-
// Our stacking context is guaranteed to contain all of our descendants that may need
// repositioning, so update compositing layers from there.
if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
@@ -2291,6 +2283,34 @@ IntPoint RenderLayer::currentMousePosition() const
return renderer()->frame() ? renderer()->frame()->eventHandler()->currentMousePosition() : IntPoint();
}
+IntRect RenderLayer::rectForHorizontalScrollbar(const IntRect& borderBoxRect) const
+{
+ if (!m_hBar)
+ return IntRect();
+
+ const RenderBox* box = renderBox();
+ const IntRect& scrollCorner = scrollCornerRect();
+
+ return IntRect(horizontalScrollbarStart(borderBoxRect.x()),
+ borderBoxRect.maxY() - box->borderBottom() - m_hBar->height(),
+ borderBoxRect.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
+ m_hBar->height());
+}
+
+IntRect RenderLayer::rectForVerticalScrollbar(const IntRect& borderBoxRect) const
+{
+ if (!m_vBar)
+ return IntRect();
+
+ const RenderBox* box = renderBox();
+ const IntRect& scrollCorner = scrollCornerRect();
+
+ return IntRect(verticalScrollbarStart(borderBoxRect.x(), borderBoxRect.maxX()),
+ borderBoxRect.y() + box->borderTop(),
+ m_vBar->width(),
+ borderBoxRect.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height());
+}
+
LayoutUnit RenderLayer::verticalScrollbarStart(int minX, int maxX) const
{
const RenderBox* box = renderBox();
@@ -2513,18 +2533,18 @@ void RenderLayer::positionOverflowControls(const IntSize& offsetFromRoot)
const IntRect borderBox = box->pixelSnappedBorderBoxRect();
const IntRect& scrollCorner = scrollCornerRect();
IntRect absBounds(borderBox.location() + offsetFromRoot, borderBox.size());
- if (m_vBar)
- m_vBar->setFrameRect(IntRect(verticalScrollbarStart(absBounds.x(), absBounds.maxX()),
- absBounds.y() + box->borderTop(),
- m_vBar->width(),
- absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));
-
- if (m_hBar)
- m_hBar->setFrameRect(IntRect(horizontalScrollbarStart(absBounds.x()),
- absBounds.maxY() - box->borderBottom() - m_hBar->height(),
- absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
- m_hBar->height()));
-
+ if (m_vBar) {
+ IntRect vBarRect = rectForVerticalScrollbar(borderBox);
+ vBarRect.move(offsetFromRoot);
+ m_vBar->setFrameRect(vBarRect);
+ }
+
+ if (m_hBar) {
+ IntRect hBarRect = rectForHorizontalScrollbar(borderBox);
+ hBarRect.move(offsetFromRoot);
+ m_hBar->setFrameRect(hBarRect);
+ }
+
if (m_scrollCorner)
m_scrollCorner->setFrameRect(scrollCorner);
if (m_resizer)
@@ -2715,6 +2735,25 @@ void RenderLayer::updateScrollInfoAfterLayout()
#endif
}
+bool RenderLayer::overflowControlsIntersectRect(const IntRect& localRect) const
+{
+ const IntRect borderBox = renderBox()->pixelSnappedBorderBoxRect();
+
+ if (rectForHorizontalScrollbar(borderBox).intersects(localRect))
+ return true;
+
+ if (rectForVerticalScrollbar(borderBox).intersects(localRect))
+ return true;
+
+ if (scrollCornerRect().intersects(localRect))
+ return true;
+
+ if (resizerCornerRect(this, borderBox).intersects(localRect))
+ return true;
+
+ return false;
+}
+
void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
{
// Don't do anything if we have no overflow.
@@ -2734,9 +2773,21 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint
if ((m_hBar && layerForHorizontalScrollbar()) || (m_vBar && layerForVerticalScrollbar()))
return;
#endif
+ IntRect localDamgeRect = damageRect;
+ localDamgeRect.moveBy(-paintOffset);
+ if (!overflowControlsIntersectRect(localDamgeRect))
+ return;
+
RenderView* renderView = renderer()->view();
- renderView->layer()->setContainsDirtyOverlayScrollbars(true);
- renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
+
+ RenderLayer* paintingRoot = 0;
+#if USE(ACCELERATED_COMPOSITING)
+ paintingRoot = enclosingCompositingLayer();
+#endif
+ if (!paintingRoot)
+ paintingRoot = renderView->layer();
+
+ paintingRoot->setContainsDirtyOverlayScrollbars(true);
return;
}
@@ -2939,7 +2990,10 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit
void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags)
{
OverlapTestRequestMap overlapTestRequests;
- paintLayer(this, context, enclosingIntRect(damageRect), LayoutSize(), paintBehavior, paintingRoot, region, &overlapTestRequests, paintFlags);
+
+ LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, region, &overlapTestRequests);
+ paintLayer(context, paintingInfo, paintFlags);
+
OverlapTestRequestMap::iterator end = overlapTestRequests.end();
for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
it->key->setOverlapTestResult(false);
@@ -2949,8 +3003,10 @@ void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutR
{
if (!m_containsDirtyOverlayScrollbars)
return;
- paintLayer(this, context, damageRect, LayoutSize(), paintBehavior, paintingRoot, 0, 0, PaintLayerHaveTransparency | PaintLayerTemporaryClipRects
- | PaintLayerPaintingOverlayScrollbars);
+
+ LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot);
+ paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
+
m_containsDirtyOverlayScrollbars = false;
}
@@ -3045,18 +3101,17 @@ static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
}
-void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior,
- RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
- PaintLayerFlags paintFlags)
+void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
#if USE(ACCELERATED_COMPOSITING)
if (isComposited()) {
// The updatingControlTints() painting pass goes through compositing layers,
// but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
- if (context->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
+ if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers))
paintFlags |= PaintLayerTemporaryClipRects;
- else if (!backing()->paintsIntoWindow() && !backing()->paintsIntoCompositedAncestor() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection) && !(rootLayer->containsDirtyOverlayScrollbars() && (paintFlags & PaintLayerPaintingOverlayScrollbars))) {
+ else if (!backing()->paintsIntoWindow()
+ && !backing()->paintsIntoCompositedAncestor()
+ && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
// If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
return;
}
@@ -3074,12 +3129,12 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
if (!renderer()->opacity())
return;
- if (paintsWithTransparency(paintBehavior))
+ if (paintsWithTransparency(paintingInfo.paintBehavior))
paintFlags |= PaintLayerHaveTransparency;
// PaintLayerAppliedTransform is used in RenderReplica, to avoid applying the transform twice.
- if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
- TransformationMatrix layerTransform = renderableTransform(paintBehavior);
+ if (paintsWithTransform(paintingInfo.paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
+ TransformationMatrix layerTransform = renderableTransform(paintingInfo.paintBehavior);
// If the transform can't be inverted, then don't paint anything.
if (!layerTransform.isInvertible())
return;
@@ -3088,31 +3143,32 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
// layer from the parent now, assuming there is a parent
if (paintFlags & PaintLayerHaveTransparency) {
if (parent())
- parent()->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
+ parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
else
- beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
+ beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
}
// Make sure the parent's clip rects have been calculated.
- ClipRect clipRect = paintDirtyRect;
+ ClipRect clipRect = paintingInfo.paintDirtyRect;
if (parent()) {
- clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
+ ClipRectsContext clipRectsContext(paintingInfo.rootLayer, paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
- clipRect.intersect(paintDirtyRect);
+ clipRect = backgroundClipRect(clipRectsContext);
+ clipRect.intersect(paintingInfo.paintDirtyRect);
// Push the parent coordinate space's clip.
- parent()->clipToRect(rootLayer, context, paintDirtyRect, clipRect);
+ parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
}
// Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
// This involves subtracting out the position of the layer in our current coordinate space, but preserving
// the accumulated error for sub-pixel layout.
LayoutPoint delta;
- convertToLayerCoords(rootLayer, delta);
+ convertToLayerCoords(paintingInfo.rootLayer, delta);
TransformationMatrix transform(layerTransform);
IntPoint roundedDelta = roundedIntPoint(delta);
transform.translateRight(roundedDelta.x(), roundedDelta.y());
- LayoutSize adjustedSubPixelAccumulation = subPixelAccumulation + (delta - roundedDelta);
+ LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
// Apply the transform.
{
@@ -3120,23 +3176,21 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
context->concatCTM(transform.toAffineTransform());
// Now do a paint with the root layer shifted to be us.
- paintLayerContentsAndReflection(this, context, enclosingIntRect(transform.inverse().mapRect(paintDirtyRect)), adjustedSubPixelAccumulation, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
+ LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior, adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.region, paintingInfo.overlapTestRequests);
+ paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags);
}
// Restore the clip.
if (parent())
- parent()->restoreClip(context, paintDirtyRect, clipRect);
+ parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
return;
}
- paintLayerContentsAndReflection(rootLayer, context, paintDirtyRect, subPixelAccumulation, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
+ paintLayerContentsAndReflection(context, paintingInfo, paintFlags);
}
-void RenderLayer::paintLayerContentsAndReflection(RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior,
- RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
- PaintLayerFlags paintFlags)
+void RenderLayer::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
@@ -3146,18 +3200,15 @@ void RenderLayer::paintLayerContentsAndReflection(RenderLayer* rootLayer, Graphi
if (m_reflection && !m_paintingInsideReflection) {
// Mark that we are now inside replica painting.
m_paintingInsideReflection = true;
- reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, subPixelAccumulation, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
+ reflectionLayer()->paintLayer(context, paintingInfo, localPaintFlags | PaintLayerPaintingReflection);
m_paintingInsideReflection = false;
}
localPaintFlags |= PaintLayerPaintingCompositingAllPhases;
- paintLayerContents(rootLayer, context, paintDirtyRect, subPixelAccumulation, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
+ paintLayerContents(context, paintingInfo, localPaintFlags);
}
-void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& parentPaintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior,
- RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
- PaintLayerFlags paintFlags)
+void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
@@ -3169,18 +3220,38 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars;
bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars;
- // Calculate the clip rects we should use only when we need them.
- LayoutRect layerBounds;
- ClipRect damageRect, clipRectToApply, outlineRect;
- LayoutPoint paintOffset;
- LayoutRect paintDirtyRect = parentPaintDirtyRect;
-
bool useClipRect = true;
GraphicsContext* transparencyLayerContext = context;
// Ensure our lists are up-to-date.
updateLayerListsIfNeeded();
+ LayoutPoint offsetFromRoot;
+ convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
+
+ IntRect rootRelativeBounds;
+ bool rootRelativeBoundsComputed = false;
+
+ bool didQuantizeFonts = true;
+ bool scrollingOnMainThread = true;
+ Frame* frame = renderer()->frame();
+#if ENABLE(THREADED_SCROLLING)
+ if (frame) {
+ if (Page* page = frame->page()) {
+ if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+ scrollingOnMainThread = scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread();
+ }
+ }
+#endif
+
+ // FIXME: We shouldn't have to disable subpixel quantization for overflow clips or subframes once we scroll those
+ // things on the scrolling thread.
+ bool needToAdjustSubpixelQuantization = scrollingOnMainThread || (renderer()->hasOverflowClip() && !usesCompositedScrolling()) || (frame && frame->ownerElement());
+ if (needToAdjustSubpixelQuantization) {
+ didQuantizeFonts = context->shouldSubpixelQuantizeFonts();
+ context->setShouldSubpixelQuantizeFonts(false);
+ }
+
// Apply clip-path to context.
bool hasClipPath = false;
RenderStyle* style = renderer()->style();
@@ -3190,7 +3261,13 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
hasClipPath = true;
context->save();
ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(style->clipPath());
- context->clipPath(clipPath->path(calculateLayerBounds(this, rootLayer, 0)), clipPath->windRule());
+
+ if (!rootRelativeBoundsComputed) {
+ rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+ rootRelativeBoundsComputed = true;
+ }
+
+ context->clipPath(clipPath->path(rootRelativeBounds), clipPath->windRule());
}
#if ENABLE(SVG)
else if (style->clipPath()->getOperationType() == ClipPathOperation::REFERENCE) {
@@ -3198,22 +3275,33 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
Document* document = renderer()->document();
// FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405)
Element* element = document ? document->getElementById(referenceClipPathOperation->fragment()) : 0;
- if (element && element->hasTagName(SVGNames::clipPathTag) && element->renderer())
- static_cast<RenderSVGResourceClipper*>(element->renderer())->applyClippingToContext(renderer(), calculateLayerBounds(this, rootLayer, 0), paintDirtyRect, context);
+ if (element && element->hasTagName(SVGNames::clipPathTag) && element->renderer()) {
+ if (!rootRelativeBoundsComputed) {
+ rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+ rootRelativeBoundsComputed = true;
+ }
+
+ static_cast<RenderSVGResourceClipper*>(element->renderer())->applyClippingToContext(renderer(), rootRelativeBounds, paintingInfo.paintDirtyRect, context);
+ }
}
#endif
}
+ LayerPaintingInfo localPaintingInfo(paintingInfo);
#if ENABLE(CSS_FILTERS)
FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
- LayoutPoint rootLayerOffset;
- convertToLayerCoords(rootLayer, rootLayerOffset);
RenderLayerFilterInfo* filterInfo = this->filterInfo();
ASSERT(filterInfo);
LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
- filterRepaintRect.move(rootLayerOffset.x(), rootLayerOffset.y());
- if (filterPainter.prepareFilterEffect(this, calculateLayerBounds(this, rootLayer, 0), parentPaintDirtyRect, filterRepaintRect)) {
+ filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y());
+
+ if (!rootRelativeBoundsComputed) {
+ rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+ rootRelativeBoundsComputed = true;
+ }
+
+ if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, paintingInfo.paintDirtyRect, filterRepaintRect)) {
// Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
filterInfo->resetDirtySourceRect();
@@ -3225,7 +3313,7 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
// Check that we didn't fail to allocate the graphics context for the offscreen buffer.
if (filterPainter.hasStartedFilterEffect()) {
- paintDirtyRect = filterPainter.repaintRect();
+ localPaintingInfo.paintDirtyRect = filterPainter.repaintRect();
// If the filter needs the full source image, we need to avoid using the clip rectangles.
// Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
// Note that we will still apply the clipping on the final rendering of the filter.
@@ -3234,57 +3322,62 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
}
}
#endif
-
+
+ // Calculate the clip rects we should use only when we need them.
+ LayoutRect layerBounds;
+ ClipRect damageRect, clipRectToApply, outlineRect;
+ LayoutPoint paintOffset;
+
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
- calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect,
- IgnoreOverlayScrollbarSize, localPaintFlags & PaintLayerPaintingOverflowContents ? IgnoreOverflowClip : RespectOverflowClip);
- paintOffset = toPoint(layerBounds.location() - renderBoxLocation() + subPixelAccumulation);
- if (this == rootLayer)
+ ClipRectsContext clipRectsContext(localPaintingInfo.rootLayer, localPaintingInfo.region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, localPaintFlags & PaintLayerPaintingOverflowContents ? IgnoreOverflowClip : RespectOverflowClip);
+ calculateRects(clipRectsContext, localPaintingInfo.paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, &offsetFromRoot);
+ paintOffset = toPoint(layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation);
+ if (this == localPaintingInfo.rootLayer)
paintOffset = roundedIntPoint(paintOffset);
}
- bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
- bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly;
+ bool forceBlackText = localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText;
+ bool selectionOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly;
// If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
// is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
// Else, our renderer tree may or may not contain the painting root, so we pass that root along
// so it will be tested against as we descend through the renderers.
RenderObject* paintingRootForRenderer = 0;
- if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
- paintingRootForRenderer = paintingRoot;
+ if (localPaintingInfo.paintingRoot && !renderer()->isDescendantOf(localPaintingInfo.paintingRoot))
+ paintingRootForRenderer = localPaintingInfo.paintingRoot;
- if (overlapTestRequests && isSelfPaintingLayer)
- performOverlapTests(*overlapTestRequests, rootLayer, this);
+ if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
+ performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
// We want to paint our layer, but only if we intersect the damage rect.
- if (this != rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents))
- shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
+ if (this != localPaintingInfo.rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents))
+ shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), localPaintingInfo.rootLayer, &offsetFromRoot);
if (localPaintFlags & PaintLayerPaintingCompositingBackgroundPhase) {
if (shouldPaintContent && !selectionOnly) {
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
- beginTransparencyLayers(transparencyLayerContext, rootLayer, paintDirtyRect, paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, localPaintingInfo.paintBehavior);
if (useClipRect) {
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
- clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
+ clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
}
// Paint the background.
- PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
+ PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, localPaintingInfo.region, 0);
renderer()->paint(paintInfo, paintOffset);
if (useClipRect) {
// Restore the clip.
- restoreClip(context, paintDirtyRect, damageRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, damageRect);
}
}
// Now walk the sorted list of children with negative z-indices.
- paintList(negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
+ paintList(negZOrderList(), context, localPaintingInfo, localPaintFlags);
}
if (localPaintFlags & PaintLayerPaintingCompositingForegroundPhase) {
@@ -3292,22 +3385,22 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
if (shouldPaintContent && !clipRectToApply.isEmpty()) {
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
- beginTransparencyLayers(transparencyLayerContext, rootLayer, paintDirtyRect, paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, localPaintingInfo.paintBehavior);
if (useClipRect) {
// Set up the clip used when painting our children.
- clipToRect(rootLayer, context, paintDirtyRect, clipRectToApply);
+ clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, clipRectToApply);
}
PaintInfo paintInfo(context, pixelSnappedIntRect(clipRectToApply.rect()),
selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
- forceBlackText, paintingRootForRenderer, region, 0);
+ forceBlackText, paintingRootForRenderer, localPaintingInfo.region, 0);
renderer()->paint(paintInfo, paintOffset);
if (!selectionOnly) {
paintInfo.phase = PaintPhaseFloat;
renderer()->paint(paintInfo, paintOffset);
paintInfo.phase = PaintPhaseForeground;
- paintInfo.overlapTestRequests = overlapTestRequests;
+ paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
renderer()->paint(paintInfo, paintOffset);
paintInfo.phase = PaintPhaseChildOutlines;
renderer()->paint(paintInfo, paintOffset);
@@ -3315,37 +3408,37 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
if (useClipRect) {
// Now restore our clip.
- restoreClip(context, paintDirtyRect, clipRectToApply);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, clipRectToApply);
}
}
if (shouldPaintOutline && !outlineRect.isEmpty()) {
// Paint our own outline
- PaintInfo paintInfo(context, pixelSnappedIntRect(outlineRect.rect()), PaintPhaseSelfOutline, false, paintingRootForRenderer, region, 0);
- clipToRect(rootLayer, context, paintDirtyRect, outlineRect, DoNotIncludeSelfForBorderRadius);
+ PaintInfo paintInfo(context, pixelSnappedIntRect(outlineRect.rect()), PaintPhaseSelfOutline, false, paintingRootForRenderer, localPaintingInfo.region, 0);
+ clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, outlineRect, DoNotIncludeSelfForBorderRadius);
renderer()->paint(paintInfo, paintOffset);
- restoreClip(context, paintDirtyRect, outlineRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, outlineRect);
}
// Paint any child layers that have overflow.
- paintList(m_normalFlowList, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
+ paintList(m_normalFlowList, context, localPaintingInfo, localPaintFlags);
// Now walk the sorted list of children with positive z-indices.
- paintList(posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
+ paintList(posZOrderList(), context, localPaintingInfo, localPaintFlags);
}
if (isPaintingOverlayScrollbars) {
- clipToRect(rootLayer, context, paintDirtyRect, damageRect);
+ clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, damageRect);
paintOverflowControls(context, roundedIntPoint(paintOffset), pixelSnappedIntRect(damageRect.rect()), true);
- restoreClip(context, paintDirtyRect, damageRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, damageRect);
}
#if ENABLE(CSS_FILTERS)
if (filterPainter.hasStartedFilterEffect()) {
// Apply the correct clipping (ie. overflow: hidden).
- clipToRect(rootLayer, transparencyLayerContext, paintDirtyRect, damageRect);
+ clipToRect(localPaintingInfo.rootLayer, transparencyLayerContext, localPaintingInfo.paintDirtyRect, damageRect);
context = filterPainter.applyFilterEffect();
- restoreClip(transparencyLayerContext, paintDirtyRect, damageRect);
+ restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, damageRect);
}
#endif
@@ -3354,15 +3447,15 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
if ((localPaintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly) {
if (useClipRect)
- clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
+ clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
// Paint the mask.
- PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseMask, false, paintingRootForRenderer, region, 0);
+ PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseMask, false, paintingRootForRenderer, localPaintingInfo.region, 0);
renderer()->paint(paintInfo, paintOffset);
if (useClipRect) {
// Restore the clip.
- restoreClip(context, paintDirtyRect, damageRect);
+ restoreClip(context, localPaintingInfo.paintDirtyRect, damageRect);
}
}
@@ -3373,14 +3466,15 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
m_usedTransparency = false;
}
+ // Re-set this to whatever it was before we painted the layer.
+ if (needToAdjustSubpixelQuantization)
+ context->setShouldSubpixelQuantizeFonts(didQuantizeFonts);
+
if (hasClipPath)
context->restore();
}
-void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
- RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
- PaintLayerFlags paintFlags)
+void RenderLayer::paintList(Vector<RenderLayer*>* list, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
if (!list)
return;
@@ -3395,16 +3489,13 @@ void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
for (size_t i = 0; i < list->size(); ++i) {
RenderLayer* childLayer = list->at(i);
if (!childLayer->isPaginated())
- childLayer->paintLayer(rootLayer, context, paintDirtyRect, LayoutSize(), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
+ childLayer->paintLayer(context, paintingInfo, paintFlags);
else
- paintPaginatedChildLayer(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
+ paintPaginatedChildLayer(childLayer, context, paintingInfo, paintFlags);
}
}
-void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
- RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
- PaintLayerFlags paintFlags)
+void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
{
// We need to do multiple passes, breaking up our child layer into strips.
Vector<RenderLayer*> columnLayers;
@@ -3422,13 +3513,11 @@ void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer*
if (!columnLayers.size())
return;
- paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1);
+ paintChildLayerIntoColumns(childLayer, context, paintingInfo, paintFlags, columnLayers, columnLayers.size() - 1);
}
-void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
- RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
- PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
+void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo,
+ PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
{
RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
@@ -3439,7 +3528,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
LayoutPoint layerOffset;
// FIXME: It looks suspicious to call convertToLayerCoords here
// as canUseConvertToLayerCoords is true for this layer.
- columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
+ columnBlock->layer()->convertToLayerCoords(paintingInfo.rootLayer, layerOffset);
bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
@@ -3466,7 +3555,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
colRect.moveBy(layerOffset);
- LayoutRect localDirtyRect(paintDirtyRect);
+ LayoutRect localDirtyRect(paintingInfo.paintDirtyRect);
localDirtyRect.intersect(colRect);
if (!localDirtyRect.isEmpty()) {
@@ -3486,7 +3575,11 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height()));
childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
- childLayer->paintLayer(rootLayer, context, localDirtyRect, LayoutSize(), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
+
+ LayerPaintingInfo localPaintingInfo(paintingInfo);
+ localPaintingInfo.paintDirtyRect = localDirtyRect;
+ childLayer->paintLayer(context, localPaintingInfo, paintFlags);
+
if (oldHasTransform)
childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
else
@@ -3495,7 +3588,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
// Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
// This involves subtracting out the position of the layer in our current coordinate space.
LayoutPoint childOffset;
- columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childOffset);
+ columnLayers[colIndex - 1]->convertToLayerCoords(paintingInfo.rootLayer, childOffset);
TransformationMatrix transform;
transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height()));
@@ -3503,9 +3596,10 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
context->concatCTM(transform.toAffineTransform());
// Now do a paint with the root layer shifted to be the next multicol block.
- paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior,
- paintingRoot, region, overlapTestRequests, paintFlags,
- columnLayers, colIndex - 1);
+ LayerPaintingInfo columnPaintingInfo(paintingInfo);
+ columnPaintingInfo.rootLayer = columnLayers[colIndex - 1];
+ columnPaintingInfo.paintDirtyRect = transform.inverse().mapRect(localDirtyRect);
+ paintChildLayerIntoColumns(childLayer, context, columnPaintingInfo, paintFlags, columnLayers, colIndex - 1);
}
}
@@ -3548,7 +3642,7 @@ bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation&
// 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()) {
- renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(result.point()));
+ renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(hitTestLocation.point()));
insideLayer = this;
}
}
@@ -3573,6 +3667,23 @@ Node* RenderLayer::enclosingElement() const
return 0;
}
+#if ENABLE(DIALOG_ELEMENT)
+bool RenderLayer::isInTopLayer() const
+{
+ Node* node = renderer()->node();
+ return node && node->isElementNode() && toElement(node)->isInTopLayer();
+}
+
+bool RenderLayer::isInTopLayerSubtree() const
+{
+ for (const RenderLayer* layer = this; layer; layer = layer->parent()) {
+ if (layer->isInTopLayer())
+ return true;
+ }
+ return false;
+}
+#endif
+
// Compute the z-offset of the point in the transformState.
// This is effectively projecting a ray normal to the plane of ancestor, finding where that
// ray intersects target, and computing the z delta between those two points.
@@ -3661,13 +3772,12 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
// The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
- bool useTemporaryClipRects = renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
-
// Apply a transform if we have one.
if (transform() && !appliedTransform) {
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- ClipRect clipRect = backgroundClipRect(rootLayer, hitTestLocation.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ ClipRectsContext clipRectsContext(rootLayer, hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ ClipRect clipRect = backgroundClipRect(clipRectsContext);
// Go ahead and test the enclosing clip now.
if (!clipRect.intersects(hitTestLocation))
return 0;
@@ -3734,7 +3844,9 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
ClipRect bgRect;
ClipRect fgRect;
ClipRect outlineRect;
- calculateRects(rootLayer, hitTestLocation.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, IncludeOverlayScrollbarSize);
+
+ ClipRectsContext clipRectsContext(rootLayer, hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
+ calculateRects(clipRectsContext, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
// The following are used for keeping track of the z-depth of the hit point of 3d-transformed
// descendants.
@@ -4017,23 +4129,25 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
return 0;
}
-void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip)
+void RenderLayer::updateClipRects(const ClipRectsContext& clipRectsContext)
{
+ ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
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));
+ ASSERT(clipRectsContext.rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
+ ASSERT(m_clipRectsCache->m_respectingOverflowClip[clipRectsType] == (clipRectsContext.respectOverflowClip == RespectOverflowClip));
+ ASSERT(m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] == clipRectsContext.overlayScrollbarSizeRelevancy);
return; // We have the correct cached value.
}
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
- RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
+ RenderLayer* parentLayer = clipRectsContext.rootLayer != this ? parent() : 0;
if (parentLayer)
- parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
+ parentLayer->updateClipRects(clipRectsContext);
ClipRects clipRects;
- calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
+ calculateClipRects(clipRectsContext, clipRects);
if (!m_clipRectsCache)
m_clipRectsCache = adoptPtr(new ClipRectsCache);
@@ -4044,12 +4158,13 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* re
m_clipRectsCache->m_clipRects[clipRectsType] = ClipRects::create(clipRects);
#ifndef NDEBUG
- m_clipRectsCache->m_clipRectsRoot[clipRectsType] = rootLayer;
- m_clipRectsCache->m_respectingOverflowClip[clipRectsType] = respectOverflowClip == RespectOverflowClip;
+ m_clipRectsCache->m_clipRectsRoot[clipRectsType] = clipRectsContext.rootLayer;
+ m_clipRectsCache->m_respectingOverflowClip[clipRectsType] = clipRectsContext.respectOverflowClip == RespectOverflowClip;
+ m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] = clipRectsContext.overlayScrollbarSizeRelevancy;
#endif
}
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
+void RenderLayer::calculateClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
if (!parent()) {
// The root layer's clip rect is always infinite.
@@ -4057,18 +4172,22 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
return;
}
+ ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
bool useCached = clipRectsType != TemporaryClipRects;
// For transformed layers, the root layer was shifted to be us, so there is no need to
// examine the parent. We want to cache clip rects with us as the root.
- RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
+ RenderLayer* parentLayer = clipRectsContext.rootLayer != this ? parent() : 0;
// Ensure that our parent's clip has been calculated so that we can examine the values.
if (parentLayer) {
if (useCached && parentLayer->clipRects(clipRectsType))
clipRects = *parentLayer->clipRects(clipRectsType);
- else
- parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects, IgnoreOverlayScrollbarSize, respectOverflowClip);
+ else {
+ ClipRectsContext parentContext(clipRectsContext);
+ parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize; // FIXME: why?
+ parentLayer->calculateClipRects(parentContext, clipRects);
+ }
} else
clipRects.reset(PaintInfo::infiniteRect());
@@ -4084,22 +4203,22 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
clipRects.setOverflowClipRect(clipRects.posClipRect());
// Update the clip rects that will be passed to child layers.
- if ((renderer()->hasOverflowClip() && (respectOverflowClip == RespectOverflowClip || this != rootLayer)) || renderer()->hasClip()) {
+ if ((renderer()->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || this != clipRectsContext.rootLayer)) || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
// This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
// some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
// clipRects are needed in view space.
LayoutPoint offset;
- offset = roundedLayoutPoint(renderer()->localToContainerPoint(FloatPoint(), rootLayer->renderer()));
+ offset = roundedLayoutPoint(renderer()->localToContainerPoint(FloatPoint(), clipRectsContext.rootLayer->renderer()));
RenderView* view = renderer()->view();
ASSERT(view);
- if (view && clipRects.fixed() && rootLayer->renderer() == view) {
+ if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) {
offset -= view->frameView()->scrollOffsetForFixedPosition();
}
if (renderer()->hasOverflowClip()) {
- ClipRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(offset, region, relevancy);
+ ClipRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy);
if (renderer()->style()->hasBorderRadius())
newOverflowClip.setHasRadius(true);
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
@@ -4107,7 +4226,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
}
if (renderer()->hasClip()) {
- LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, region);
+ LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, clipRectsContext.region);
clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
@@ -4115,16 +4234,16 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion*
}
}
-void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
+void RenderLayer::parentClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
{
ASSERT(parent());
- if (clipRectsType == TemporaryClipRects) {
- parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
+ if (clipRectsContext.clipRectsType == TemporaryClipRects) {
+ parent()->calculateClipRects(clipRectsContext, clipRects);
return;
}
- parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
- clipRects = *parent()->clipRects(clipRectsType);
+ parent()->updateClipRects(clipRectsContext);
+ clipRects = *parent()->clipRects(clipRectsContext.clipRectsType);
}
static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
@@ -4138,27 +4257,27 @@ static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRect
return parentRects.overflowClipRect();
}
-ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
+ClipRect RenderLayer::backgroundClipRect(const ClipRectsContext& clipRectsContext) const
{
ASSERT(parent());
ClipRects parentRects;
- parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy, respectOverflowClip);
+ parentClipRects(clipRectsContext, parentRects);
ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
RenderView* view = renderer()->view();
ASSERT(view);
// Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
- if (parentRects.fixed() && rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
+ if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition());
return backgroundClipRect;
}
-void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
- ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
+void RenderLayer::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+ ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
{
- if (rootLayer != this && parent()) {
- backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
+ if (clipRectsContext.rootLayer != this && parent()) {
+ backgroundRect = backgroundClipRect(clipRectsContext);
backgroundRect.intersect(paintDirtyRect);
} else
backgroundRect = paintDirtyRect;
@@ -4167,21 +4286,24 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* reg
outlineRect = backgroundRect;
LayoutPoint offset;
- convertToLayerCoords(rootLayer, offset);
+ if (offsetFromRoot)
+ offset = *offsetFromRoot;
+ else
+ convertToLayerCoords(clipRectsContext.rootLayer, offset);
layerBounds = LayoutRect(offset, size());
// Update the clip rects that will be passed to child layers.
if (renderer()->hasClipOrOverflowClip()) {
// This layer establishes a clip of some kind.
- if (renderer()->hasOverflowClip() && (this != rootLayer || respectOverflowClip == RespectOverflowClip)) {
- foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, region, relevancy));
+ if (renderer()->hasOverflowClip() && (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)) {
+ foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy));
if (renderer()->style()->hasBorderRadius())
foregroundRect.setHasRadius(true);
}
if (renderer()->hasClip()) {
// Clip applies to *us* as well, so go ahead and update the damageRect.
- LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, region);
+ LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, clipRectsContext.region);
backgroundRect.intersect(newPosClip);
foregroundRect.intersect(newPosClip);
outlineRect.intersect(newPosClip);
@@ -4196,13 +4318,13 @@ 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);
- if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
+ if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
backgroundRect.intersect(layerBoundsWithVisualOverflow);
} else {
// Shift the bounds to be for our region only.
- LayoutRect bounds = renderBox()->borderBoxRectInRegion(region);
+ LayoutRect bounds = renderBox()->borderBoxRectInRegion(clipRectsContext.region);
bounds.moveBy(offset);
- if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
+ if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
backgroundRect.intersect(bounds);
}
}
@@ -4216,8 +4338,9 @@ LayoutRect RenderLayer::childrenClipRect() const
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
+ ClipRectsContext clipRectsContext(clippingRootLayer, 0, TemporaryClipRects);
// Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
- calculateRects(clippingRootLayer, 0, TemporaryClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ calculateRects(clipRectsContext, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect()), SnapOffsetForTransforms).enclosingBoundingBox();
}
@@ -4229,7 +4352,8 @@ LayoutRect RenderLayer::selfClipRect() const
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
- calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
+ calculateRects(clipRectsContext, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect()), SnapOffsetForTransforms).enclosingBoundingBox();
}
@@ -4240,7 +4364,8 @@ LayoutRect RenderLayer::localClipRect() const
RenderLayer* clippingRootLayer = clippingRootForPainting();
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
- calculateRects(clippingRootLayer, 0, PaintingClipRects, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
+ calculateRects(clipRectsContext, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
LayoutRect clipRect = backgroundRect.rect();
if (clipRect == PaintInfo::infiniteRect())
@@ -4275,7 +4400,7 @@ void RenderLayer::repaintBlockSelectionGaps()
LayoutRect rect = m_blockSelectionGapsBounds;
rect.move(-scrolledContentOffset());
- if (renderer()->hasOverflowClip())
+ if (renderer()->hasOverflowClip() && !usesCompositedScrolling())
rect.intersect(toRenderBox(renderer())->overflowClipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
if (renderer()->hasClip())
rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
@@ -4283,7 +4408,7 @@ void RenderLayer::repaintBlockSelectionGaps()
renderer()->repaintRectangle(rect);
}
-bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer) const
+bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) const
{
// Always examine the canvas and the root.
// FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
@@ -4304,7 +4429,7 @@ bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const Layo
// Otherwise we need to compute the bounding box of this single layer and see if it intersects
// the damage rect.
- return boundingBox(rootLayer).intersects(damageRect);
+ return boundingBox(rootLayer, offsetFromRoot).intersects(damageRect);
}
LayoutRect RenderLayer::localBoundingBox() const
@@ -4319,7 +4444,7 @@ LayoutRect RenderLayer::localBoundingBox() const
// as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those
// floats.
LayoutRect result;
- if (renderer()->isRenderInline())
+ if (renderer()->isInline() && renderer()->isRenderInline())
result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
else if (renderer()->isTableRow()) {
// Our bounding box is just the union of all of our cells' border/overflow rects.
@@ -4355,15 +4480,20 @@ LayoutRect RenderLayer::localBoundingBox() const
return result;
}
-LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
+LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot) const
{
LayoutRect result = localBoundingBox();
if (renderer()->isBox())
renderBox()->flipForWritingMode(result);
else
renderer()->containingBlock()->flipForWritingMode(result);
+
LayoutPoint delta;
- convertToLayerCoords(ancestorLayer, delta);
+ if (offsetFromRoot)
+ delta = *offsetFromRoot;
+ else
+ convertToLayerCoords(ancestorLayer, delta);
+
result.moveBy(delta);
return result;
}
@@ -4373,26 +4503,34 @@ IntRect RenderLayer::absoluteBoundingBox() const
return pixelSnappedIntRect(boundingBox(root()));
}
-IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags)
+IntRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot, CalculateLayerBoundsFlags flags) const
{
- if (!layer->isSelfPaintingLayer())
+ if (!isSelfPaintingLayer())
return IntRect();
// FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
- if ((flags & ExcludeHiddenDescendants) && layer != ancestorLayer && !layer->hasVisibleContent() && !layer->hasVisibleDescendant())
+ if ((flags & ExcludeHiddenDescendants) && this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
return IntRect();
- LayoutRect boundingBoxRect = layer->localBoundingBox();
- if (layer->renderer()->isBox())
- layer->renderBox()->flipForWritingMode(boundingBoxRect);
+ RenderLayerModelObject* renderer = this->renderer();
+
+ if (isRootLayer()) {
+ // The root layer is always just the size of the document.
+ return renderer->view()->unscaledDocumentRect();
+ }
+
+ LayoutRect boundingBoxRect = localBoundingBox();
+
+ if (renderer->isBox())
+ toRenderBox(renderer)->flipForWritingMode(boundingBoxRect);
else
- layer->renderer()->containingBlock()->flipForWritingMode(boundingBoxRect);
+ renderer->containingBlock()->flipForWritingMode(boundingBoxRect);
- if (layer->renderer()->isRoot()) {
+ if (renderer->isRoot()) {
// If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
// then it has to be big enough to cover the viewport in order to display the background. This is akin
// to the code in RenderBox::paintRootBoxFillLayers().
- if (FrameView* frameView = layer->renderer()->view()->frameView()) {
+ if (FrameView* frameView = renderer->view()->frameView()) {
LayoutUnit contentsWidth = frameView->contentsWidth();
LayoutUnit contentsHeight = frameView->contentsHeight();
@@ -4404,13 +4542,13 @@ IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const Render
LayoutRect unionBounds = boundingBoxRect;
if (flags & UseLocalClipRectIfPossible) {
- LayoutRect localClipRect = layer->localClipRect();
+ LayoutRect localClipRect = this->localClipRect();
if (localClipRect != PaintInfo::infiniteRect()) {
- if ((flags & IncludeSelfTransform) && layer->paintsWithTransform(PaintBehaviorNormal))
- localClipRect = layer->transform()->mapRect(localClipRect);
+ if ((flags & IncludeSelfTransform) && paintsWithTransform(PaintBehaviorNormal))
+ localClipRect = transform()->mapRect(localClipRect);
LayoutPoint ancestorRelOffset;
- layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
+ convertToLayerCoords(ancestorLayer, ancestorRelOffset);
localClipRect.moveBy(ancestorRelOffset);
return pixelSnappedIntRect(localClipRect);
}
@@ -4419,49 +4557,49 @@ IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const Render
// FIXME: should probably just pass 'flags' down to descendants.
CalculateLayerBoundsFlags descendantFlags = DefaultCalculateLayerBoundsFlags | (flags & ExcludeHiddenDescendants);
- const_cast<RenderLayer*>(layer)->updateLayerListsIfNeeded();
+ const_cast<RenderLayer*>(this)->updateLayerListsIfNeeded();
- if (RenderLayer* reflection = layer->reflectionLayer()) {
+ if (RenderLayer* reflection = reflectionLayer()) {
if (!reflection->isComposited()) {
- IntRect childUnionBounds = calculateLayerBounds(reflection, layer, descendantFlags);
+ IntRect childUnionBounds = reflection->calculateLayerBounds(this, 0, descendantFlags);
unionBounds.unite(childUnionBounds);
}
}
- ASSERT(layer->isStackingContext() || (!layer->posZOrderList() || !layer->posZOrderList()->size()));
+ ASSERT(isStackingContext() || (!posZOrderList() || !posZOrderList()->size()));
#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(layer));
+ LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this));
#endif
- if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ if (Vector<RenderLayer*>* negZOrderList = this->negZOrderList()) {
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = negZOrderList->at(i);
if (!curLayer->isComposited()) {
- IntRect childUnionBounds = calculateLayerBounds(curLayer, layer, descendantFlags);
+ IntRect childUnionBounds = curLayer->calculateLayerBounds(this, 0, descendantFlags);
unionBounds.unite(childUnionBounds);
}
}
}
- if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ if (Vector<RenderLayer*>* posZOrderList = this->posZOrderList()) {
size_t listSize = posZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = posZOrderList->at(i);
if (!curLayer->isComposited()) {
- IntRect childUnionBounds = calculateLayerBounds(curLayer, layer, descendantFlags);
+ IntRect childUnionBounds = curLayer->calculateLayerBounds(this, 0, descendantFlags);
unionBounds.unite(childUnionBounds);
}
}
}
- if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ if (Vector<RenderLayer*>* normalFlowList = this->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = normalFlowList->at(i);
if (!curLayer->isComposited()) {
- IntRect curAbsBounds = calculateLayerBounds(curLayer, layer, descendantFlags);
+ IntRect curAbsBounds = curLayer->calculateLayerBounds(this, 0, descendantFlags);
unionBounds.unite(curAbsBounds);
}
}
@@ -4471,25 +4609,28 @@ IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const Render
// FIXME: We can optimize the size of the composited layers, by not enlarging
// filtered areas with the outsets if we know that the filter is going to render in hardware.
// https://bugs.webkit.org/show_bug.cgi?id=81239
- if ((flags & IncludeLayerFilterOutsets) && layer->renderer()->style()->hasFilterOutsets()) {
+ if ((flags & IncludeLayerFilterOutsets) && renderer->style()->hasFilterOutsets()) {
int topOutset;
int rightOutset;
int bottomOutset;
int leftOutset;
- layer->renderer()->style()->getFilterOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
+ renderer->style()->getFilterOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
unionBounds.move(-leftOutset, -topOutset);
unionBounds.expand(leftOutset + rightOutset, topOutset + bottomOutset);
}
#endif
- if ((flags & IncludeSelfTransform) && layer->paintsWithTransform(PaintBehaviorNormal)) {
- TransformationMatrix* affineTrans = layer->transform();
+ if ((flags & IncludeSelfTransform) && paintsWithTransform(PaintBehaviorNormal)) {
+ TransformationMatrix* affineTrans = transform();
boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
unionBounds = affineTrans->mapRect(unionBounds);
}
LayoutPoint ancestorRelOffset;
- layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
+ if (offsetFromRoot)
+ ancestorRelOffset = *offsetFromRoot;
+ else
+ convertToLayerCoords(ancestorLayer, ancestorRelOffset);
unionBounds.moveBy(ancestorRelOffset);
return pixelSnappedIntRect(unionBounds);
@@ -4662,6 +4803,21 @@ void RenderLayer::rebuildZOrderLists()
if (m_negZOrderList)
std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
+#if ENABLE(DIALOG_ELEMENT)
+ // Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes.
+ // The renderers of top layer elements are children of the view, sorted in top layer stacking order.
+ if (isRootLayer()) {
+ RenderObject* view = renderer()->view();
+ for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) {
+ Element* childElement = child->node()->isElementNode() ? toElement(child->node()) : 0;
+ if (childElement && childElement->isInTopLayer()) {
+ RenderLayer* layer = toRenderLayerModelObject(child)->layer();
+ m_posZOrderList->append(layer);
+ }
+ }
+ }
+#endif
+
m_zOrderListsDirty = false;
}
@@ -4686,6 +4842,11 @@ void RenderLayer::updateNormalFlowList()
void RenderLayer::collectLayers(bool includeHiddenLayers, Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
{
+#if ENABLE(DIALOG_ELEMENT)
+ if (isInTopLayer())
+ return;
+#endif
+
updateDescendantDependentFlags();
// Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
@@ -5201,6 +5362,9 @@ void RenderLayer::updateOrRemoveFilterEffectRenderer()
RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
filterRenderer->setRenderingMode(renderingMode);
filterInfo->setRenderer(filterRenderer.release());
+
+ // We can optimize away code paths in other places if we know that there are no software filters.
+ renderer()->document()->view()->setHasSoftwareFilters(true);
}
// If the filter fails to build, remove it from the layer. It will still attempt to
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 7fe448afc..19d52968c 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved.
*
* Portions are Copyright (C) 1998 Netscape Communications Corporation.
*
@@ -62,6 +62,7 @@ class FilterOperations;
class HitTestRequest;
class HitTestResult;
class HitTestingTransformState;
+class RenderGeometryMap;
class RenderMarquee;
class RenderReplica;
class RenderScrollbarPart;
@@ -237,6 +238,7 @@ public:
for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
m_clipRectsRoot[i] = 0;
m_respectingOverflowClip[i] = false;
+ m_scrollbarRelevancy[i] = IgnoreOverlayScrollbarSize;
}
#endif
}
@@ -245,6 +247,7 @@ public:
#ifndef NDEBUG
const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
bool m_respectingOverflowClip[NumCachedClipRectsTypes];
+ OverlayScrollbarSizeRelevancy m_scrollbarRelevancy[NumCachedClipRectsTypes];
#endif
};
@@ -388,7 +391,7 @@ public:
bool canRender3DTransforms() const;
void updateLayerPosition();
-
+
enum UpdateLayerPositionsFlag {
CheckForRepaint = 1,
IsCompositingUpdateRoot = 1 << 1,
@@ -397,9 +400,9 @@ public:
};
typedef unsigned UpdateLayerPositionsFlags;
static const UpdateLayerPositionsFlags defaultFlags = CheckForRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers;
- // Providing |cachedOffset| prevents a outlineBoxForRepaint from walking back to the root for each layer in our subtree.
- // This is an optimistic optimization that is not guaranteed to succeed.
- void updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerPositionsFlags = defaultFlags);
+
+ void updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags);
+ void updateLayerPositionsAfterScroll();
bool isPaginated() const { return m_isPaginated; }
@@ -488,7 +491,7 @@ public:
bool canUseConvertToLayerCoords() const
{
// These RenderObject have an impact on their layers' without them knowing about it.
- return !renderer()->hasColumns() && !renderer()->hasTransform() && !isComposited()
+ return !renderer()->hasColumns() && !renderer()->hasTransform()
#if ENABLE(SVG)
&& !renderer()->isSVGRoot()
#endif
@@ -525,33 +528,53 @@ public:
RenderRegion* = 0, PaintLayerFlags = 0);
bool hitTest(const HitTestRequest&, HitTestResult&);
bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
- void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior, RenderObject* paintingRoot);
+ void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior, RenderObject* paintingRoot = 0);
enum ShouldRespectOverflowClip { IgnoreOverflowClip, RespectOverflowClip };
+ struct ClipRectsContext {
+ ClipRectsContext(const RenderLayer* inRootLayer, RenderRegion* inRegion, ClipRectsType inClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip inRespectOverflowClip = RespectOverflowClip)
+ : rootLayer(inRootLayer)
+ , region(inRegion)
+ , clipRectsType(inClipRectsType)
+ , overlayScrollbarSizeRelevancy(inOverlayScrollbarSizeRelevancy)
+ , respectOverflowClip(inRespectOverflowClip)
+ { }
+ const RenderLayer* rootLayer;
+ RenderRegion* region;
+ ClipRectsType clipRectsType;
+ OverlayScrollbarSizeRelevancy overlayScrollbarSizeRelevancy;
+ ShouldRespectOverflowClip 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, ShouldRespectOverflowClip = RespectOverflowClip) const;
+ // Pass offsetFromRoot if known.
+ void calculateRects(const ClipRectsContext&, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+ ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot = 0) const;
// Compute and cache clip rects computed with the given layer as the root
- void updateClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRectsType, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip);
+ void updateClipRects(const ClipRectsContext&);
// 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, ShouldRespectOverflowClip = RespectOverflowClip) const;
+ void calculateClipRects(const ClipRectsContext&, ClipRects&) const;
- ClipRects* clipRects(ClipRectsType type) const { ASSERT(type < NumCachedClipRectsTypes); return m_clipRectsCache ? m_clipRectsCache->m_clipRects[type].get() : 0; }
+ ClipRects* clipRects(ClipRectsType type) const
+ {
+ ASSERT(type < NumCachedClipRectsTypes);
+ return m_clipRectsCache ? m_clipRectsCache->m_clipRects[type].get() : 0;
+ }
LayoutRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
LayoutRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
LayoutRect localClipRect() const; // Returns the background clip rect of the layer in the local coordinate space.
- bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer) const;
+ // Pass offsetFromRoot if known.
+ bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0) const;
- // Bounding box relative to some ancestor layer.
- LayoutRect boundingBox(const RenderLayer* rootLayer) const;
+ // Bounding box relative to some ancestor layer. Pass offsetFromRoot if known.
+ LayoutRect boundingBox(const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0) const;
// Bounding box in the coordinates of this layer.
LayoutRect localBoundingBox() const;
// Pixel snapped bounding box relative to the root.
@@ -565,7 +588,8 @@ public:
DefaultCalculateLayerBoundsFlags = IncludeSelfTransform | UseLocalClipRectIfPossible | IncludeLayerFilterOutsets
};
typedef unsigned CalculateLayerBoundsFlags;
- static IntRect calculateLayerBounds(const RenderLayer*, const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags = DefaultCalculateLayerBoundsFlags);
+ // Can pass offsetFromRoot if known.
+ IntRect calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot = 0, CalculateLayerBoundsFlags = DefaultCalculateLayerBoundsFlags) const;
// WARNING: This method returns the offset for the parent as this is what updateLayerPositions expects.
LayoutPoint computeOffsetFromRoot(bool& hasLayerOffset) const;
@@ -574,14 +598,6 @@ public:
LayoutRect repaintRect() const { return m_repaintRect; }
LayoutRect repaintRectIncludingNonCompositingDescendants() const;
- enum UpdateLayerPositionsAfterScrollFlag {
- NoFlag = 0,
- HasSeenViewportConstrainedAncestor = 1 << 0,
- HasSeenAncestorWithOverflowClip = 1 << 1
- };
-
- typedef unsigned UpdateLayerPositionsAfterScrollFlags;
- void updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags = NoFlag);
void setRepaintStatus(RepaintStatus status) { m_repaintStatus = status; }
LayoutUnit staticInlinePosition() const { return m_staticInlinePosition; }
@@ -686,6 +702,11 @@ public:
Node* enclosingElement() const;
+#if ENABLE(DIALOG_ELEMENT)
+ bool isInTopLayer() const;
+ bool isInTopLayerSubtree() const;
+#endif
+
private:
void updateZOrderLists();
void rebuildZOrderLists();
@@ -699,7 +720,7 @@ private:
void setAncestorChainHasSelfPaintingLayerDescendant();
void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
- void computeRepaintRects(LayoutPoint* offsetFromRoot = 0);
+ void computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* = 0);
void computeRepaintRectsIncludingDescendants();
void clearRepaintRects();
@@ -715,6 +736,16 @@ private:
void updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle);
void updateScrollbarsAfterLayout();
+ void updateLayerPositions(RenderGeometryMap* = 0, UpdateLayerPositionsFlags = defaultFlags);
+
+ enum UpdateLayerPositionsAfterScrollFlag {
+ NoFlag = 0,
+ HasSeenViewportConstrainedAncestor = 1 << 0,
+ HasSeenAncestorWithOverflowClip = 1 << 1
+ };
+ typedef unsigned UpdateLayerPositionsAfterScrollFlags;
+ void updateLayerPositionsAfterScroll(RenderGeometryMap*, UpdateLayerPositionsAfterScrollFlags = NoFlag);
+
friend IntSize RenderBox::scrolledContentOffset() const;
IntSize scrolledContentOffset() const { return m_scrollOffset; }
@@ -737,27 +768,31 @@ private:
void updateCompositingAndLayerListsIfNeeded();
- void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation,
- PaintBehavior, RenderObject* paintingRoot, RenderRegion* = 0, OverlapTestRequestMap* = 0,
- PaintLayerFlags = 0);
- void paintLayerContentsAndReflection(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation,
- PaintBehavior, RenderObject* paintingRoot, RenderRegion* = 0, OverlapTestRequestMap* = 0,
- PaintLayerFlags = 0);
- void paintLayerContents(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation,
- PaintBehavior, RenderObject* paintingRoot, RenderRegion* = 0, OverlapTestRequestMap* = 0,
- PaintLayerFlags = 0);
- void paintList(Vector<RenderLayer*>*, RenderLayer* rootLayer, GraphicsContext* p,
- const LayoutRect& paintDirtyRect, PaintBehavior,
- RenderObject* paintingRoot, RenderRegion*, OverlapTestRequestMap*,
- PaintLayerFlags);
- void paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext*,
- const LayoutRect& paintDirtyRect, PaintBehavior,
- RenderObject* paintingRoot, RenderRegion*, OverlapTestRequestMap*,
- PaintLayerFlags);
- void paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext*,
- const LayoutRect& paintDirtyRect, PaintBehavior,
- RenderObject* paintingRoot, RenderRegion*, OverlapTestRequestMap*,
- PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
+ struct LayerPaintingInfo {
+ LayerPaintingInfo(RenderLayer* inRootLayer, const LayoutRect& inDirtyRect, PaintBehavior inPaintBehavior, const LayoutSize& inSubPixelAccumulation, RenderObject* inPaintingRoot = 0, RenderRegion*inRegion = 0, OverlapTestRequestMap* inOverlapTestRequests = 0)
+ : rootLayer(inRootLayer)
+ , paintingRoot(inPaintingRoot)
+ , paintDirtyRect(inDirtyRect)
+ , subPixelAccumulation(inSubPixelAccumulation)
+ , region(inRegion)
+ , overlapTestRequests(inOverlapTestRequests)
+ , paintBehavior(inPaintBehavior)
+ { }
+ RenderLayer* rootLayer;
+ RenderObject* paintingRoot; // only paint descendants of this object
+ LayoutRect paintDirtyRect; // relative to rootLayer;
+ LayoutSize subPixelAccumulation;
+ RenderRegion* region; // May be null.
+ OverlapTestRequestMap* overlapTestRequests; // May be null.
+ PaintBehavior paintBehavior;
+ };
+
+ void paintLayer(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+ void paintLayerContentsAndReflection(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+ void paintLayerContents(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+ void paintList(Vector<RenderLayer*>*, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+ void paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+ void paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
const LayoutRect& hitTestRect, const HitTestLocation&, bool appliedTransform,
@@ -851,8 +886,9 @@ private:
void updateOrRemoveFilterEffectRenderer();
#endif
- 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;
+ void parentClipRects(const ClipRectsContext&, ClipRects&) const;
+ ClipRect backgroundClipRect(const ClipRectsContext&) const;
+
LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
RenderLayer* enclosingTransformedAncestor() const;
@@ -899,9 +935,14 @@ private:
LayoutUnit overflowLeft() const;
LayoutUnit overflowRight() const;
+ IntRect rectForHorizontalScrollbar(const IntRect& borderBoxRect) const;
+ IntRect rectForVerticalScrollbar(const IntRect& borderBoxRect) const;
+
LayoutUnit verticalScrollbarStart(int minX, int maxX) const;
LayoutUnit horizontalScrollbarStart(int minX) const;
+ bool overflowControlsIntersectRect(const IntRect& localRect) const;
+
protected:
// The bitfields are up here so they will fall into the padding from ScrollableArea on 64-bit.
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 1f2a647f5..88be08dfe 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -221,11 +221,22 @@ void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaint
m_maskLayer->setShowRepaintCounter(showRepaintCounter);
}
+ if (m_layerForHorizontalScrollbar)
+ m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
+
+ if (m_layerForVerticalScrollbar)
+ m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
+
+ if (m_layerForScrollCorner)
+ m_layerForScrollCorner->setShowDebugBorder(showBorder);
+
if (m_scrollingLayer)
m_scrollingLayer->setShowDebugBorder(showBorder);
- if (m_scrollingContentsLayer)
+ if (m_scrollingContentsLayer) {
m_scrollingContentsLayer->setShowDebugBorder(showBorder);
+ m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter);
+ }
}
void RenderLayerBacking::createPrimaryGraphicsLayer()
@@ -370,7 +381,7 @@ void RenderLayerBacking::updateCompositedBounds()
LayoutRect clippingBounds = view->unscaledDocumentRect();
if (m_owningLayer != rootLayer)
- clippingBounds.intersect(m_owningLayer->backgroundClipRect(rootLayer, 0, AbsoluteClipRects).rect()); // FIXME: Incorrect for CSS regions.
+ clippingBounds.intersect(m_owningLayer->backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
LayoutPoint delta;
m_owningLayer->convertToLayerCoords(rootLayer, delta);
@@ -609,7 +620,8 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
// 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, IgnoreOverlayScrollbarSize, RenderLayer::IgnoreOverflowClip).rect()); // FIXME: Incorrect for CSS regions.
+ RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, RenderLayer::IgnoreOverflowClip);
+ IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions.
ASSERT(parentClipRect != PaintInfo::infiniteRect());
m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
m_ancestorClippingLayer->setSize(parentClipRect.size());
@@ -742,9 +754,8 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
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_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
}
m_graphicsLayer->setContentsRect(contentsBox());
@@ -1303,8 +1314,14 @@ bool RenderLayerBacking::isDirectlyCompositedImage() const
RenderImage* imageRenderer = toRenderImage(renderObject);
if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
- if (cachedImage->hasImage())
- return cachedImage->imageForRenderer(imageRenderer)->isBitmapImage();
+ if (!cachedImage->hasImage())
+ return false;
+
+ Image* image = cachedImage->imageForRenderer(imageRenderer);
+ if (!image->isBitmapImage())
+ return false;
+
+ return m_graphicsLayer->shouldDirectlyCompositeImage(image);
}
return false;
@@ -1505,8 +1522,7 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
const IntRect& paintDirtyRect, // In the coords of rootLayer.
- PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase,
- RenderObject* paintingRoot)
+ PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
{
if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
ASSERT_NOT_REACHED();
@@ -1526,10 +1542,11 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
// FIXME: GraphicsLayers need a way to split for RenderRegions.
- m_owningLayer->paintLayerContents(rootLayer, context, paintDirtyRect, LayoutSize(), paintBehavior, paintingRoot, 0, 0, paintFlags);
+ RenderLayer::LayerPaintingInfo paintingInfo(rootLayer, paintDirtyRect, paintBehavior, LayoutSize());
+ m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags);
if (m_owningLayer->containsDirtyOverlayScrollbars())
- m_owningLayer->paintOverlayScrollbars(context, paintDirtyRect, paintBehavior, paintingRoot);
+ m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
ASSERT(!m_owningLayer->m_usedTransparency);
}
@@ -1565,7 +1582,7 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
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());
+ paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
if (m_usingTiledCacheLayer)
m_owningLayer->renderer()->frame()->view()->setLastPaintTime(currentTime());
diff --git a/Source/WebCore/rendering/RenderLayerBacking.h b/Source/WebCore/rendering/RenderLayerBacking.h
index 39f6ac594..cdcc030c2 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.h
+++ b/Source/WebCore/rendering/RenderLayerBacking.h
@@ -247,7 +247,7 @@ private:
bool hasTileCacheFlatteningLayer() const { return (m_containmentLayer && m_usingTiledCacheLayer); }
GraphicsLayer* tileCacheFlatteningLayer() const { return m_usingTiledCacheLayer ? m_containmentLayer.get() : 0; }
- void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
+ void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase);
static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID);
static AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID);
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index f026d02d6..870bf1ddf 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -83,6 +83,7 @@ class RenderLayerCompositor::OverlapMap {
WTF_MAKE_NONCOPYABLE(OverlapMap);
public:
OverlapMap()
+ : m_geometryMap(UseTransforms)
{
// Begin assuming the root layer will be composited so that there is
// something on the stack. The root layer should also never get an
@@ -259,11 +260,23 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
setCompositingLayersNeedRebuild();
+ bool debugBordersChanged = m_showDebugBorders != showDebugBorders;
m_hasAcceleratedCompositing = hasAcceleratedCompositing;
m_showDebugBorders = showDebugBorders;
m_showRepaintCounter = showRepaintCounter;
m_forceCompositingMode = forceCompositingMode;
m_acceleratedDrawingEnabled = acceleratedDrawingEnabled;
+
+ if (debugBordersChanged) {
+ if (m_layerForHorizontalScrollbar)
+ m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
+
+ if (m_layerForVerticalScrollbar)
+ m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
+
+ if (m_layerForScrollCorner)
+ m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
+ }
}
bool RenderLayerCompositor::canRender3DTransforms() const
@@ -665,7 +678,7 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
{
if (!canBeComposited(layer))
return IntRect();
- return RenderLayer::calculateLayerBounds(layer, ancestorLayer, RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants);
+ return layer->calculateLayerBounds(ancestorLayer, 0, RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants);
}
void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
@@ -710,7 +723,7 @@ void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer*
boundsComputed = true;
}
- IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(rootRenderLayer(), 0, AbsoluteClipRects).rect()); // FIXME: Incorrect for CSS regions.
+ IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(RenderLayer::ClipRectsContext(rootRenderLayer(), 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
clipRect.scale(pageScaleFactor());
clipRect.intersect(layerBounds);
overlapMap.add(layer, clipRect);
@@ -1710,7 +1723,7 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
if (!computeClipRoot || computeClipRoot == layer)
return false;
- return layer->backgroundClipRect(computeClipRoot, 0, TemporaryClipRects).rect() != PaintInfo::infiniteRect(); // FIXME: Incorrect for CSS regions.
+ return layer->backgroundClipRect(RenderLayer::ClipRectsContext(computeClipRoot, 0, TemporaryClipRects)).rect() != PaintInfo::infiniteRect(); // FIXME: Incorrect for CSS regions.
}
// Return true if the given layer is a stacking context and has compositing child
@@ -2213,6 +2226,7 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
if (requiresHorizontalScrollbarLayer()) {
if (!m_layerForHorizontalScrollbar) {
m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
#ifndef NDEBUG
m_layerForHorizontalScrollbar->setName("horizontal scrollbar");
#endif
@@ -2235,6 +2249,7 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
if (requiresVerticalScrollbarLayer()) {
if (!m_layerForVerticalScrollbar) {
m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
#ifndef NDEBUG
m_layerForVerticalScrollbar->setName("vertical scrollbar");
#endif
@@ -2257,6 +2272,7 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
if (requiresScrollCornerLayer()) {
if (!m_layerForScrollCorner) {
m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
#ifndef NDEBUG
m_layerForScrollCorner->setName("scroll corner");
#endif
@@ -2590,7 +2606,9 @@ const FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewpo
ASSERT(layer->isComposited());
FrameView* frameView = m_renderView->frameView();
+
LayoutRect viewportRect = frameView->visibleContentRect();
+ viewportRect.setLocation(toPoint(frameView->scrollOffsetForFixedPosition()));
FixedPositionViewportConstraints constraints = FixedPositionViewportConstraints();
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.cpp b/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
index 190de61be..6e25d573c 100644
--- a/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
+++ b/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
@@ -130,7 +130,7 @@ void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations&
if (filterOperation->getOperationType() != FilterOperation::REFERENCE)
continue;
ReferenceFilterOperation* referenceFilterOperation = static_cast<ReferenceFilterOperation*>(filterOperation.get());
- CachedSVGDocumentReference* documentReference = static_cast<CachedSVGDocumentReference*>(referenceFilterOperation->data());
+ CachedSVGDocumentReference* documentReference = referenceFilterOperation->cachedSVGDocumentReference();
CachedSVGDocument* cachedSVGDocument = documentReference ? documentReference->document() : 0;
if (cachedSVGDocument) {
diff --git a/Source/WebCore/rendering/RenderMediaControls.cpp b/Source/WebCore/rendering/RenderMediaControls.cpp
index cfaed5e79..f17647b0b 100644
--- a/Source/WebCore/rendering/RenderMediaControls.cpp
+++ b/Source/WebCore/rendering/RenderMediaControls.cpp
@@ -197,9 +197,11 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R
ASSERT_NOT_REACHED();
case MediaTextTrackDisplayContainer:
case MediaTextTrackDisplay:
+ case MediaClosedCaptionsContainer:
+ case MediaClosedCaptionsTrackList:
ASSERT_NOT_REACHED();
break;
-}
+ }
return false;
}
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
index 38a4e5a3e..0451fbdd2 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
@@ -383,6 +383,8 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType
case MediaTextTrackDisplay:
case MediaFullScreenVolumeSlider:
case MediaFullScreenVolumeSliderThumb:
+ case MediaClosedCaptionsContainer:
+ case MediaClosedCaptionsTrackList:
ASSERT_NOT_REACHED();
break;
}
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 983aced4e..15dcdd058 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -1280,10 +1280,12 @@ RenderLayerModelObject* RenderObject::containerForRepaint() const
#endif
#if ENABLE(CSS_FILTERS)
- if (RenderLayer* parentLayer = enclosingLayer()) {
- RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
- if (enclosingFilterLayer)
- return enclosingFilterLayer->renderer();
+ if (document()->view()->hasSoftwareFilters()) {
+ if (RenderLayer* parentLayer = enclosingLayer()) {
+ RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
+ if (enclosingFilterLayer)
+ return enclosingFilterLayer->renderer();
+ }
}
#endif
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index b1f541f91..118a996af 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -981,7 +981,7 @@ protected:
virtual void willBeDestroyed();
void arenaDelete(RenderArena*, void* objectBase);
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, LayoutPoint* /*cachedOffsetToRepaintContainer*/ = 0) const { return LayoutRect(); }
+ virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap* = 0) const { return LayoutRect(); }
virtual bool canBeReplacedWithInlineRunIn() const;
diff --git a/Source/WebCore/rendering/RenderRegion.cpp b/Source/WebCore/rendering/RenderRegion.cpp
index 9ef649dd9..ce0b9d4f9 100644
--- a/Source/WebCore/rendering/RenderRegion.cpp
+++ b/Source/WebCore/rendering/RenderRegion.cpp
@@ -607,6 +607,7 @@ void RenderRegion::updateLogicalHeight()
return;
LayoutUnit newLogicalHeight = overrideLogicalContentHeight() + borderAndPaddingLogicalHeight();
+ ASSERT(newLogicalHeight < LayoutUnit::max() / 2);
if (newLogicalHeight > logicalHeight())
setLogicalHeight(newLogicalHeight);
}
diff --git a/Source/WebCore/rendering/RenderReplica.cpp b/Source/WebCore/rendering/RenderReplica.cpp
index ad3acf0ba..c10bdcaf3 100644
--- a/Source/WebCore/rendering/RenderReplica.cpp
+++ b/Source/WebCore/rendering/RenderReplica.cpp
@@ -68,14 +68,14 @@ void RenderReplica::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
LayoutPoint adjustedPaintOffset = paintOffset + location();
- if (paintInfo.phase == PaintPhaseForeground)
+ if (paintInfo.phase == PaintPhaseForeground) {
// Turn around and paint the parent layer. Use temporary clipRects, so that the layer doesn't end up caching clip rects
// computing using the wrong rootLayer
- layer()->parent()->paintLayer(layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor(),
- paintInfo.context, paintInfo.rect, LayoutSize(),
- PaintBehaviorNormal, 0, paintInfo.renderRegion, 0,
- RenderLayer::PaintLayerHaveTransparency | RenderLayer::PaintLayerAppliedTransform | RenderLayer::PaintLayerTemporaryClipRects | RenderLayer::PaintLayerPaintingReflection);
- else if (paintInfo.phase == PaintPhaseMask)
+ RenderLayer* rootPaintingLayer = layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor();
+ RenderLayer::LayerPaintingInfo paintingInfo(rootPaintingLayer, paintInfo.rect, PaintBehaviorNormal, LayoutSize(), 0, paintInfo.renderRegion);
+ RenderLayer::PaintLayerFlags flags = RenderLayer::PaintLayerHaveTransparency | RenderLayer::PaintLayerAppliedTransform | RenderLayer::PaintLayerTemporaryClipRects | RenderLayer::PaintLayerPaintingReflection;
+ layer()->parent()->paintLayer(paintInfo.context, paintingInfo, flags);
+ } else if (paintInfo.phase == PaintPhaseMask)
paintMask(paintInfo, adjustedPaintOffset);
}
diff --git a/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp b/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp
index a7a9f4aee..272f04b93 100644
--- a/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp
+++ b/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp
@@ -37,9 +37,14 @@
namespace WebCore {
+static const int autoStartPlugInSizeThresholdWidth = 1;
+static const int autoStartPlugInSizeThresholdHeight = 1;
+static const int startButtonPadding = 10;
+
RenderSnapshottedPlugIn::RenderSnapshottedPlugIn(HTMLPlugInImageElement* element)
: RenderEmbeddedObject(element)
, m_snapshotResource(RenderImageResource::create())
+ , m_isMouseInButtonRect(false)
{
m_snapshotResource->initialize(this);
}
@@ -79,7 +84,7 @@ void RenderSnapshottedPlugIn::paintReplaced(PaintInfo& paintInfo, const LayoutPo
{
if (plugInImageElement()->displayState() < HTMLPlugInElement::Playing) {
paintReplacedSnapshot(paintInfo, paintOffset);
- theme()->paintPlugInSnapshotOverlay(this, paintInfo, paintOffset);
+ paintButton(paintInfo, paintOffset);
return;
}
@@ -117,6 +122,41 @@ void RenderSnapshottedPlugIn::paintReplacedSnapshot(PaintInfo& paintInfo, const
context->drawImage(image.get(), style()->colorSpace(), alignedRect, CompositeSourceOver, shouldRespectImageOrientation(), useLowQualityScaling);
}
+static Image* startButtonImage()
+{
+ static Image* buttonImage = Image::loadPlatformResource("startButton").leakRef();
+ return buttonImage;
+}
+
+static Image* startButtonPressedImage()
+{
+ static Image* buttonImage = Image::loadPlatformResource("startButtonPressed").leakRef();
+ return buttonImage;
+}
+
+void RenderSnapshottedPlugIn::paintButton(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+ LayoutRect contentRect = contentBoxRect();
+ if (contentRect.isEmpty())
+ return;
+
+ Image* buttonImage = startButtonImage();
+ if (plugInImageElement()->active()) {
+ if (m_isMouseInButtonRect)
+ buttonImage = startButtonPressedImage();
+ } else if (!plugInImageElement()->hovered())
+ return;
+
+ LayoutPoint contentLocation = paintOffset + contentRect.maxXMaxYCorner() - buttonImage->size() - LayoutSize(startButtonPadding, startButtonPadding);
+ paintInfo.context->drawImage(buttonImage, ColorSpaceDeviceRGB, roundedIntPoint(contentLocation), buttonImage->rect());
+}
+
+void RenderSnapshottedPlugIn::repaintButton()
+{
+ // FIXME: This is unfortunate. We should just repaint the button.
+ repaint();
+}
+
CursorDirective RenderSnapshottedPlugIn::getCursor(const LayoutPoint& point, Cursor& overrideCursor) const
{
if (plugInImageElement()->displayState() < HTMLPlugInElement::Playing) {
@@ -132,6 +172,7 @@ void RenderSnapshottedPlugIn::handleEvent(Event* event)
return;
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+
if (event->type() == eventNames().clickEvent && mouseEvent->button() == LeftButton) {
plugInImageElement()->setDisplayState(HTMLPlugInElement::Playing);
if (widget()) {
@@ -140,7 +181,30 @@ void RenderSnapshottedPlugIn::handleEvent(Event* event)
repaint();
}
event->setDefaultHandled();
+ } else if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent)
+ repaintButton();
+ else if (event->type() == eventNames().mousedownEvent) {
+ bool isMouseInButtonRect = m_buttonRect.contains(IntPoint(mouseEvent->offsetX(), mouseEvent->offsetY()));
+ if (isMouseInButtonRect != m_isMouseInButtonRect) {
+ m_isMouseInButtonRect = isMouseInButtonRect;
+ repaintButton();
+ }
}
}
+void RenderSnapshottedPlugIn::layout()
+{
+ RenderEmbeddedObject::layout();
+ if (plugInImageElement()->displayState() < HTMLPlugInElement::Playing) {
+ LayoutRect rect = contentBoxRect();
+ int width = rect.width();
+ int height = rect.height();
+ if (!width || !height || (width <= autoStartPlugInSizeThresholdWidth && height <= autoStartPlugInSizeThresholdHeight))
+ plugInImageElement()->setDisplayState(HTMLPlugInElement::Playing);
+ }
+
+ LayoutSize buttonSize = startButtonImage()->size();
+ m_buttonRect = LayoutRect(contentBoxRect().maxXMaxYCorner() - LayoutSize(startButtonPadding, startButtonPadding) - buttonSize, buttonSize);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderSnapshottedPlugIn.h b/Source/WebCore/rendering/RenderSnapshottedPlugIn.h
index 6a13a3a3f..2a1f896c7 100644
--- a/Source/WebCore/rendering/RenderSnapshottedPlugIn.h
+++ b/Source/WebCore/rendering/RenderSnapshottedPlugIn.h
@@ -52,9 +52,16 @@ private:
virtual bool isSnapshottedPlugIn() const OVERRIDE { return true; }
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
+
void paintReplacedSnapshot(PaintInfo&, const LayoutPoint&);
+ void paintButton(PaintInfo&, const LayoutPoint&);
+ void repaintButton();
+
+ virtual void layout() OVERRIDE;
OwnPtr<RenderImageResource> m_snapshotResource;
+ LayoutRect m_buttonRect;
+ bool m_isMouseInButtonRect;
};
inline RenderSnapshottedPlugIn* toRenderSnapshottedPlugIn(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 887b65c0d..7527c47a9 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -318,7 +318,7 @@ LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& st
// HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
LayoutUnit borders = 0;
bool isCSSTable = !node() || !node()->hasTagName(tableTag);
- if (isCSSTable && styleLogicalWidth.isFixed() && styleLogicalWidth.isPositive()) {
+ if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) {
recalcBordersInRowDirection();
if (style()->boxSizing() == CONTENT_BOX)
borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
diff --git a/Source/WebCore/rendering/RenderTextControlMultiLine.cpp b/Source/WebCore/rendering/RenderTextControlMultiLine.cpp
index 92d002829..f40994326 100644
--- a/Source/WebCore/rendering/RenderTextControlMultiLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -59,7 +59,7 @@ float RenderTextControlMultiLine::getAvgCharWidth(AtomicString family)
// Since Lucida Grande is the default font, we want this to match the width
// of Courier New, the default font for textareas in IE, Firefox and Safari Win.
// 1229 is the avgCharWidth value in the OS/2 table for Courier New.
- if (family == AtomicString("Lucida Grande"))
+ if (family == "Lucida Grande")
return scaleEmToUnits(1229);
return RenderTextControl::getAvgCharWidth(family);
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
index 967fb2acc..c7f075a4b 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -283,7 +283,7 @@ float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family)
// of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
// IE for some encodings (in IE, the default font is encoding specific).
// 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg.
- if (family == AtomicString("Lucida Grande"))
+ if (family == "Lucida Grande")
return scaleEmToUnits(901);
return RenderTextControl::getAvgCharWidth(family);
@@ -304,7 +304,7 @@ LayoutUnit RenderTextControlSingleLine::preferredContentWidth(float charWidth) c
// of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
// IE for some encodings (in IE, the default font is encoding specific).
// 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg.
- if (family == AtomicString("Lucida Grande"))
+ if (family == "Lucida Grande")
maxCharWidth = scaleEmToUnits(4027);
else if (hasValidAvgCharWidth(family))
maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth());
diff --git a/Source/WebCore/rendering/RenderTheme.h b/Source/WebCore/rendering/RenderTheme.h
index b14749318..bbb86e192 100644
--- a/Source/WebCore/rendering/RenderTheme.h
+++ b/Source/WebCore/rendering/RenderTheme.h
@@ -207,6 +207,7 @@ public:
virtual bool usesVerticalVolumeSlider() const { return true; }
virtual double mediaControlsFadeInDuration() { return 0.1; }
virtual double mediaControlsFadeOutDuration() { return 0.3; }
+ virtual double timeWithoutMouseMovementBeforeHidingControls() { return 3.0; }
virtual String formatMediaControlsTime(float time) const;
virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const;
@@ -242,8 +243,6 @@ public:
virtual String fileListDefaultLabel(bool multipleFilesAllowed) const;
virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const;
- virtual void paintPlugInSnapshotOverlay(RenderSnapshottedPlugIn*, const PaintInfo&, const LayoutPoint&) const { }
-
virtual bool shouldOpenPickerWithF4Key() const;
protected:
diff --git a/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp b/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp
index 6e9079535..51f87c5e3 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp
@@ -33,7 +33,6 @@ namespace WebCore {
bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
{
- // FIXME: We still need to support datetime, date, month, week, time, datetime-local.
return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url()
|| type == InputTypeNames::telephone() || type == InputTypeNames::email() || type == InputTypeNames::number()
#if ENABLE(INPUT_TYPE_COLOR)
@@ -42,6 +41,10 @@ bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
#if ENABLE(CALENDAR_PICKER)
|| type == InputTypeNames::date()
#endif
+ || type == InputTypeNames::datetime()
+ || type == InputTypeNames::datetimelocal()
+ || type == InputTypeNames::month()
+ || type == InputTypeNames::week()
|| type == InputTypeNames::time()
|| type == InputTypeNames::range();
}
@@ -49,8 +52,11 @@ bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
bool RenderThemeChromiumCommon::supportsCalendarPicker(const AtomicString& type)
{
- // FIXME: We'd like to support datetime, datetime-local, month, and week too.
- return type == InputTypeNames::date();
+ return type == InputTypeNames::date()
+ || type == InputTypeNames::datetime()
+ || type == InputTypeNames::datetimelocal()
+ || type == InputTypeNames::month()
+ || type == InputTypeNames::week();
}
#endif
diff --git a/Source/WebCore/rendering/RenderThemeChromiumDefault.cpp b/Source/WebCore/rendering/RenderThemeChromiumDefault.cpp
new file mode 100644
index 000000000..d643729ad
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumDefault.cpp
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumDefault.h"
+
+#include "CSSValueKeywords.h"
+#include "Color.h"
+#include "PaintInfo.h"
+#include "PlatformContextSkia.h"
+#include "RenderObject.h"
+#include "RenderProgress.h"
+#include "RenderSlider.h"
+#include "ScrollbarTheme.h"
+#include "UserAgentStyleSheets.h"
+#include <public/Platform.h>
+#include <public/WebRect.h>
+#include <public/default/WebThemeEngine.h>
+
+namespace WebCore {
+
+unsigned RenderThemeChromiumDefault::m_activeSelectionBackgroundColor =
+ 0xff1e90ff;
+unsigned RenderThemeChromiumDefault::m_activeSelectionForegroundColor =
+ Color::black;
+unsigned RenderThemeChromiumDefault::m_inactiveSelectionBackgroundColor =
+ 0xffc8c8c8;
+unsigned RenderThemeChromiumDefault::m_inactiveSelectionForegroundColor =
+ 0xff323232;
+
+double RenderThemeChromiumDefault::m_caretBlinkInterval;
+
+static const unsigned defaultButtonBackgroundColor = 0xffdddddd;
+
+static WebKit::WebThemeEngine::State getWebThemeState(const RenderTheme* theme, const RenderObject* o)
+{
+ if (!theme->isEnabled(o))
+ return WebKit::WebThemeEngine::StateDisabled;
+ if (theme->isPressed(o))
+ return WebKit::WebThemeEngine::StatePressed;
+ if (theme->isHovered(o))
+ return WebKit::WebThemeEngine::StateHover;
+
+ return WebKit::WebThemeEngine::StateNormal;
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumDefault::create()
+{
+ return adoptRef(new RenderThemeChromiumDefault());
+}
+
+// RenderTheme::themeForPage for Android is defined in RenderThemeChromiumAndroid.cpp.
+#if !OS(ANDROID)
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* rt = RenderThemeChromiumDefault::create().leakRef();
+ return rt;
+}
+#endif
+
+RenderThemeChromiumDefault::RenderThemeChromiumDefault()
+{
+ m_caretBlinkInterval = RenderTheme::caretBlinkInterval();
+}
+
+RenderThemeChromiumDefault::~RenderThemeChromiumDefault()
+{
+}
+
+Color RenderThemeChromiumDefault::systemColor(int cssValueId) const
+{
+ static const Color defaultButtonGrayColor(0xffdddddd);
+
+ if (cssValueId == CSSValueButtonface)
+ return defaultButtonGrayColor;
+ return RenderTheme::systemColor(cssValueId);
+}
+
+String RenderThemeChromiumDefault::extraDefaultStyleSheet()
+{
+#if !OS(WINDOWS)
+ return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
+ String(themeChromiumLinuxUserAgentStyleSheet, sizeof(themeChromiumLinuxUserAgentStyleSheet));
+#else
+ return RenderThemeChromiumSkia::extraDefaultStyleSheet();
+#endif
+}
+
+bool RenderThemeChromiumDefault::controlSupportsTints(const RenderObject* o) const
+{
+ return isEnabled(o);
+}
+
+Color RenderThemeChromiumDefault::activeListBoxSelectionBackgroundColor() const
+{
+ return Color(0x28, 0x28, 0x28);
+}
+
+Color RenderThemeChromiumDefault::activeListBoxSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeChromiumDefault::inactiveListBoxSelectionBackgroundColor() const
+{
+ return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumDefault::inactiveListBoxSelectionForegroundColor() const
+{
+ return Color(0x32, 0x32, 0x32);
+}
+
+Color RenderThemeChromiumDefault::platformActiveSelectionBackgroundColor() const
+{
+ return m_activeSelectionBackgroundColor;
+}
+
+Color RenderThemeChromiumDefault::platformInactiveSelectionBackgroundColor() const
+{
+ return m_inactiveSelectionBackgroundColor;
+}
+
+Color RenderThemeChromiumDefault::platformActiveSelectionForegroundColor() const
+{
+ return m_activeSelectionForegroundColor;
+}
+
+Color RenderThemeChromiumDefault::platformInactiveSelectionForegroundColor() const
+{
+ return m_inactiveSelectionForegroundColor;
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+IntSize RenderThemeChromiumDefault::sliderTickSize() const
+{
+ return IntSize(1, 6);
+}
+
+int RenderThemeChromiumDefault::sliderTickOffsetFromTrackCenter() const
+{
+ return -16;
+}
+#endif
+
+void RenderThemeChromiumDefault::adjustSliderThumbSize(RenderStyle* style, Element* element) const
+{
+ IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartSliderThumb);
+
+ if (style->appearance() == SliderThumbHorizontalPart) {
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ } else if (style->appearance() == SliderThumbVerticalPart) {
+ style->setWidth(Length(size.height(), Fixed));
+ style->setHeight(Length(size.width(), Fixed));
+ } else
+ RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
+}
+
+bool RenderThemeChromiumDefault::supportsControlTints() const
+{
+ return true;
+}
+
+void RenderThemeChromiumDefault::setCaretBlinkInterval(double interval)
+{
+ m_caretBlinkInterval = interval;
+}
+
+double RenderThemeChromiumDefault::caretBlinkIntervalInternal() const
+{
+ return m_caretBlinkInterval;
+}
+
+void RenderThemeChromiumDefault::setSelectionColors(
+ unsigned activeBackgroundColor,
+ unsigned activeForegroundColor,
+ unsigned inactiveBackgroundColor,
+ unsigned inactiveForegroundColor)
+{
+ m_activeSelectionBackgroundColor = activeBackgroundColor;
+ m_activeSelectionForegroundColor = activeForegroundColor;
+ m_inactiveSelectionBackgroundColor = inactiveBackgroundColor;
+ m_inactiveSelectionForegroundColor = inactiveForegroundColor;
+}
+
+bool RenderThemeChromiumDefault::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ extraParams.button.checked = isChecked(o);
+ extraParams.button.indeterminate = isIndeterminate(o);
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartCheckbox, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+void RenderThemeChromiumDefault::setCheckboxSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartCheckbox);
+ setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumDefault::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ extraParams.button.checked = isChecked(o);
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartRadio, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+void RenderThemeChromiumDefault::setRadioSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartRadio);
+ setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumDefault::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ extraParams.button.isDefault = isDefault(o);
+ extraParams.button.hasBorder = true;
+ extraParams.button.backgroundColor = defaultButtonBackgroundColor;
+ if (o->hasBackground())
+ extraParams.button.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartButton, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+bool RenderThemeChromiumDefault::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ // WebThemeEngine does not handle border rounded corner and background image
+ // so return true to draw CSS border and background.
+ if (o->style()->hasBorderRadius() || o->style()->hasBackgroundImage())
+ return true;
+
+ ControlPart part = o->style()->appearance();
+
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ extraParams.textField.isTextArea = part == TextAreaPart;
+ extraParams.textField.isListbox = part == ListboxPart;
+
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+
+ // Fallback to white if the specified color object is invalid.
+ Color backgroundColor(Color::white);
+ if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
+ backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+ extraParams.textField.backgroundColor = backgroundColor.rgb();
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartTextField, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+bool RenderThemeChromiumDefault::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ if (!o->isBox())
+ return false;
+
+ const int right = rect.x() + rect.width();
+ const int middle = rect.y() + rect.height() / 2;
+
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
+ extraParams.menuList.arrowY = middle;
+ const RenderBox* box = toRenderBox(o);
+ // Match Chromium Win behaviour of showing all borders if any are shown.
+ extraParams.menuList.hasBorder = box->borderRight() || box->borderLeft() || box->borderTop() || box->borderBottom();
+ extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius();
+ // Fallback to transparent if the specified color object is invalid.
+ extraParams.menuList.backgroundColor = Color::transparent;
+ if (o->hasBackground())
+ extraParams.menuList.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
+
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartMenuList, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+bool RenderThemeChromiumDefault::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ extraParams.slider.vertical = o->style()->appearance() == SliderVerticalPart;
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartSliderTrack, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+
+#if ENABLE(DATALIST_ELEMENT)
+ paintSliderTicks(o, i, rect);
+#endif
+
+ return false;
+}
+
+bool RenderThemeChromiumDefault::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ extraParams.slider.vertical = o->style()->appearance() == SliderThumbVerticalPart;
+ extraParams.slider.inDrag = isPressed(o);
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartSliderThumb, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+void RenderThemeChromiumDefault::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartInnerSpinButton);
+
+ style->setWidth(Length(size.width(), Fixed));
+ style->setMinWidth(Length(size.width(), Fixed));
+}
+
+bool RenderThemeChromiumDefault::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpState);
+ extraParams.innerSpin.readOnly = isReadOnlyControl(o);
+
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartInnerSpinButton, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+#if ENABLE(PROGRESS_ELEMENT)
+
+bool RenderThemeChromiumDefault::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ if (!o->isProgress())
+ return true;
+
+ RenderProgress* renderProgress = toRenderProgress(o);
+ IntRect valueRect = progressValueRectFor(renderProgress, rect);
+
+ WebKit::WebThemeEngine::ExtraParams extraParams;
+ extraParams.progressBar.determinate = renderProgress->isDeterminate();
+ extraParams.progressBar.valueRectX = valueRect.x();
+ extraParams.progressBar.valueRectY = valueRect.y();
+ extraParams.progressBar.valueRectWidth = valueRect.width();
+ extraParams.progressBar.valueRectHeight = valueRect.height();
+
+ DirectionFlippingScope scope(o, i, rect);
+ WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+ WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartProgressBar, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+ return false;
+}
+
+#endif
+
+bool RenderThemeChromiumDefault::shouldOpenPickerWithF4Key() const
+{
+ return true;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumDefault.h b/Source/WebCore/rendering/RenderThemeChromiumDefault.h
new file mode 100644
index 000000000..129b482cb
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumDefault.h
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * All rights reserved.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeChromiumDefault_h
+#define RenderThemeChromiumDefault_h
+
+#include "RenderThemeChromiumSkia.h"
+
+namespace WebCore {
+
+class RenderThemeChromiumDefault : public RenderThemeChromiumSkia {
+public:
+ static PassRefPtr<RenderTheme> create();
+ virtual String extraDefaultStyleSheet();
+
+ virtual Color systemColor(int cssValidId) const;
+
+ // A method asking if the control changes its tint when the window has focus or not.
+ virtual bool controlSupportsTints(const RenderObject*) const;
+
+ // List Box selection color
+ virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color activeListBoxSelectionForegroundColor() const;
+ virtual Color inactiveListBoxSelectionBackgroundColor() const;
+ virtual Color inactiveListBoxSelectionForegroundColor() const;
+
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+
+#if ENABLE(DATALIST_ELEMENT)
+ virtual IntSize sliderTickSize() const OVERRIDE;
+ virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
+#endif
+ virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+
+ static void setCaretBlinkInterval(double);
+ virtual double caretBlinkIntervalInternal() const;
+
+ virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void setCheckboxSize(RenderStyle*) const;
+
+ virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void setRadioSize(RenderStyle*) const;
+
+ virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+ virtual bool popsMenuBySpaceOrReturn() const OVERRIDE { return true; }
+
+#if ENABLE(PROGRESS_ELEMENT)
+ virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
+#endif
+
+ virtual bool shouldOpenPickerWithF4Key() const OVERRIDE;
+
+ static void setSelectionColors(unsigned activeBackgroundColor, unsigned activeForegroundColor, unsigned inactiveBackgroundColor, unsigned inactiveForegroundColor);
+
+protected:
+ RenderThemeChromiumDefault();
+ virtual ~RenderThemeChromiumDefault();
+
+private:
+ // A general method asking if any control tinting is supported at all.
+ virtual bool supportsControlTints() const;
+
+ static double m_caretBlinkInterval;
+
+ static unsigned m_activeSelectionBackgroundColor;
+ static unsigned m_activeSelectionForegroundColor;
+ static unsigned m_inactiveSelectionBackgroundColor;
+ static unsigned m_inactiveSelectionForegroundColor;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumDefault_h
diff --git a/Source/WebCore/rendering/RenderThemeChromiumFontProvider.cpp b/Source/WebCore/rendering/RenderThemeChromiumFontProvider.cpp
new file mode 100644
index 000000000..78068e537
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumFontProvider.cpp
@@ -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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumFontProvider.h"
+
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// The default variable-width font size. We use this as the default font
+// size for the "system font", and as a base size (which we then shrink) for
+// form control fonts.
+// static
+float RenderThemeChromiumFontProvider::s_defaultFontSize = 16.0;
+
+// We aim to match IE here.
+// -IE uses a font based on the encoding as the default font for form controls.
+// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
+// which returns MS Shell Dlg)
+// -Safari uses Lucida Grande.
+//
+// FIXME: The only case where we know we don't match IE is for ANSI encodings.
+// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
+// sizes (e.g. 15px). So, for now we just use Arial.
+const String& RenderThemeChromiumFontProvider::defaultGUIFont()
+{
+ DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Arial")));
+ return fontFace;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumFontProvider.h b/Source/WebCore/rendering/RenderThemeChromiumFontProvider.h
new file mode 100644
index 000000000..0f7eeac27
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumFontProvider.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderThemeChromiumFontProvider_h
+#define RenderThemeChromiumFontProvider_h
+
+namespace WTF {
+class String;
+}
+
+namespace WebCore {
+
+class FontDescription;
+
+class RenderThemeChromiumFontProvider {
+public:
+ static void systemFont(int propId, FontDescription&);
+ static void setDefaultFontSize(int);
+
+protected:
+ static const WTF::String& defaultGUIFont();
+
+ static float s_defaultFontSize;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumFontProvider_h
diff --git a/Source/WebCore/rendering/RenderThemeChromiumFontProviderLinux.cpp b/Source/WebCore/rendering/RenderThemeChromiumFontProviderLinux.cpp
new file mode 100644
index 000000000..009c72417
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumFontProviderLinux.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 COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumFontProvider.h"
+
+#include "CSSValueKeywords.h"
+#include "FontDescription.h"
+
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// static
+void RenderThemeChromiumFontProvider::setDefaultFontSize(int fontSize)
+{
+ s_defaultFontSize = static_cast<float>(fontSize);
+}
+
+// static
+void RenderThemeChromiumFontProvider::systemFont(int propId, FontDescription& fontDescription)
+{
+ float fontSize = s_defaultFontSize;
+
+ switch (propId) {
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ // Why 2 points smaller? Because that's what Gecko does. Note that we
+ // are assuming a 96dpi screen, which is the default that we use on
+ // Windows.
+ static const float pointsPerInch = 72.0f;
+ static const float pixelsPerInch = 96.0f;
+ fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
+ break;
+ }
+
+ fontDescription.firstFamily().setFamily(defaultGUIFont());
+ fontDescription.setSpecifiedSize(fontSize);
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+ fontDescription.setWeight(FontWeightNormal);
+ fontDescription.setItalic(false);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumFontProviderWin.cpp b/Source/WebCore/rendering/RenderThemeChromiumFontProviderWin.cpp
new file mode 100644
index 000000000..faf3c942b
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumFontProviderWin.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumFontProvider.h"
+
+#include "CSSValueKeywords.h"
+#include "FontDescription.h"
+#include "HWndDC.h"
+#include "SystemInfo.h"
+
+#include <windows.h>
+#include <wtf/text/WTFString.h>
+
+#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
+ offsetof(structName, member) + \
+ (sizeof static_cast<structName*>(0)->member)
+#define NONCLIENTMETRICS_SIZE_PRE_VISTA \
+ SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
+
+namespace WebCore {
+
+static FontDescription& smallSystemFont()
+{
+ DEFINE_STATIC_LOCAL(FontDescription, font, ());
+ return font;
+}
+
+static FontDescription& menuFont()
+{
+ DEFINE_STATIC_LOCAL(FontDescription, font, ());
+ return font;
+}
+
+static FontDescription& labelFont()
+{
+ DEFINE_STATIC_LOCAL(FontDescription, font, ());
+ return font;
+}
+
+// Converts |points| to pixels. One point is 1/72 of an inch.
+static float pointsToPixels(float points)
+{
+ static float pixelsPerInch = 0.0f;
+ if (!pixelsPerInch) {
+ HWndDC hdc(0); // What about printing? Is this the right DC?
+ if (hdc) // Can this ever actually be 0?
+ pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
+ else
+ pixelsPerInch = 96.0f;
+ }
+
+ static const float pointsPerInch = 72.0f;
+ return points / pointsPerInch * pixelsPerInch;
+}
+
+static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
+{
+ static UINT size = (windowsVersion() >= WindowsVista) ?
+ sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
+ metrics->cbSize = size;
+ bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
+ ASSERT(success);
+}
+
+// Return the height of system font |font| in pixels. We use this size by
+// default for some non-form-control elements.
+static float systemFontSize(const LOGFONT& font)
+{
+ float size = -font.lfHeight;
+ if (size < 0) {
+ HFONT hFont = CreateFontIndirect(&font);
+ if (hFont) {
+ HWndDC hdc(0); // What about printing? Is this the right DC?
+ if (hdc) {
+ HGDIOBJ hObject = SelectObject(hdc, hFont);
+ TEXTMETRIC tm;
+ GetTextMetrics(hdc, &tm);
+ SelectObject(hdc, hObject);
+ size = tm.tmAscent;
+ }
+ DeleteObject(hFont);
+ }
+ }
+
+ // The "codepage 936" bit here is from Gecko; apparently this helps make
+ // fonts more legible in Simplified Chinese where the default font size is
+ // too small.
+ //
+ // FIXME: http://b/1119883 Since this is only used for "small caption",
+ // "menu", and "status bar" objects, I'm not sure how much this even
+ // matters. Plus the Gecko patch went in back in 2002, and maybe this
+ // isn't even relevant anymore. We should investigate whether this should
+ // be removed, or perhaps broadened to be "any CJK locale".
+ //
+ return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
+}
+
+// static
+void RenderThemeChromiumFontProvider::systemFont(int propId, FontDescription& fontDescription)
+{
+ // This logic owes much to RenderThemeSafari.cpp.
+ FontDescription* cachedDesc = 0;
+ AtomicString faceName;
+ float fontSize = 0;
+ switch (propId) {
+ case CSSValueSmallCaption:
+ cachedDesc = &smallSystemFont();
+ if (!smallSystemFont().isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
+ fontSize = systemFontSize(metrics.lfSmCaptionFont);
+ }
+ break;
+ case CSSValueMenu:
+ cachedDesc = &menuFont();
+ if (!menuFont().isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
+ fontSize = systemFontSize(metrics.lfMenuFont);
+ }
+ break;
+ case CSSValueStatusBar:
+ cachedDesc = &labelFont();
+ if (!labelFont().isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = metrics.lfStatusFont.lfFaceName;
+ fontSize = systemFontSize(metrics.lfStatusFont);
+ }
+ break;
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ faceName = defaultGUIFont();
+ // Why 2 points smaller? Because that's what Gecko does.
+ fontSize = s_defaultFontSize - pointsToPixels(2);
+ break;
+ default:
+ faceName = defaultGUIFont();
+ fontSize = s_defaultFontSize;
+ break;
+ }
+
+ if (!cachedDesc)
+ cachedDesc = &fontDescription;
+
+ if (fontSize) {
+ cachedDesc->firstFamily().setFamily(faceName);
+ cachedDesc->setIsAbsoluteSize(true);
+ cachedDesc->setGenericFamily(FontDescription::NoFamily);
+ cachedDesc->setSpecifiedSize(fontSize);
+ cachedDesc->setWeight(FontWeightNormal);
+ cachedDesc->setItalic(false);
+ }
+ fontDescription = *cachedDesc;
+}
+
+// static
+void RenderThemeChromiumFontProvider::setDefaultFontSize(int fontSize)
+{
+ s_defaultFontSize = static_cast<float>(fontSize);
+
+ // Reset cached fonts.
+ smallSystemFont() = menuFont() = labelFont() = FontDescription();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.h b/Source/WebCore/rendering/RenderThemeChromiumMac.h
index 1f5a81484..5acd13af5 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.h
@@ -25,11 +25,11 @@
#define RenderThemeChromiumMac_h
#import "RenderThemeChromiumCommon.h"
-#import "RenderThemeMac.h"
+#import "RenderThemeMacShared.h"
namespace WebCore {
-class RenderThemeChromiumMac : public RenderThemeMac {
+class RenderThemeChromiumMac : public RenderThemeMacShared {
public:
static PassRefPtr<RenderTheme> create();
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.mm b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
index 56d9ea607..91fe6ba66 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.mm
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -99,7 +99,7 @@ int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const
if (style->appearance() == TextFieldPart)
return autofillPopupHorizontalPadding;
- return RenderThemeMac::popupInternalPaddingLeft(style);
+ return RenderThemeMacShared::popupInternalPaddingLeft(style);
}
int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const
@@ -107,7 +107,7 @@ int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const
if (style->appearance() == TextFieldPart)
return autofillPopupHorizontalPadding;
- return RenderThemeMac::popupInternalPaddingRight(style);
+ return RenderThemeMacShared::popupInternalPaddingRight(style);
}
// Updates the control tint (a.k.a. active state) of |cell| (from |o|).
@@ -171,7 +171,7 @@ String RenderThemeChromiumMac::extraFullScreenStyleSheet()
String RenderThemeChromiumMac::extraDefaultStyleSheet()
{
- return RenderThemeMac::extraDefaultStyleSheet() +
+ return RenderThemeMacShared::extraDefaultStyleSheet() +
String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet));
}
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
index 4e504cab4..968423d81 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -39,6 +39,7 @@
#include "RenderObject.h"
#include "RenderProgress.h"
#include "RenderSlider.h"
+#include "RenderThemeChromiumFontProvider.h"
#include "ScrollbarTheme.h"
#include "TimeRanges.h"
#include "TransformationMatrix.h"
@@ -70,23 +71,6 @@ static const float minSearchFieldResultsDecorationSize = 9;
static const float maxSearchFieldResultsDecorationSize = 30;
static const float defaultSearchFieldResultsButtonWidth = 18;
-// We aim to match IE here.
-// -IE uses a font based on the encoding as the default font for form controls.
-// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
-// which returns MS Shell Dlg)
-// -Safari uses Lucida Grande.
-//
-// FIXME: The only case where we know we don't match IE is for ANSI encodings.
-// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
-// sizes (e.g. 15px). So, for now we just use Arial.
-const String& RenderThemeChromiumSkia::defaultGUIFont()
-{
- DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Arial")));
- return fontFace;
-}
-
-float RenderThemeChromiumSkia::defaultFontSize = 16.0;
-
RenderThemeChromiumSkia::RenderThemeChromiumSkia()
{
}
@@ -183,27 +167,7 @@ double RenderThemeChromiumSkia::caretBlinkInterval() const
void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const
{
- float fontSize = defaultFontSize;
-
- switch (propId) {
- case CSSValueWebkitMiniControl:
- case CSSValueWebkitSmallControl:
- case CSSValueWebkitControl:
- // Why 2 points smaller? Because that's what Gecko does. Note that we
- // are assuming a 96dpi screen, which is the default that we use on
- // Windows.
- static const float pointsPerInch = 72.0f;
- static const float pixelsPerInch = 96.0f;
- fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
- break;
- }
-
- fontDescription.firstFamily().setFamily(defaultGUIFont());
- fontDescription.setSpecifiedSize(fontSize);
- fontDescription.setIsAbsoluteSize(true);
- fontDescription.setGenericFamily(FontDescription::NoFamily);
- fontDescription.setWeight(FontWeightNormal);
- fontDescription.setItalic(false);
+ RenderThemeChromiumFontProvider::systemFont(propId, fontDescription);
}
int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
@@ -573,7 +537,7 @@ int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) cons
// static
void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
{
- defaultFontSize = static_cast<float>(fontSize);
+ RenderThemeChromiumFontProvider::setDefaultFontSize(fontSize);
}
double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.h b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
index 87b4e81dd..8dc3a3a36 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
@@ -36,142 +36,142 @@ namespace WebCore {
class RenderProgress;
class RenderThemeChromiumSkia : public RenderTheme {
- public:
- RenderThemeChromiumSkia();
- virtual ~RenderThemeChromiumSkia();
+public:
+ RenderThemeChromiumSkia();
+ virtual ~RenderThemeChromiumSkia();
- virtual String extraDefaultStyleSheet();
- virtual String extraQuirksStyleSheet();
+ virtual String extraDefaultStyleSheet();
+ virtual String extraQuirksStyleSheet();
#if ENABLE(VIDEO)
- virtual String extraMediaControlsStyleSheet();
+ virtual String extraMediaControlsStyleSheet();
+#endif
+
+#if ENABLE(TOUCH_EVENTS)
+ virtual Color platformTapHighlightColor() const OVERRIDE
+ {
+ return Color(defaultTapHighlightColor);
+ }
#endif
- // A method asking if the theme's controls actually care about redrawing when hovered.
- virtual bool supportsHover(const RenderStyle*) const;
+ // A method asking if the theme's controls actually care about redrawing when hovered.
+ virtual bool supportsHover(const RenderStyle*) const;
- // A method asking if the theme is able to draw the focus ring.
- virtual bool supportsFocusRing(const RenderStyle*) const;
+ // A method asking if the theme is able to draw the focus ring.
+ virtual bool supportsFocusRing(const RenderStyle*) const;
- virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
+ virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
#if ENABLE(VIDEO_TRACK)
- virtual bool supportsClosedCaptioning() const OVERRIDE;
+ virtual bool supportsClosedCaptioning() const OVERRIDE;
#endif
- // The platform selection color.
- virtual Color platformActiveSelectionBackgroundColor() const;
- virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color platformActiveSelectionForegroundColor() const;
- virtual Color platformInactiveSelectionForegroundColor() const;
- virtual Color platformFocusRingColor() const;
+ // The platform selection color.
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+ virtual Color platformFocusRingColor() const;
- // To change the blink interval, override caretBlinkIntervalInternal instead of this one so that we may share layout test code an intercepts.
- virtual double caretBlinkInterval() const;
+ // To change the blink interval, override caretBlinkIntervalInternal instead of this one so that we may share layout test code an intercepts.
+ virtual double caretBlinkInterval() const;
- // System fonts.
- virtual void systemFont(int propId, FontDescription&) const;
+ // System fonts.
+ virtual void systemFont(int propId, FontDescription&) const;
- virtual int minimumMenuListSize(RenderStyle*) const;
+ virtual int minimumMenuListSize(RenderStyle*) const;
- virtual void setCheckboxSize(RenderStyle*) const;
+ virtual void setCheckboxSize(RenderStyle*) const;
- virtual void setRadioSize(RenderStyle*) const;
+ virtual void setRadioSize(RenderStyle*) const;
- virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
- virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual String formatMediaControlsTime(float time) const;
- virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
- virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const;
- virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+ virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual String formatMediaControlsTime(float time) const;
+ virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
+ virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const;
+ virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
- // MenuList refers to an unstyled menulist (meaning a menulist without
- // background-color or border set) and MenuListButton refers to a styled
- // menulist (a menulist with background-color or border set). They have
- // this distinction to support showing aqua style themes whenever they
- // possibly can, which is something we don't want to replicate.
- //
- // In short, we either go down the MenuList code path or the MenuListButton
- // codepath. We never go down both. And in both cases, they render the
- // entire menulist.
- virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
+ // MenuList refers to an unstyled menulist (meaning a menulist without
+ // background-color or border set) and MenuListButton refers to a styled
+ // menulist (a menulist with background-color or border set). They have
+ // this distinction to support showing aqua style themes whenever they
+ // possibly can, which is something we don't want to replicate.
+ //
+ // In short, we either go down the MenuList code path or the MenuListButton
+ // codepath. We never go down both. And in both cases, they render the
+ // entire menulist.
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
#if ENABLE(PROGRESS_ELEMENT)
- virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
- virtual double animationDurationForProgressBar(RenderProgress*) const;
+ virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+ virtual double animationDurationForProgressBar(RenderProgress*) const;
#endif
- // These methods define the padding for the MenuList's inner block.
- virtual int popupInternalPaddingLeft(RenderStyle*) const;
- virtual int popupInternalPaddingRight(RenderStyle*) const;
- virtual int popupInternalPaddingTop(RenderStyle*) const;
- virtual int popupInternalPaddingBottom(RenderStyle*) const;
+ // These methods define the padding for the MenuList's inner block.
+ virtual int popupInternalPaddingLeft(RenderStyle*) const;
+ virtual int popupInternalPaddingRight(RenderStyle*) const;
+ virtual int popupInternalPaddingTop(RenderStyle*) const;
+ virtual int popupInternalPaddingBottom(RenderStyle*) const;
#if ENABLE(VIDEO)
- // Media controls
- virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
- virtual bool usesVerticalVolumeSlider() const { return false; }
+ // Media controls
+ virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
+ virtual bool usesVerticalVolumeSlider() const { return false; }
#endif
- // Provide a way to pass the default font size from the Settings object
- // to the render theme. FIXME: http://b/1129186 A cleaner way would be
- // to remove the default font size from this object and have callers
- // that need the value to get it directly from the appropriate Settings
- // object.
- static void setDefaultFontSize(int);
+ // Provide a way to pass the default font size from the Settings object
+ // to the render theme. FIXME: http://b/1129186 A cleaner way would be
+ // to remove the default font size from this object and have callers
+ // that need the value to get it directly from the appropriate Settings
+ // object.
+ static void setDefaultFontSize(int);
- protected:
- static const String& defaultGUIFont();
+protected:
+ virtual double caretBlinkIntervalInternal() const;
- // The default variable-width font size. We use this as the default font
- // size for the "system font", and as a base size (which we then shrink) for
- // form control fonts.
- static float defaultFontSize;
+ virtual int menuListArrowPadding() const;
- virtual double caretBlinkIntervalInternal() const;
+ static void setSizeIfAuto(RenderStyle*, const IntSize&);
- virtual int menuListArrowPadding() const;
+#if ENABLE(PROGRESS_ELEMENT)
+ IntRect determinateProgressValueRectFor(RenderProgress*, const IntRect&) const;
+ IntRect indeterminateProgressValueRectFor(RenderProgress*, const IntRect&) const;
+ IntRect progressValueRectFor(RenderProgress*, const IntRect&) const;
- static void setSizeIfAuto(RenderStyle*, const IntSize&);
+ class DirectionFlippingScope {
+ public:
+ DirectionFlippingScope(RenderObject*, const PaintInfo&, const IntRect&);
+ ~DirectionFlippingScope();
-#if ENABLE(PROGRESS_ELEMENT)
- IntRect determinateProgressValueRectFor(RenderProgress*, const IntRect&) const;
- IntRect indeterminateProgressValueRectFor(RenderProgress*, const IntRect&) const;
- IntRect progressValueRectFor(RenderProgress*, const IntRect&) const;
-
- class DirectionFlippingScope {
- public:
- DirectionFlippingScope(RenderObject*, const PaintInfo&, const IntRect&);
- ~DirectionFlippingScope();
-
- private:
- bool m_needsFlipping;
- const PaintInfo& m_paintInfo;
- };
+ private:
+ bool m_needsFlipping;
+ const PaintInfo& m_paintInfo;
+ };
#endif
private:
@@ -188,6 +188,8 @@ private:
int menuListInternalPadding(RenderStyle*, int paddingType) const;
bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
IntRect convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const;
+
+ static const RGBA32 defaultTapHighlightColor = 0x2e000000; // 18% black.
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
index 04e893f81..709904c59 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -35,7 +35,6 @@
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
-#include "HWndDC.h"
#include "LayoutTestSupport.h"
#include "MediaControlElements.h"
#include "PaintInfo.h"
@@ -43,6 +42,7 @@
#include "RenderBox.h"
#include "RenderProgress.h"
#include "RenderSlider.h"
+#include "RenderThemeChromiumCommon.h"
#include "ScrollbarTheme.h"
#include "SystemInfo.h"
#include "TransparencyWin.h"
@@ -52,12 +52,6 @@
// FIXME: This dependency should eventually be removed.
#include <skia/ext/skia_utils_win.h>
-#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
- offsetof(structName, member) + \
- (sizeof static_cast<structName*>(0)->member)
-#define NONCLIENTMETRICS_SIZE_PRE_VISTA \
- SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
-
namespace WebCore {
// The standard width for the menu list drop-down button when run under
@@ -135,19 +129,6 @@ bool ThemePainter::s_hasInstance = false;
} // namespace
-static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
-{
- static UINT size = (windowsVersion() >= WindowsVista) ?
- sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
- metrics->cbSize = size;
- bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
- ASSERT(success);
-}
-
-static FontDescription smallSystemFont;
-static FontDescription menuFont;
-static FontDescription labelFont;
-
// Internal static helper functions. We don't put them in an anonymous
// namespace so they have easier access to the WebCore namespace.
@@ -166,55 +147,6 @@ static bool supportsFocus(ControlPart appearance)
return false;
}
-// Return the height of system font |font| in pixels. We use this size by
-// default for some non-form-control elements.
-static float systemFontSize(const LOGFONT& font)
-{
- float size = -font.lfHeight;
- if (size < 0) {
- HFONT hFont = CreateFontIndirect(&font);
- if (hFont) {
- HWndDC hdc(0); // What about printing? Is this the right DC?
- if (hdc) {
- HGDIOBJ hObject = SelectObject(hdc, hFont);
- TEXTMETRIC tm;
- GetTextMetrics(hdc, &tm);
- SelectObject(hdc, hObject);
- size = tm.tmAscent;
- }
- DeleteObject(hFont);
- }
- }
-
- // The "codepage 936" bit here is from Gecko; apparently this helps make
- // fonts more legible in Simplified Chinese where the default font size is
- // too small.
- //
- // FIXME: http://b/1119883 Since this is only used for "small caption",
- // "menu", and "status bar" objects, I'm not sure how much this even
- // matters. Plus the Gecko patch went in back in 2002, and maybe this
- // isn't even relevant anymore. We should investigate whether this should
- // be removed, or perhaps broadened to be "any CJK locale".
- //
- return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
-}
-
-// Converts |points| to pixels. One point is 1/72 of an inch.
-static float pointsToPixels(float points)
-{
- static float pixelsPerInch = 0.0f;
- if (!pixelsPerInch) {
- HWndDC hdc(0); // What about printing? Is this the right DC?
- if (hdc) // Can this ever actually be NULL?
- pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
- else
- pixelsPerInch = 96.0f;
- }
-
- static const float pointsPerInch = 72.0f;
- return points / pointsPerInch * pixelsPerInch;
-}
-
static double querySystemBlinkInterval(double defaultInterval)
{
UINT blinkTime = GetCaretBlinkTime();
@@ -285,67 +217,6 @@ Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
return Color(0xff, 0xff, 0x96); // Yellow.
}
-void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescription) const
-{
- // This logic owes much to RenderThemeSafari.cpp.
- FontDescription* cachedDesc = 0;
- AtomicString faceName;
- float fontSize = 0;
- switch (propId) {
- case CSSValueSmallCaption:
- cachedDesc = &smallSystemFont;
- if (!smallSystemFont.isAbsoluteSize()) {
- NONCLIENTMETRICS metrics;
- getNonClientMetrics(&metrics);
- faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
- fontSize = systemFontSize(metrics.lfSmCaptionFont);
- }
- break;
- case CSSValueMenu:
- cachedDesc = &menuFont;
- if (!menuFont.isAbsoluteSize()) {
- NONCLIENTMETRICS metrics;
- getNonClientMetrics(&metrics);
- faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
- fontSize = systemFontSize(metrics.lfMenuFont);
- }
- break;
- case CSSValueStatusBar:
- cachedDesc = &labelFont;
- if (!labelFont.isAbsoluteSize()) {
- NONCLIENTMETRICS metrics;
- getNonClientMetrics(&metrics);
- faceName = metrics.lfStatusFont.lfFaceName;
- fontSize = systemFontSize(metrics.lfStatusFont);
- }
- break;
- case CSSValueWebkitMiniControl:
- case CSSValueWebkitSmallControl:
- case CSSValueWebkitControl:
- faceName = defaultGUIFont();
- // Why 2 points smaller? Because that's what Gecko does.
- fontSize = defaultFontSize - pointsToPixels(2);
- break;
- default:
- faceName = defaultGUIFont();
- fontSize = defaultFontSize;
- break;
- }
-
- if (!cachedDesc)
- cachedDesc = &fontDescription;
-
- if (fontSize) {
- cachedDesc->firstFamily().setFamily(faceName);
- cachedDesc->setIsAbsoluteSize(true);
- cachedDesc->setGenericFamily(FontDescription::NoFamily);
- cachedDesc->setSpecifiedSize(fontSize);
- cachedDesc->setWeight(FontWeightNormal);
- cachedDesc->setItalic(false);
- }
- fontDescription = *cachedDesc;
-}
-
// Map a CSSValue* system color to an index understood by GetSysColor().
static int cssValueIdToSysColorIndex(int cssValueId)
{
@@ -536,15 +407,6 @@ bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i,
return false;
}
-// static
-void RenderThemeChromiumWin::setDefaultFontSize(int fontSize)
-{
- RenderThemeChromiumSkia::setDefaultFontSize(fontSize);
-
- // Reset cached fonts.
- smallSystemFont = menuFont = labelFont = FontDescription();
-}
-
double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
{
// This involves a system call, so we cache the result.
diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.h b/Source/WebCore/rendering/RenderThemeChromiumWin.h
index 85cca45ff..bf335c7b8 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumWin.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumWin.h
@@ -57,8 +57,6 @@ namespace WebCore {
virtual Color platformActiveTextSearchHighlightColor() const;
virtual Color platformInactiveTextSearchHighlightColor() const;
- // System fonts.
- virtual void systemFont(int propId, FontDescription&) const;
virtual Color systemColor(int cssValueId) const;
#if ENABLE(DATALIST_ELEMENT)
@@ -86,10 +84,6 @@ namespace WebCore {
// entire menulist.
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- // Override RenderThemeChromiumSkia's setDefaultFontSize method to also reset the local font property caches.
- // See comment in RenderThemeChromiumSkia::setDefaultFontSize() regarding ugliness of this hack.
- static void setDefaultFontSize(int);
-
virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
diff --git a/Source/WebCore/rendering/RenderThemeMac.h b/Source/WebCore/rendering/RenderThemeMac.h
index 3288471ad..03d809ed6 100644
--- a/Source/WebCore/rendering/RenderThemeMac.h
+++ b/Source/WebCore/rendering/RenderThemeMac.h
@@ -23,131 +23,24 @@
#ifndef RenderThemeMac_h
#define RenderThemeMac_h
-#import "RenderTheme.h"
-#import <wtf/HashMap.h>
+#import "RenderThemeMacShared.h"
#import <wtf/RetainPtr.h>
-
-OBJC_CLASS WebCoreRenderThemeNotificationObserver;
-
namespace WebCore {
class RenderProgress;
class RenderStyle;
-class RenderThemeMac : public RenderTheme {
+class RenderThemeMac : public RenderThemeMacShared {
public:
static PassRefPtr<RenderTheme> create();
- // A method asking if the control changes its tint when the window has focus or not.
- virtual bool controlSupportsTints(const RenderObject*) const;
-
- // A general method asking if any control tinting is supported at all.
- virtual bool supportsControlTints() const { return true; }
-
- virtual void adjustRepaintRect(const RenderObject*, IntRect&) OVERRIDE;
-
- virtual bool isControlStyled(const RenderStyle*, const BorderData&,
- const FillLayer&, const Color& backgroundColor) const;
-
- virtual Color platformActiveSelectionBackgroundColor() const;
- virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color platformActiveListBoxSelectionBackgroundColor() const;
- virtual Color platformActiveListBoxSelectionForegroundColor() const;
- virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
- virtual Color platformInactiveListBoxSelectionForegroundColor() const;
- virtual Color platformFocusRingColor() const;
-
- virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; }
-
- virtual void platformColorsDidChange();
-
- // System fonts.
- virtual void systemFont(int cssValueId, FontDescription&) const;
-
- virtual int minimumMenuListSize(RenderStyle*) const;
-
- virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
-
-#if ENABLE(DATALIST_ELEMENT)
- virtual IntSize sliderTickSize() const OVERRIDE;
- virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
-#endif
-
- virtual int popupInternalPaddingLeft(RenderStyle*) const;
- virtual int popupInternalPaddingRight(RenderStyle*) const;
- virtual int popupInternalPaddingTop(RenderStyle*) const;
- virtual int popupInternalPaddingBottom(RenderStyle*) const;
-
- virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
-
- virtual bool popsMenuByArrowKeys() const OVERRIDE { return true; }
-
-#if ENABLE(METER_ELEMENT)
- virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const OVERRIDE;
- virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool supportsMeter(ControlPart) const;
-#endif
-
-#if ENABLE(PROGRESS_ELEMENT)
- // Returns the repeat interval of the animation for the progress bar.
- virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
- // Returns the duration of the animation for the progress bar.
- virtual double animationDurationForProgressBar(RenderProgress*) const;
-#endif
-
- virtual Color systemColor(int cssValueId) const;
- // Controls color values returned from platformFocusRingColor(). systemColor() will be used when false.
- virtual bool usesTestModeFocusRingColor() const;
- // A view associated to the contained document. Subclasses may not have such a view and return a fake.
virtual NSView* documentViewFor(RenderObject*) const;
- virtual void paintPlugInSnapshotOverlay(RenderSnapshottedPlugIn*, const PaintInfo&, const LayoutPoint&) const OVERRIDE;
-
protected:
RenderThemeMac();
virtual ~RenderThemeMac();
- virtual bool supportsSelectionForegroundColors() const { return false; }
-
- virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
-
- virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
-
- virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
-
- virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
-
-#if ENABLE(PROGRESS_ELEMENT)
- virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
-#endif
-
- virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
-
- virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
-
- virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
-
- virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
-
#if ENABLE(VIDEO)
virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
@@ -174,87 +67,12 @@ protected:
virtual String extraFullScreenStyleSheet();
#endif
- virtual bool supportsClosedCaptioning() const { return true; }
virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const;
virtual bool usesMediaControlStatusDisplay();
virtual bool usesMediaControlVolumeSlider() const;
virtual void adjustMediaSliderThumbSize(RenderStyle*) const;
virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const OVERRIDE;
#endif
-
- virtual bool shouldShowPlaceholderWhenFocused() const;
-
-private:
- virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const OVERRIDE;
-
- IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
-
- FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const;
-
- // Get the control size based off the font. Used by some of the controls (like buttons).
- NSControlSize controlSizeForFont(RenderStyle*) const;
- NSControlSize controlSizeForSystemFont(RenderStyle*) const;
- void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f);
- void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
- IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
- IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
- void setFontFromControlSize(StyleResolver*, RenderStyle*, NSControlSize) const;
-
- void updateCheckedState(NSCell*, const RenderObject*);
- void updateEnabledState(NSCell*, const RenderObject*);
- void updateFocusedState(NSCell*, const RenderObject*);
- void updatePressedState(NSCell*, const RenderObject*);
- // An optional hook for subclasses to update the control tint of NSCell.
- virtual void updateActiveState(NSCell*, const RenderObject*) {}
-
- // Helpers for adjusting appearance and for painting
-
- void setPopupButtonCellState(const RenderObject*, const IntRect&);
- const IntSize* popupButtonSizes() const;
- const int* popupButtonMargins() const;
- const int* popupButtonPadding(NSControlSize) const;
- void paintMenuListButtonGradients(RenderObject*, const PaintInfo&, const IntRect&);
- const IntSize* menuListSizes() const;
-
- const IntSize* searchFieldSizes() const;
- const IntSize* cancelButtonSizes() const;
- const IntSize* resultsButtonSizes() const;
- void setSearchCellState(RenderObject*, const IntRect&);
- void setSearchFieldSize(RenderStyle*) const;
-
- NSPopUpButtonCell* popupButton() const;
- NSSearchFieldCell* search() const;
- NSMenu* searchMenuTemplate() const;
- NSSliderCell* sliderThumbHorizontal() const;
- NSSliderCell* sliderThumbVertical() const;
- NSTextFieldCell* textField() const;
-
-#if ENABLE(METER_ELEMENT)
- NSLevelIndicatorStyle levelIndicatorStyleFor(ControlPart) const;
- NSLevelIndicatorCell* levelIndicatorFor(const RenderMeter*) const;
-#endif
-
-#if ENABLE(PROGRESS_ELEMENT)
- int minimumProgressBarHeight(RenderStyle*) const;
- const IntSize* progressBarSizes() const;
- const int* progressBarMargins(NSControlSize) const;
-#endif
-
-private:
- mutable RetainPtr<NSPopUpButtonCell> m_popupButton;
- mutable RetainPtr<NSSearchFieldCell> m_search;
- mutable RetainPtr<NSMenu> m_searchMenuTemplate;
- mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal;
- mutable RetainPtr<NSSliderCell> m_sliderThumbVertical;
- mutable RetainPtr<NSLevelIndicatorCell> m_levelIndicator;
- mutable RetainPtr<NSTextFieldCell> m_textField;
-
- bool m_isSliderThumbHorizontalPressed;
- bool m_isSliderThumbVerticalPressed;
-
- mutable HashMap<int, RGBA32> m_systemColorCache;
-
- RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm
index e0837fdc5..fadd09011 100644
--- a/Source/WebCore/rendering/RenderThemeMac.mm
+++ b/Source/WebCore/rendering/RenderThemeMac.mm
@@ -20,137 +20,32 @@
#import "config.h"
#import "RenderThemeMac.h"
-#import "BitmapImage.h"
-#import "ColorMac.h"
-#import "CSSValueList.h"
-#import "CSSValueKeywords.h"
-#import "Document.h"
#import "Element.h"
-#import "FileList.h"
-#import "FrameView.h"
#import "GraphicsContextCG.h"
-#import "HTMLInputElement.h"
#import "HTMLMediaElement.h"
-#import "HTMLNames.h"
-#import "Image.h"
-#import "ImageBuffer.h"
#import "LocalCurrentGraphicsContext.h"
-#import "LocalizedStrings.h"
#import "MediaControlElements.h"
#import "PaintInfo.h"
#import "RenderMedia.h"
#import "RenderMediaControls.h"
-#import "RenderSlider.h"
-#import "RenderSnapshottedPlugIn.h"
#import "RenderView.h"
-#import "SharedBuffer.h"
-#import "StringTruncator.h"
-#import "StyleResolver.h"
#import "TimeRanges.h"
#import "ThemeMac.h"
-#import "WebCoreNSCellExtras.h"
#import "WebCoreSystemInterface.h"
#import "UserAgentStyleSheets.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <wtf/RetainPtr.h>
-#import <wtf/StdLibExtras.h>
-#import <math.h>
-
-#import "RenderProgress.h"
-
-#if ENABLE(METER_ELEMENT)
-#include "RenderMeter.h"
-#include "HTMLMeterElement.h"
-#endif
-
-
-using namespace std;
-
-// The methods in this file are specific to the Mac OS X platform.
-
-// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari.
-
-// We estimate the animation rate of a Mac OS X progress bar is 33 fps.
-// Hard code the value here because we haven't found API for it.
-const double progressAnimationFrameRate = 0.033;
-
-// Mac OS X progress bar animation seems to have 256 frames.
-const double progressAnimationNumFrames = 256;
-
-@interface WebCoreRenderThemeNotificationObserver : NSObject
-{
- WebCore::RenderTheme *_theme;
-}
-
-- (id)initWithTheme:(WebCore::RenderTheme *)theme;
-- (void)systemColorsDidChange:(NSNotification *)notification;
-
-@end
-
-@implementation WebCoreRenderThemeNotificationObserver
-
-- (id)initWithTheme:(WebCore::RenderTheme *)theme
-{
- if (!(self = [super init]))
- return nil;
-
- _theme = theme;
- return self;
-}
-
-- (void)systemColorsDidChange:(NSNotification *)unusedNotification
-{
- ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
- _theme->platformColorsDidChange();
-}
-
-@end
-
-@interface NSTextFieldCell (WKDetails)
-- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
-@end
-
-
-@interface WebCoreTextFieldCell : NSTextFieldCell
-- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
-@end
-
-@implementation WebCoreTextFieldCell
-- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus
-{
- // FIXME: This is a post-Lion-only workaround for <rdar://problem/11385461>. When that bug is resolved, we should remove this code.
- CFMutableDictionaryRef coreUIDrawOptions = CFDictionaryCreateMutableCopy(NULL, 0, [super _coreUIDrawOptionsWithFrame:cellFrame inView:controlView includeFocus:includeFocus]);
- CFDictionarySetValue(coreUIDrawOptions, @"borders only", kCFBooleanTrue);
- return (CFDictionaryRef)[NSMakeCollectable(coreUIDrawOptions) autorelease];
-}
-@end
namespace WebCore {
using namespace HTMLNames;
-enum {
- topMargin,
- rightMargin,
- bottomMargin,
- leftMargin
-};
-
-enum {
- topPadding,
- rightPadding,
- bottomPadding,
- leftPadding
-};
-
-#if PLATFORM(MAC)
PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
{
static RenderTheme* rt = RenderThemeMac::create().leakRef();
return rt;
}
-#endif
PassRefPtr<RenderTheme> RenderThemeMac::create()
{
@@ -158,1575 +53,20 @@ PassRefPtr<RenderTheme> RenderThemeMac::create()
}
RenderThemeMac::RenderThemeMac()
- : m_isSliderThumbHorizontalPressed(false)
- , m_isSliderThumbVerticalPressed(false)
- , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
{
- [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
- selector:@selector(systemColorsDidChange:)
- name:NSSystemColorsDidChangeNotification
- object:nil];
}
RenderThemeMac::~RenderThemeMac()
{
- [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
-}
-
-Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
-{
- NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
-}
-
-Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
-{
- NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
-}
-
-Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() const
-{
- NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
-}
-
-Color RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const
-{
- return Color::white;
-}
-
-Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
-{
- return Color::black;
-}
-
-Color RenderThemeMac::platformFocusRingColor() const
-{
- if (usesTestModeFocusRingColor())
- return oldAquaFocusRingColor();
-
- return systemColor(CSSValueWebkitFocusRingColor);
-}
-
-Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
-{
- return platformInactiveSelectionBackgroundColor();
-}
-
-static FontWeight toFontWeight(NSInteger appKitFontWeight)
-{
- ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
- if (appKitFontWeight > 14)
- appKitFontWeight = 14;
- else if (appKitFontWeight < 1)
- appKitFontWeight = 1;
-
- static FontWeight fontWeights[] = {
- FontWeight100,
- FontWeight100,
- FontWeight200,
- FontWeight300,
- FontWeight400,
- FontWeight500,
- FontWeight600,
- FontWeight600,
- FontWeight700,
- FontWeight800,
- FontWeight800,
- FontWeight900,
- FontWeight900,
- FontWeight900
- };
- return fontWeights[appKitFontWeight - 1];
-}
-
-void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
-{
- DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
- DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
- DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
- DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
- DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
- DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
- DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
-
- FontDescription* cachedDesc;
- NSFont* font = nil;
- switch (cssValueId) {
- case CSSValueSmallCaption:
- cachedDesc = &smallSystemFont;
- if (!smallSystemFont.isAbsoluteSize())
- font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
- break;
- case CSSValueMenu:
- cachedDesc = &menuFont;
- if (!menuFont.isAbsoluteSize())
- font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
- break;
- case CSSValueStatusBar:
- cachedDesc = &labelFont;
- if (!labelFont.isAbsoluteSize())
- font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
- break;
- case CSSValueWebkitMiniControl:
- cachedDesc = &miniControlFont;
- if (!miniControlFont.isAbsoluteSize())
- font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
- break;
- case CSSValueWebkitSmallControl:
- cachedDesc = &smallControlFont;
- if (!smallControlFont.isAbsoluteSize())
- font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
- break;
- case CSSValueWebkitControl:
- cachedDesc = &controlFont;
- if (!controlFont.isAbsoluteSize())
- font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
- break;
- default:
- cachedDesc = &systemFont;
- if (!systemFont.isAbsoluteSize())
- font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
- }
-
- if (font) {
- NSFontManager *fontManager = [NSFontManager sharedFontManager];
- cachedDesc->setIsAbsoluteSize(true);
- cachedDesc->setGenericFamily(FontDescription::NoFamily);
- cachedDesc->firstFamily().setFamily([font familyName]);
- cachedDesc->setSpecifiedSize([font pointSize]);
- cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
- cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
- }
- fontDescription = *cachedDesc;
-}
-
-static RGBA32 convertNSColorToColor(NSColor *color)
-{
- NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- if (colorInColorSpace) {
- static const double scaleFactor = nextafter(256.0, 0.0);
- return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
- static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
- static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
- }
-
- // This conversion above can fail if the NSColor in question is an NSPatternColor
- // (as many system colors are). These colors are actually a repeating pattern
- // not just a solid color. To work around this we simply draw a 1x1 image of
- // the color and use that pixel's color. It might be better to use an average of
- // the colors in the pattern instead.
- NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
- pixelsWide:1
- pixelsHigh:1
- bitsPerSample:8
- samplesPerPixel:4
- hasAlpha:YES
- isPlanar:NO
- colorSpaceName:NSDeviceRGBColorSpace
- bytesPerRow:4
- bitsPerPixel:32];
-
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
- NSEraseRect(NSMakeRect(0, 0, 1, 1));
- [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
- [NSGraphicsContext restoreGraphicsState];
-
- NSUInteger pixel[4];
- [offscreenRep getPixel:pixel atX:0 y:0];
-
- [offscreenRep release];
-
- return makeRGB(pixel[0], pixel[1], pixel[2]);
-}
-
-static RGBA32 menuBackgroundColor()
-{
- NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
- pixelsWide:1
- pixelsHigh:1
- bitsPerSample:8
- samplesPerPixel:4
- hasAlpha:YES
- isPlanar:NO
- colorSpaceName:NSDeviceRGBColorSpace
- bytesPerRow:4
- bitsPerPixel:32];
-
- CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
- CGRect rect = CGRectMake(0, 0, 1, 1);
- HIThemeMenuDrawInfo drawInfo;
- drawInfo.version = 0;
- drawInfo.menuType = kThemeMenuTypePopUp;
- HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
-
- NSUInteger pixel[4];
- [offscreenRep getPixel:pixel atX:0 y:0];
-
- [offscreenRep release];
-
- return makeRGB(pixel[0], pixel[1], pixel[2]);
-}
-
-void RenderThemeMac::platformColorsDidChange()
-{
- m_systemColorCache.clear();
- RenderTheme::platformColorsDidChange();
-}
-
-Color RenderThemeMac::systemColor(int cssValueId) const
-{
- {
- HashMap<int, RGBA32>::iterator it = m_systemColorCache.find(cssValueId);
- if (it != m_systemColorCache.end())
- return it->value;
- }
-
- Color color;
- switch (cssValueId) {
- case CSSValueActiveborder:
- color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
- break;
- case CSSValueActivecaption:
- color = convertNSColorToColor([NSColor windowFrameTextColor]);
- break;
- case CSSValueAppworkspace:
- color = convertNSColorToColor([NSColor headerColor]);
- break;
- case CSSValueBackground:
- // Use theme independent default
- break;
- case CSSValueButtonface:
- // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
- // We may want to change this to use the NSColor in future.
- color = 0xFFC0C0C0;
- break;
- case CSSValueButtonhighlight:
- color = convertNSColorToColor([NSColor controlHighlightColor]);
- break;
- case CSSValueButtonshadow:
- color = convertNSColorToColor([NSColor controlShadowColor]);
- break;
- case CSSValueButtontext:
- color = convertNSColorToColor([NSColor controlTextColor]);
- break;
- case CSSValueCaptiontext:
- color = convertNSColorToColor([NSColor textColor]);
- break;
- case CSSValueGraytext:
- color = convertNSColorToColor([NSColor disabledControlTextColor]);
- break;
- case CSSValueHighlight:
- color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
- break;
- case CSSValueHighlighttext:
- color = convertNSColorToColor([NSColor selectedTextColor]);
- break;
- case CSSValueInactiveborder:
- color = convertNSColorToColor([NSColor controlBackgroundColor]);
- break;
- case CSSValueInactivecaption:
- color = convertNSColorToColor([NSColor controlBackgroundColor]);
- break;
- case CSSValueInactivecaptiontext:
- color = convertNSColorToColor([NSColor textColor]);
- break;
- case CSSValueInfobackground:
- // There is no corresponding NSColor for this so we use a hard coded value.
- color = 0xFFFBFCC5;
- break;
- case CSSValueInfotext:
- color = convertNSColorToColor([NSColor textColor]);
- break;
- case CSSValueMenu:
- color = menuBackgroundColor();
- break;
- case CSSValueMenutext:
- color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
- break;
- case CSSValueScrollbar:
- color = convertNSColorToColor([NSColor scrollBarColor]);
- break;
- case CSSValueText:
- color = convertNSColorToColor([NSColor textColor]);
- break;
- case CSSValueThreeddarkshadow:
- color = convertNSColorToColor([NSColor controlDarkShadowColor]);
- break;
- case CSSValueThreedshadow:
- color = convertNSColorToColor([NSColor shadowColor]);
- break;
- case CSSValueThreedface:
- // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
- // We may want to change this to use the NSColor in future.
- color = 0xFFC0C0C0;
- break;
- case CSSValueThreedhighlight:
- color = convertNSColorToColor([NSColor highlightColor]);
- break;
- case CSSValueThreedlightshadow:
- color = convertNSColorToColor([NSColor controlLightHighlightColor]);
- break;
- case CSSValueWebkitFocusRingColor:
- color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
- break;
- case CSSValueWindow:
- color = convertNSColorToColor([NSColor windowBackgroundColor]);
- break;
- case CSSValueWindowframe:
- color = convertNSColorToColor([NSColor windowFrameColor]);
- break;
- case CSSValueWindowtext:
- color = convertNSColorToColor([NSColor windowFrameTextColor]);
- break;
- }
-
- if (!color.isValid())
- color = RenderTheme::systemColor(cssValueId);
-
- if (color.isValid())
- m_systemColorCache.set(cssValueId, color.rgb());
-
- return color;
-}
-
-bool RenderThemeMac::usesTestModeFocusRingColor() const
-{
- return WebCore::usesTestModeFocusRingColor();
}
NSView* RenderThemeMac::documentViewFor(RenderObject* o) const
{
-#if PLATFORM(MAC)
return ThemeMac::ensuredView(o->view()->frameView());
-#else
- ASSERT_NOT_REACHED();
- return 0;
-#endif
-}
-
-bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
- const FillLayer& background, const Color& backgroundColor) const
-{
- if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
- return style->border() != border;
-
- // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
- // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style
- // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming
- // is in effect we treat it like the control is styled.
- if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
- return true;
-
- return RenderTheme::isControlStyled(style, border, background, backgroundColor);
-}
-
-void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
-{
- ControlPart part = o->style()->appearance();
-
-#if USE(NEW_THEME)
- switch (part) {
- case CheckboxPart:
- case RadioPart:
- case PushButtonPart:
- case SquareButtonPart:
- case DefaultButtonPart:
- case ButtonPart:
- case InnerSpinButtonPart:
- return RenderTheme::adjustRepaintRect(o, r);
- default:
- break;
- }
-#endif
-
- float zoomLevel = o->style()->effectiveZoom();
-
- if (part == MenulistPart) {
- setPopupButtonCellState(o, r);
- IntSize size = popupButtonSizes()[[popupButton() controlSize]];
- size.setHeight(size.height() * zoomLevel);
- size.setWidth(r.width());
- r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
- }
-}
-
-IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
-{
- // Only do the inflation if the available width/height are too small. Otherwise try to
- // fit the glow/check space into the available box's width/height.
- int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
- int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
- IntRect result(r);
- if (widthDelta < 0) {
- result.setX(result.x() - margins[leftMargin] * zoomLevel);
- result.setWidth(result.width() - widthDelta);
- }
- if (heightDelta < 0) {
- result.setY(result.y() - margins[topMargin] * zoomLevel);
- result.setHeight(result.height() - heightDelta);
- }
- return result;
-}
-
-FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
-{
- FloatRect partRect(inputRect);
-
- // Compute an offset between the part renderer and the input renderer
- FloatSize offsetFromInputRenderer;
- const RenderObject* renderer = partRenderer;
- while (renderer && renderer != inputRenderer) {
- RenderObject* containingRenderer = renderer->container();
- offsetFromInputRenderer -= roundedIntSize(renderer->offsetFromContainer(containingRenderer, LayoutPoint()));
- renderer = containingRenderer;
- }
- // If the input renderer was not a container, something went wrong
- ASSERT(renderer == inputRenderer);
- // Move the rect into partRenderer's coords
- partRect.move(offsetFromInputRenderer);
- // Account for the local drawing offset (tx, ty)
- partRect.move(r.x(), r.y());
-
- return partRect;
-}
-
-void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
-{
- bool oldIndeterminate = [cell state] == NSMixedState;
- bool indeterminate = isIndeterminate(o);
- bool checked = isChecked(o);
-
- if (oldIndeterminate != indeterminate) {
- [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
- return;
- }
-
- bool oldChecked = [cell state] == NSOnState;
- if (checked != oldChecked)
- [cell setState:checked ? NSOnState : NSOffState];
-}
-
-void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
-{
- bool oldEnabled = [cell isEnabled];
- bool enabled = isEnabled(o);
- if (enabled != oldEnabled)
- [cell setEnabled:enabled];
-}
-
-void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
-{
- bool oldFocused = [cell showsFirstResponder];
- bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
- if (focused != oldFocused)
- [cell setShowsFirstResponder:focused];
-}
-
-void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
-{
- bool oldPressed = [cell isHighlighted];
- bool pressed = (o->node() && o->node()->active());
- if (pressed != oldPressed)
- [cell setHighlighted:pressed];
-}
-
-bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
-{
- // An alternate way to implement this would be to get the appropriate cell object
- // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
- // that would be that we would match AppKit behavior more closely, but a disadvantage
- // would be that we would rely on an AppKit SPI method.
-
- if (!isEnabled(o))
- return false;
-
- // Checkboxes only have tint when checked.
- if (o->style()->appearance() == CheckboxPart)
- return isChecked(o);
-
- // For now assume other controls have tint if enabled.
- return true;
-}
-
-NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
-{
- int fontSize = style->fontSize();
- if (fontSize >= 16)
- return NSRegularControlSize;
- if (fontSize >= 11)
- return NSSmallControlSize;
- return NSMiniControlSize;
-}
-
-void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
-{
- NSControlSize size;
- if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
- minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
- size = NSRegularControlSize;
- else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
- minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
- size = NSSmallControlSize;
- else
- size = NSMiniControlSize;
- if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
- [cell setControlSize:size];
-}
-
-IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
-{
- if (style->effectiveZoom() != 1.0f) {
- IntSize result = sizes[controlSizeForFont(style)];
- return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
- }
- return sizes[controlSizeForFont(style)];
-}
-
-IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
-{
- if (style->effectiveZoom() != 1.0f) {
- IntSize result = sizes[controlSizeForSystemFont(style)];
- return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
- }
- return sizes[controlSizeForSystemFont(style)];
-}
-
-void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
-{
- // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
- IntSize size = sizeForFont(style, sizes);
- if (style->width().isIntrinsicOrAuto() && size.width() > 0)
- style->setWidth(Length(size.width(), Fixed));
- if (style->height().isAuto() && size.height() > 0)
- style->setHeight(Length(size.height(), Fixed));
-}
-
-void RenderThemeMac::setFontFromControlSize(StyleResolver*, RenderStyle* style, NSControlSize controlSize) const
-{
- FontDescription fontDescription;
- fontDescription.setIsAbsoluteSize(true);
- fontDescription.setGenericFamily(FontDescription::SerifFamily);
-
- NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
- fontDescription.firstFamily().setFamily([font familyName]);
- fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
- fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
-
- // Reset line height
- style->setLineHeight(RenderStyle::initialLineHeight());
-
- if (style->setFontDescription(fontDescription))
- style->font().update(0);
-}
-
-NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
-{
- int fontSize = style->fontSize();
- if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
- return NSRegularControlSize;
- if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
- return NSSmallControlSize;
- return NSMiniControlSize;
-}
-
-bool RenderThemeMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- LocalCurrentGraphicsContext localContext(paintInfo.context);
-
-#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
- bool useNSTextFieldCell = o->style()->hasAppearance()
- && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white
- && !o->style()->hasBackgroundImage();
-
- // We do not use NSTextFieldCell to draw styled text fields on Lion and SnowLeopard because
- // there are a number of bugs on those platforms that require NSTextFieldCell to be in charge
- // of painting its own background. We need WebCore to paint styled backgrounds, so we'll use
- // this WebCoreSystemInterface function instead.
- if (!useNSTextFieldCell) {
- wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
- return false;
- }
-#endif
-
- NSTextFieldCell *textField = this->textField();
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- [textField setEnabled:(isEnabled(o) && !isReadOnlyControl(o))];
- [textField drawWithFrame:NSRect(r) inView:documentViewFor(o)];
-
- [textField setControlView:nil];
-
- return false;
-}
-
-void RenderThemeMac::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
-{
-}
-
-bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
-{
- if (paintInfo.context->paintingDisabled())
- return true;
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawCapsLockIndicator(localContext.cgContext(), r);
-
- return false;
-}
-
-bool RenderThemeMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
- return false;
-}
-
-void RenderThemeMac::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
-{
-}
-
-const int* RenderThemeMac::popupButtonMargins() const
-{
- static const int margins[3][4] =
- {
- { 0, 3, 1, 3 },
- { 0, 3, 2, 3 },
- { 0, 1, 0, 1 }
- };
- return margins[[popupButton() controlSize]];
-}
-
-const IntSize* RenderThemeMac::popupButtonSizes() const
-{
- static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
- return sizes;
-}
-
-const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
-{
- static const int padding[3][4] =
- {
- { 2, 26, 3, 8 },
- { 2, 23, 3, 8 },
- { 2, 22, 3, 10 }
- };
- return padding[size];
-}
-
-bool RenderThemeMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- setPopupButtonCellState(o, r);
-
- NSPopUpButtonCell* popupButton = this->popupButton();
-
- float zoomLevel = o->style()->effectiveZoom();
- IntSize size = popupButtonSizes()[[popupButton controlSize]];
- size.setHeight(size.height() * zoomLevel);
- size.setWidth(r.width());
-
- // Now inflate it to account for the shadow.
- IntRect inflatedRect = r;
- if (r.width() >= minimumMenuListSize(o->style()))
- inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
- paintInfo.context->clip(inflatedRect);
-
- if (zoomLevel != 1.0f) {
- inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
- inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
- paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
- paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
- }
-
- NSView *view = documentViewFor(o);
- [popupButton drawWithFrame:inflatedRect inView:view];
-#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
- if (isFocused(o) && o->style()->outlineStyleIsAuto())
- [popupButton _web_drawFocusRingWithFrame:inflatedRect inView:view];
-#endif
- [popupButton setControlView:nil];
-
- return false;
-}
-
-#if ENABLE(METER_ELEMENT)
-
-IntSize RenderThemeMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
-{
- if (NoControlPart == renderMeter->style()->appearance())
- return bounds.size();
-
- NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
- // Makes enough room for cell's intrinsic size.
- NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
- return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
- bounds.height() < cellSize.height ? cellSize.height : bounds.height());
-}
-
-bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
-{
- if (!renderObject->isMeter())
- return true;
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
-
- NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- [cell drawWithFrame:rect inView:documentViewFor(renderObject)];
- [cell setControlView:nil];
- return false;
-}
-
-bool RenderThemeMac::supportsMeter(ControlPart part) const
-{
- switch (part) {
- case RelevancyLevelIndicatorPart:
- case DiscreteCapacityLevelIndicatorPart:
- case RatingLevelIndicatorPart:
- case MeterPart:
- case ContinuousCapacityLevelIndicatorPart:
- return true;
- default:
- return false;
- }
-}
-
-NSLevelIndicatorStyle RenderThemeMac::levelIndicatorStyleFor(ControlPart part) const
-{
- switch (part) {
- case RelevancyLevelIndicatorPart:
- return NSRelevancyLevelIndicatorStyle;
- case DiscreteCapacityLevelIndicatorPart:
- return NSDiscreteCapacityLevelIndicatorStyle;
- case RatingLevelIndicatorPart:
- return NSRatingLevelIndicatorStyle;
- case MeterPart:
- case ContinuousCapacityLevelIndicatorPart:
- default:
- return NSContinuousCapacityLevelIndicatorStyle;
- }
-
-}
-
-NSLevelIndicatorCell* RenderThemeMac::levelIndicatorFor(const RenderMeter* renderMeter) const
-{
- RenderStyle* style = renderMeter->style();
- ASSERT(style->appearance() != NoControlPart);
-
- if (!m_levelIndicator)
- m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]);
- NSLevelIndicatorCell* cell = m_levelIndicator.get();
-
- HTMLMeterElement* element = renderMeter->meterElement();
- double value = element->value();
-
- // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring,
- // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is.
- switch (element->gaugeRegion()) {
- case HTMLMeterElement::GaugeRegionOptimum:
- // Make meter the green
- [cell setWarningValue:value + 1];
- [cell setCriticalValue:value + 2];
- break;
- case HTMLMeterElement::GaugeRegionSuboptimal:
- // Make the meter yellow
- [cell setWarningValue:value - 1];
- [cell setCriticalValue:value + 1];
- break;
- case HTMLMeterElement::GaugeRegionEvenLessGood:
- // Make the meter red
- [cell setWarningValue:value - 2];
- [cell setCriticalValue:value - 1];
- break;
- }
-
- [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())];
- [cell setBaseWritingDirection:style->isLeftToRightDirection() ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft];
- [cell setMinValue:element->min()];
- [cell setMaxValue:element->max()];
- RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value];
- [cell setObjectValue:valueObject.get()];
-
- return cell;
-}
-
-#endif
-
-#if ENABLE(PROGRESS_ELEMENT)
-const IntSize* RenderThemeMac::progressBarSizes() const
-{
- static const IntSize sizes[3] = { IntSize(0, 20), IntSize(0, 12), IntSize(0, 12) };
- return sizes;
-}
-
-const int* RenderThemeMac::progressBarMargins(NSControlSize controlSize) const
-{
- static const int margins[3][4] =
- {
- { 0, 0, 1, 0 },
- { 0, 0, 1, 0 },
- { 0, 0, 1, 0 },
- };
- return margins[controlSize];
-}
-
-int RenderThemeMac::minimumProgressBarHeight(RenderStyle* style) const
-{
- return sizeForSystemFont(style, progressBarSizes()).height();
-}
-
-double RenderThemeMac::animationRepeatIntervalForProgressBar(RenderProgress*) const
-{
- return progressAnimationFrameRate;
-}
-
-double RenderThemeMac::animationDurationForProgressBar(RenderProgress*) const
-{
- return progressAnimationNumFrames * progressAnimationFrameRate;
-}
-
-void RenderThemeMac::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
-{
-}
-
-bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
-{
- if (!renderObject->isProgress())
- return true;
-
- float zoomLevel = renderObject->style()->effectiveZoom();
- int controlSize = controlSizeForFont(renderObject->style());
- IntSize size = progressBarSizes()[controlSize];
- size.setHeight(size.height() * zoomLevel);
- size.setWidth(rect.width());
-
- // Now inflate it to account for the shadow.
- IntRect inflatedRect = rect;
- if (rect.height() <= minimumProgressBarHeight(renderObject->style()))
- inflatedRect = inflateRect(inflatedRect, size, progressBarMargins(controlSize), zoomLevel);
-
- RenderProgress* renderProgress = toRenderProgress(renderObject);
- HIThemeTrackDrawInfo trackInfo;
- trackInfo.version = 0;
- if (controlSize == NSRegularControlSize)
- trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar;
- else
- trackInfo.kind = renderProgress->position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar;
-
- trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size());
- trackInfo.min = 0;
- trackInfo.max = numeric_limits<SInt32>::max();
- trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0));
- trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0));
- trackInfo.attributes = kThemeTrackHorizontal;
- trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive;
- trackInfo.reserved = 0;
- trackInfo.filler1 = 0;
-
- OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size(), 1);
- if (!imageBuffer)
- return true;
-
- ContextContainer cgContextContainer(imageBuffer->context());
- CGContextRef cgContext = cgContextContainer.context();
- HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- if (!renderProgress->style()->isLeftToRightDirection()) {
- paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0);
- paintInfo.context->scale(FloatSize(-1, 1));
- }
-
- paintInfo.context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, inflatedRect.location());
- return false;
-}
-#endif
-
-const float baseFontSize = 11.0f;
-const float baseArrowHeight = 4.0f;
-const float baseArrowWidth = 5.0f;
-const float baseSpaceBetweenArrows = 2.0f;
-const int arrowPaddingLeft = 6;
-const int arrowPaddingRight = 6;
-const int paddingBeforeSeparator = 4;
-const int baseBorderRadius = 5;
-const int styledPopupPaddingLeft = 8;
-const int styledPopupPaddingTop = 1;
-const int styledPopupPaddingBottom = 2;
-
-static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
- static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
- static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
- static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
-{
- static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
- static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
- float a = inData[0];
- int i = 0;
- for (i = 0; i < 4; i++)
- outData[i] = (1.0f - a) * dark[i] + a * light[i];
-}
-
-void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- if (r.isEmpty())
- return;
-
- ContextContainer cgContextContainer(paintInfo.context);
- CGContextRef context = cgContextContainer.context();
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- RoundedRect border = o->style()->getRoundedBorderFor(r, o->view());
- int radius = border.radii().topLeft().width();
-
- CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
-
- FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
- struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
- RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), topFunction.get(), false, false));
-
- FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
- struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
- RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), bottomFunction.get(), false, false));
-
- struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
- RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false));
-
- RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
-
- RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.maxX(), r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false));
-
- {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, r);
- paintInfo.context->addRoundedRectClip(border);
- context = cgContextContainer.context();
- CGContextDrawShading(context, mainShading.get());
- }
-
- {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, topGradient);
- paintInfo.context->addRoundedRectClip(RoundedRect(enclosingIntRect(topGradient), border.radii().topLeft(), border.radii().topRight(), IntSize(), IntSize()));
- context = cgContextContainer.context();
- CGContextDrawShading(context, topShading.get());
- }
-
- if (!bottomGradient.isEmpty()) {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, bottomGradient);
- paintInfo.context->addRoundedRectClip(RoundedRect(enclosingIntRect(bottomGradient), IntSize(), IntSize(), border.radii().bottomLeft(), border.radii().bottomRight()));
- context = cgContextContainer.context();
- CGContextDrawShading(context, bottomShading.get());
- }
-
- {
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, r);
- paintInfo.context->addRoundedRectClip(border);
- context = cgContextContainer.context();
- CGContextDrawShading(context, leftShading.get());
- CGContextDrawShading(context, rightShading.get());
- }
-}
-
-bool RenderThemeMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
- r.y() + o->style()->borderTopWidth(),
- r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
- r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
- // Draw the gradients to give the styled popup menu a button appearance
- paintMenuListButtonGradients(o, paintInfo, bounds);
-
- // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
- float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
- float centerY = bounds.y() + bounds.height() / 2.0f;
- float arrowHeight = baseArrowHeight * fontScale;
- float arrowWidth = baseArrowWidth * fontScale;
- float leftEdge = bounds.maxX() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
- float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
-
- if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
- return false;
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), o->style()->colorSpace());
- paintInfo.context->setStrokeStyle(NoStroke);
-
- FloatPoint arrow1[3];
- arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
- arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
- arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
-
- // Draw the top arrow
- paintInfo.context->drawConvexPolygon(3, arrow1, true);
-
- FloatPoint arrow2[3];
- arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
- arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
- arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
-
- // Draw the bottom arrow
- paintInfo.context->drawConvexPolygon(3, arrow2, true);
-
- Color leftSeparatorColor(0, 0, 0, 40);
- Color rightSeparatorColor(255, 255, 255, 40);
-
- // FIXME: Should the separator thickness and space be scaled up by fontScale?
- int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
- int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
-
- // Draw the separator to the left of the arrows
- paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
- paintInfo.context->setStrokeStyle(SolidStroke);
- paintInfo.context->setStrokeColor(leftSeparatorColor, ColorSpaceDeviceRGB);
- paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
- IntPoint(leftEdgeOfSeparator, bounds.maxY()));
-
- paintInfo.context->setStrokeColor(rightSeparatorColor, ColorSpaceDeviceRGB);
- paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
- IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
- return false;
-}
-
-static const IntSize* menuListButtonSizes()
-{
- static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
- return sizes;
-}
-
-void RenderThemeMac::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
-{
- NSControlSize controlSize = controlSizeForFont(style);
-
- style->resetBorder();
- style->resetPadding();
-
- // Height is locked to auto.
- style->setHeight(Length(Auto));
-
- // White-space is locked to pre
- style->setWhiteSpace(PRE);
-
- // Set the foreground color to black or gray when we have the aqua look.
- // Cast to RGB32 is to work around a compiler bug.
- style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
-
- // Set the button's vertical size.
- setSizeFromFont(style, menuListButtonSizes());
-
- // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
- // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
- // system font for the control size instead.
- setFontFromControlSize(styleResolver, style, controlSize);
-
- style->setBoxShadow(nullptr);
-}
-
-int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
-{
- if (style->appearance() == MenulistPart)
- return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
- if (style->appearance() == MenulistButtonPart)
- return styledPopupPaddingLeft * style->effectiveZoom();
- return 0;
-}
-
-int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
-{
- if (style->appearance() == MenulistPart)
- return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
- if (style->appearance() == MenulistButtonPart) {
- float fontScale = style->fontSize() / baseFontSize;
- float arrowWidth = baseArrowWidth * fontScale;
- return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
- }
- return 0;
-}
-
-int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
-{
- if (style->appearance() == MenulistPart)
- return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
- if (style->appearance() == MenulistButtonPart)
- return styledPopupPaddingTop * style->effectiveZoom();
- return 0;
-}
-
-int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
-{
- if (style->appearance() == MenulistPart)
- return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
- if (style->appearance() == MenulistButtonPart)
- return styledPopupPaddingBottom * style->effectiveZoom();
- return 0;
-}
-
-void RenderThemeMac::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
-{
- float fontScale = style->fontSize() / baseFontSize;
-
- style->resetPadding();
- style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
-
- const int minHeight = 15;
- style->setMinHeight(Length(minHeight, Fixed));
-
- style->setLineHeight(RenderStyle::initialLineHeight());
-}
-
-void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
-{
- NSPopUpButtonCell* popupButton = this->popupButton();
-
- // Set the control size based off the rectangle we're painting into.
- setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
-
- // Update the various states we respond to.
- updateActiveState(popupButton, o);
- updateCheckedState(popupButton, o);
- updateEnabledState(popupButton, o);
- updatePressedState(popupButton, o);
-#if BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
- updateFocusedState(popupButton, o);
-#endif
-}
-
-const IntSize* RenderThemeMac::menuListSizes() const
-{
- static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
- return sizes;
-}
-
-int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
-{
- return sizeForSystemFont(style, menuListSizes()).width();
-}
-
-const int trackWidth = 5;
-const int trackRadius = 2;
-
-void RenderThemeMac::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
-{
- style->setBoxShadow(nullptr);
-}
-
-bool RenderThemeMac::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- IntRect bounds = r;
- float zoomLevel = o->style()->effectiveZoom();
- float zoomedTrackWidth = trackWidth * zoomLevel;
-
- if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) {
- bounds.setHeight(zoomedTrackWidth);
- bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
- } else if (o->style()->appearance() == SliderVerticalPart) {
- bounds.setWidth(zoomedTrackWidth);
- bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
- }
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- CGContextRef context = localContext.cgContext();
- CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
-
-#if ENABLE(DATALIST_ELEMENT)
- paintSliderTicks(o, paintInfo, r);
-#endif
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- CGContextClipToRect(context, bounds);
-
- struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
- RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
- RetainPtr<CGShadingRef> mainShading;
- if (o->style()->appearance() == SliderVerticalPart)
- mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(), bounds.maxY()), CGPointMake(bounds.maxX(), bounds.maxY()), mainFunction.get(), false, false));
- else
- mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.maxY()), mainFunction.get(), false, false));
-
- IntSize radius(trackRadius, trackRadius);
- paintInfo.context->addRoundedRectClip(RoundedRect(bounds, radius, radius, radius, radius));
- context = localContext.cgContext();
- CGContextDrawShading(context, mainShading.get());
-
- return false;
-}
-
-void RenderThemeMac::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
-{
- RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
- style->setBoxShadow(nullptr);
-}
-
-const float verticalSliderHeightPadding = 0.1f;
-
-bool RenderThemeMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
- ? sliderThumbVertical()
- : sliderThumbHorizontal();
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
-
- // Update the various states we respond to.
- updateActiveState(sliderThumbCell, o);
- updateEnabledState(sliderThumbCell, o);
- updateFocusedState(sliderThumbCell, (o->node() && o->node()->focusDelegate()->renderer()) ? o->node()->focusDelegate()->renderer() : o);
-
- // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
- bool oldPressed;
- if (o->style()->appearance() == SliderThumbVerticalPart)
- oldPressed = m_isSliderThumbVerticalPressed;
- else
- oldPressed = m_isSliderThumbHorizontalPressed;
-
- bool pressed = isPressed(o);
-
- if (o->style()->appearance() == SliderThumbVerticalPart)
- m_isSliderThumbVerticalPressed = pressed;
- else
- m_isSliderThumbHorizontalPressed = pressed;
-
- if (pressed != oldPressed) {
- if (pressed)
- [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
- else
- [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
- }
-
- FloatRect bounds = r;
- // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
- if (o->style()->appearance() == SliderThumbVerticalPart)
- bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- float zoomLevel = o->style()->effectiveZoom();
-
- FloatRect unzoomedRect = bounds;
- if (zoomLevel != 1.0f) {
- unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
- unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
- paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
- paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
- }
-
-#if PLATFORM(CHROMIUM)
- paintInfo.context->translate(0, unzoomedRect.y());
- paintInfo.context->scale(FloatSize(1, -1));
- paintInfo.context->translate(0, -(unzoomedRect.y() + unzoomedRect.height()));
-#endif
-
- [sliderThumbCell drawInteriorWithFrame:unzoomedRect inView:documentViewFor(o)];
- [sliderThumbCell setControlView:nil];
-
- return false;
-}
-
-bool RenderThemeMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- NSSearchFieldCell* search = this->search();
-
- setSearchCellState(o, r);
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- float zoomLevel = o->style()->effectiveZoom();
-
- IntRect unzoomedRect = r;
-
- if (zoomLevel != 1.0f) {
- unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
- unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
- paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
- paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
- }
-
- // Set the search button to nil before drawing. Then reset it so we can draw it later.
- [search setSearchButtonCell:nil];
-
- [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)];
-
- [search setControlView:nil];
- [search resetSearchButtonCell];
-
- return false;
-}
-
-void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&)
-{
- NSSearchFieldCell* search = this->search();
-
- [search setControlSize:controlSizeForFont(o->style())];
-
- // Update the various states we respond to.
- updateActiveState(search, o);
- updateEnabledState(search, o);
- updateFocusedState(search, o);
-}
-
-const IntSize* RenderThemeMac::searchFieldSizes() const
-{
- static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
- return sizes;
-}
-
-void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
-{
- // If the width and height are both specified, then we have nothing to do.
- if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
- return;
-
- // Use the font size to determine the intrinsic width of the control.
- setSizeFromFont(style, searchFieldSizes());
-}
-
-void RenderThemeMac::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element*) const
-{
- // Override border.
- style->resetBorder();
- const short borderWidth = 2 * style->effectiveZoom();
- style->setBorderLeftWidth(borderWidth);
- style->setBorderLeftStyle(INSET);
- style->setBorderRightWidth(borderWidth);
- style->setBorderRightStyle(INSET);
- style->setBorderBottomWidth(borderWidth);
- style->setBorderBottomStyle(INSET);
- style->setBorderTopWidth(borderWidth);
- style->setBorderTopStyle(INSET);
-
- // Override height.
- style->setHeight(Length(Auto));
- setSearchFieldSize(style);
-
- // Override padding size to match AppKit text positioning.
- const int padding = 1 * style->effectiveZoom();
- style->setPaddingLeft(Length(padding, Fixed));
- style->setPaddingRight(Length(padding, Fixed));
- style->setPaddingTop(Length(padding, Fixed));
- style->setPaddingBottom(Length(padding, Fixed));
-
- NSControlSize controlSize = controlSizeForFont(style);
- setFontFromControlSize(styleResolver, style, controlSize);
-
- style->setBoxShadow(nullptr);
-}
-
-bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- Element* input = o->node()->shadowHost();
- if (!input)
- input = toElement(o->node());
-
- if (!input->renderer()->isBox())
- return false;
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- setSearchCellState(input->renderer(), r);
-
- NSSearchFieldCell* search = this->search();
-
- if (input->isEnabledFormControl() && (input->isTextFormControl() && !static_cast<HTMLTextFormControlElement*>(input)->readOnly())) {
- updateActiveState([search cancelButtonCell], o);
- updatePressedState([search cancelButtonCell], o);
- }
- else if ([[search cancelButtonCell] isHighlighted])
- [[search cancelButtonCell] setHighlighted:NO];
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
-
- float zoomLevel = o->style()->effectiveZoom();
-
- FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
-
-#if ENABLE(INPUT_SPEECH)
- // Take care of cases where the cancel button was not aligned with the right border of the input element (for e.g.
- // when speech input is enabled for the input element.
- IntRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
- int absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
- int spaceToRightOfCancelButton = absRight - (r.x() + r.width());
- localBounds.setX(localBounds.x() - spaceToRightOfCancelButton);
-#endif
-
- localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
-
- FloatRect unzoomedRect(localBounds);
- if (zoomLevel != 1.0f) {
- unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
- unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
- paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
- paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
- }
-
- [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
- [[search cancelButtonCell] setControlView:nil];
- return false;
-}
-
-const IntSize* RenderThemeMac::cancelButtonSizes() const
-{
- static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
- return sizes;
-}
-
-void RenderThemeMac::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
-{
- IntSize size = sizeForSystemFont(style, cancelButtonSizes());
- style->setWidth(Length(size.width(), Fixed));
- style->setHeight(Length(size.height(), Fixed));
- style->setBoxShadow(nullptr);
-}
-
-const IntSize* RenderThemeMac::resultsButtonSizes() const
-{
- static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
- return sizes;
-}
-
-const int emptyResultsOffset = 9;
-void RenderThemeMac::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
-{
- IntSize size = sizeForSystemFont(style, resultsButtonSizes());
- style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
- style->setHeight(Length(size.height(), Fixed));
- style->setBoxShadow(nullptr);
-}
-
-bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&)
-{
- return false;
-}
-
-void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
-{
- IntSize size = sizeForSystemFont(style, resultsButtonSizes());
- style->setWidth(Length(size.width(), Fixed));
- style->setHeight(Length(size.height(), Fixed));
- style->setBoxShadow(nullptr);
-}
-
-bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- Node* input = o->node()->shadowHost();
- if (!input)
- input = o->node();
- if (!input->renderer()->isBox())
- return false;
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- setSearchCellState(input->renderer(), r);
-
- NSSearchFieldCell* search = this->search();
-
- if ([search searchMenuTemplate] != nil)
- [search setSearchMenuTemplate:nil];
-
- updateActiveState([search searchButtonCell], o);
-
- FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
- localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
-
- [[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)];
- [[search searchButtonCell] setControlView:nil];
- return false;
-}
-
-const int resultsArrowWidth = 5;
-void RenderThemeMac::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
-{
- IntSize size = sizeForSystemFont(style, resultsButtonSizes());
- style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
- style->setHeight(Length(size.height(), Fixed));
- style->setBoxShadow(nullptr);
-}
-
-bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
-{
- Node* input = o->node()->shadowHost();
- if (!input)
- input = o->node();
- if (!input->renderer()->isBox())
- return false;
-
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- setSearchCellState(input->renderer(), r);
-
- NSSearchFieldCell* search = this->search();
-
- updateActiveState([search searchButtonCell], o);
-
- if (![search searchMenuTemplate])
- [search setSearchMenuTemplate:searchMenuTemplate()];
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context);
- float zoomLevel = o->style()->effectiveZoom();
-
- FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
- localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
-
- IntRect unzoomedRect(localBounds);
- if (zoomLevel != 1.0f) {
- unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
- unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
- paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
- paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
- paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
- }
-
- [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
- [[search searchButtonCell] setControlView:nil];
-
- return false;
}
#if ENABLE(VIDEO)
+
typedef enum {
MediaControllerThemeClassic = 1,
MediaControllerThemeQuickTime = 2
@@ -1735,7 +75,7 @@ typedef enum {
static int mediaControllerTheme()
{
static int controllerTheme = -1;
-
+
if (controllerTheme != -1)
return controllerTheme;
@@ -1750,40 +90,10 @@ static int mediaControllerTheme()
controllerTheme = MediaControllerThemeQuickTime;
return controllerTheme;
}
-#endif
-
-#if ENABLE(DATALIST_ELEMENT)
-IntSize RenderThemeMac::sliderTickSize() const
-{
- return IntSize(1, 3);
-}
-int RenderThemeMac::sliderTickOffsetFromTrackCenter() const
-{
- return -9;
-}
-#endif
-
-const int sliderThumbWidth = 15;
-const int sliderThumbHeight = 15;
const int mediaSliderThumbWidth = 13;
const int mediaSliderThumbHeight = 14;
-void RenderThemeMac::adjustSliderThumbSize(RenderStyle* style, Element*) const
-{
- float zoomLevel = style->effectiveZoom();
- if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) {
- style->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
- style->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
- }
-
-#if ENABLE(VIDEO)
- adjustMediaSliderThumbSize(style);
-#endif
-}
-
-#if ENABLE(VIDEO)
-
void RenderThemeMac::adjustMediaSliderThumbSize(RenderStyle* style) const
{
int wkPart;
@@ -1816,7 +126,7 @@ void RenderThemeMac::adjustMediaSliderThumbSize(RenderStyle* style) const
style->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
}
-enum WKMediaControllerThemeState {
+enum WKMediaControllerThemeState {
MediaUIPartDisabledFlag = 1 << 0,
MediaUIPartPressedFlag = 1 << 1,
MediaUIPartDrawEndCapsFlag = 1 << 3,
@@ -1848,7 +158,6 @@ static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const P
return unzoomedRect;
}
-
bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->node();
@@ -1930,12 +239,12 @@ bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const PaintInfo& pai
float duration = mediaElement->duration();
if (isnan(duration))
duration = 0;
-
+
ContextContainer cgContextContainer(paintInfo.context);
CGContextRef context = cgContextContainer.context();
GraphicsContextStateSaver stateSaver(*paintInfo.context);
FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
- wkDrawMediaSliderTrack(mediaControllerTheme(), context, unzoomedRect,
+ wkDrawMediaSliderTrack(mediaControllerTheme(), context, unzoomedRect,
timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
return false;
}
@@ -1950,13 +259,13 @@ bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const PaintInfo& pai
wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
}
-
+
bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->node();
if (!node)
return false;
-
+
LocalCurrentGraphicsContext localContext(paintInfo.context);
wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
@@ -1967,7 +276,7 @@ bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const Pai
Node* node = o->node();
if (!node)
return false;
-
+
LocalCurrentGraphicsContext localContext(paintInfo.context);
wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
@@ -1985,7 +294,7 @@ bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const
wkDrawMediaUIPart(mediaControlElementType(node), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
}
-
+
bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->node();
@@ -2044,7 +353,7 @@ bool RenderThemeMac::paintMediaVolumeSliderTrack(RenderObject* o, const PaintInf
wkDrawMediaUIPart(MediaVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
}
-
+
bool RenderThemeMac::paintMediaVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->node();
@@ -2061,7 +370,7 @@ bool RenderThemeMac::paintMediaFullScreenVolumeSliderTrack(RenderObject* o, cons
Node* node = o->node();
if (!node)
return false;
-
+
LocalCurrentGraphicsContext localContext(paintInfo.context);
wkDrawMediaUIPart(MediaFullScreenVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
@@ -2072,7 +381,7 @@ bool RenderThemeMac::paintMediaFullScreenVolumeSliderThumb(RenderObject* o, cons
Node* node = o->node();
if (!node)
return false;
-
+
LocalCurrentGraphicsContext localContext(paintInfo.context);
wkDrawMediaUIPart(MediaFullScreenVolumeSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
return false;
@@ -2080,29 +389,19 @@ bool RenderThemeMac::paintMediaFullScreenVolumeSliderThumb(RenderObject* o, cons
String RenderThemeMac::extraMediaControlsStyleSheet()
{
-#if PLATFORM(MAC)
if (mediaControllerTheme() == MediaControllerThemeQuickTime)
return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet));
return String();
-#else
- ASSERT_NOT_REACHED();
- return String();
-#endif
}
#if ENABLE(FULLSCREEN_API)
String RenderThemeMac::extraFullScreenStyleSheet()
{
-#if PLATFORM(MAC)
if (mediaControllerTheme() == MediaControllerThemeQuickTime)
return String(fullscreenQuickTimeUserAgentStyleSheet, sizeof(fullscreenQuickTimeUserAgentStyleSheet));
-
- return String();
-#else
- ASSERT_NOT_REACHED();
+
return String();
-#endif
}
#endif
@@ -2131,145 +430,4 @@ IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonB
#endif // ENABLE(VIDEO)
-bool RenderThemeMac::shouldShowPlaceholderWhenFocused() const
-{
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
- return true;
-#else
- return false;
-#endif
-}
-
-NSPopUpButtonCell* RenderThemeMac::popupButton() const
-{
- if (!m_popupButton) {
- m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
- [m_popupButton.get() setUsesItemFromMenu:NO];
- [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
- }
-
- return m_popupButton.get();
-}
-
-NSSearchFieldCell* RenderThemeMac::search() const
-{
- if (!m_search) {
- m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
- [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
- [m_search.get() setBezeled:YES];
- [m_search.get() setEditable:YES];
- [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
- }
-
- return m_search.get();
-}
-
-NSMenu* RenderThemeMac::searchMenuTemplate() const
-{
- if (!m_searchMenuTemplate)
- m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
-
- return m_searchMenuTemplate.get();
-}
-
-NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
-{
- if (!m_sliderThumbHorizontal) {
- m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
- [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
- [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
- [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
- }
-
- return m_sliderThumbHorizontal.get();
-}
-
-NSSliderCell* RenderThemeMac::sliderThumbVertical() const
-{
- if (!m_sliderThumbVertical) {
- m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
- [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
- [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
- [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
- }
-
- return m_sliderThumbVertical.get();
-}
-
-NSTextFieldCell* RenderThemeMac::textField() const
-{
- if (!m_textField) {
- m_textField.adoptNS([[WebCoreTextFieldCell alloc] initTextCell:@""]);
- [m_textField.get() setBezeled:YES];
- [m_textField.get() setEditable:YES];
- [m_textField.get() setFocusRingType:NSFocusRingTypeExterior];
-#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
- [m_textField.get() setDrawsBackground:YES];
- [m_textField.get() setBackgroundColor:[NSColor whiteColor]];
-#else
- // Post-Lion, WebCore can be in charge of paintinng the background thanks to
- // the workaround in place for <rdar://problem/11385461>, which is implemented
- // above as _coreUIDrawOptionsWithFrame.
- [m_textField.get() setDrawsBackground:NO];
-#endif
- }
-
- return m_textField.get();
-}
-
-String RenderThemeMac::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
-{
- if (width <= 0)
- return String();
-
- String strToTruncate;
- if (fileList->isEmpty())
- strToTruncate = fileListDefaultLabel(multipleFilesAllowed);
- else if (fileList->length() == 1)
- strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(fileList->item(0)->path())];
- else
- return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
-
- return StringTruncator::centerTruncate(strToTruncate, width, font, StringTruncator::EnableRoundingHacks);
-}
-
-void RenderThemeMac::paintPlugInSnapshotOverlay(RenderSnapshottedPlugIn* renderer, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
-{
- LayoutUnit cWidth = renderer->contentWidth();
- LayoutUnit cHeight = renderer->contentHeight();
- if (!cWidth || !cHeight)
- return;
-
- GraphicsContext* context = paintInfo.context;
- GraphicsContextStateSaver saver(*context);
-
- LayoutSize borderAndPadding(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop());
-
- LayoutSize contentSize(cWidth, cHeight);
- LayoutPoint contentLocation = paintOffset;
- contentLocation.move(borderAndPadding);
-
- RefPtr<Gradient> g = Gradient::create(contentLocation, FloatPoint(contentLocation.x(), contentLocation.y() + cHeight));
- g->addColorStop(0, Color(.5f, .5, .5, .7));
- g->addColorStop(.2, Color(.54f, .54, .54, .3));
- g->addColorStop(.6, Color(.62f, .62, .62, .3));
- g->addColorStop(1, Color(.7f, .7, .7, .95));
- context->setFillGradient(g.release());
- context->fillRect(pixelSnappedIntRect(LayoutRect(contentLocation, contentSize)));
-
- static const float diameter = 50, triangleRadius = 12;
- LayoutPoint center = contentLocation;
- center.move(cWidth / 2, cHeight / 2);
- context->setFillColor(Color(.4f, .4, .4, .7), ColorSpaceSRGB);
- context->fillEllipse(FloatRect(center.x() - diameter / 2, center.y() - diameter / 2, diameter, diameter));
-
- Path p;
- p.moveTo(FloatPoint(center.x() - triangleRadius * 3 / 4, center.y() - triangleRadius));
- p.addLineTo(FloatPoint(center.x() + triangleRadius * 5 / 4, center.y()));
- p.addLineTo(FloatPoint(center.x() - triangleRadius * 3 / 4, center.y() + triangleRadius));
- p.closeSubpath();
- context->setFillColor(Color(1.f, 1.f, 1.f, .9f), ColorSpaceSRGB);
- context->fillPath(p);
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeMacShared.h b/Source/WebCore/rendering/RenderThemeMacShared.h
new file mode 100644
index 000000000..5283cb8db
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeMacShared.h
@@ -0,0 +1,227 @@
+/*
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeMacShared_h
+#define RenderThemeMacShared_h
+
+#import "RenderTheme.h"
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+
+OBJC_CLASS WebCoreRenderThemeNotificationObserver;
+
+namespace WebCore {
+
+class RenderProgress;
+class RenderStyle;
+
+class RenderThemeMacShared : public RenderTheme {
+public:
+ // A method asking if the control changes its tint when the window has focus or not.
+ virtual bool controlSupportsTints(const RenderObject*) const;
+
+ // A general method asking if any control tinting is supported at all.
+ virtual bool supportsControlTints() const { return true; }
+
+ virtual void adjustRepaintRect(const RenderObject*, IntRect&) OVERRIDE;
+
+ virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer&, const Color& backgroundColor) const;
+
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveListBoxSelectionBackgroundColor() const;
+ virtual Color platformActiveListBoxSelectionForegroundColor() const;
+ virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
+ virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+ virtual Color platformFocusRingColor() const;
+
+ virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; }
+
+ virtual void platformColorsDidChange();
+
+ // System fonts.
+ virtual void systemFont(int cssValueId, FontDescription&) const;
+
+ virtual int minimumMenuListSize(RenderStyle*) const;
+
+ virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+
+#if ENABLE(DATALIST_ELEMENT)
+ virtual IntSize sliderTickSize() const OVERRIDE;
+ virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
+#endif
+
+ virtual int popupInternalPaddingLeft(RenderStyle*) const;
+ virtual int popupInternalPaddingRight(RenderStyle*) const;
+ virtual int popupInternalPaddingTop(RenderStyle*) const;
+ virtual int popupInternalPaddingBottom(RenderStyle*) const;
+
+ virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+ virtual bool popsMenuByArrowKeys() const OVERRIDE { return true; }
+
+#if ENABLE(METER_ELEMENT)
+ virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const OVERRIDE;
+ virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual bool supportsMeter(ControlPart) const;
+#endif
+
+#if ENABLE(PROGRESS_ELEMENT)
+ // Returns the repeat interval of the animation for the progress bar.
+ virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+ // Returns the duration of the animation for the progress bar.
+ virtual double animationDurationForProgressBar(RenderProgress*) const;
+#endif
+
+ virtual Color systemColor(int cssValueId) const;
+ // Controls color values returned from platformFocusRingColor(). systemColor() will be used when false.
+ virtual bool usesTestModeFocusRingColor() const;
+ // A view associated to the contained document. Subclasses may not have such a view and return a fake.
+ virtual NSView* documentViewFor(RenderObject*) const = 0;
+
+protected:
+ RenderThemeMacShared();
+ virtual ~RenderThemeMacShared();
+
+ virtual bool supportsSelectionForegroundColors() const { return false; }
+
+ virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+ virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+ virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+ virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+#if ENABLE(PROGRESS_ELEMENT)
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
+#endif
+
+ virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+ virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+ virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+#if ENABLE(VIDEO)
+ virtual void adjustMediaSliderThumbSize(RenderStyle*) const = 0;
+ virtual bool supportsClosedCaptioning() const { return true; }
+#endif
+
+ virtual bool shouldShowPlaceholderWhenFocused() const;
+
+private:
+ virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const OVERRIDE;
+
+ IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
+
+ FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect&) const;
+
+ // Get the control size based off the font. Used by some of the controls (like buttons).
+ NSControlSize controlSizeForFont(RenderStyle*) const;
+ NSControlSize controlSizeForSystemFont(RenderStyle*) const;
+ void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f);
+ void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
+ IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
+ IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
+ void setFontFromControlSize(StyleResolver*, RenderStyle*, NSControlSize) const;
+
+ void updateCheckedState(NSCell*, const RenderObject*);
+ void updateEnabledState(NSCell*, const RenderObject*);
+ void updateFocusedState(NSCell*, const RenderObject*);
+ void updatePressedState(NSCell*, const RenderObject*);
+ // An optional hook for subclasses to update the control tint of NSCell.
+ virtual void updateActiveState(NSCell*, const RenderObject*) { }
+
+ // Helpers for adjusting appearance and for painting
+
+ void setPopupButtonCellState(const RenderObject*, const IntRect&);
+ const IntSize* popupButtonSizes() const;
+ const int* popupButtonMargins() const;
+ const int* popupButtonPadding(NSControlSize) const;
+ void paintMenuListButtonGradients(RenderObject*, const PaintInfo&, const IntRect&);
+ const IntSize* menuListSizes() const;
+
+ const IntSize* searchFieldSizes() const;
+ const IntSize* cancelButtonSizes() const;
+ const IntSize* resultsButtonSizes() const;
+ void setSearchCellState(RenderObject*, const IntRect&);
+ void setSearchFieldSize(RenderStyle*) const;
+
+ NSPopUpButtonCell* popupButton() const;
+ NSSearchFieldCell* search() const;
+ NSMenu* searchMenuTemplate() const;
+ NSSliderCell* sliderThumbHorizontal() const;
+ NSSliderCell* sliderThumbVertical() const;
+ NSTextFieldCell* textField() const;
+
+#if ENABLE(METER_ELEMENT)
+ NSLevelIndicatorStyle levelIndicatorStyleFor(ControlPart) const;
+ NSLevelIndicatorCell* levelIndicatorFor(const RenderMeter*) const;
+#endif
+
+#if ENABLE(PROGRESS_ELEMENT)
+ int minimumProgressBarHeight(RenderStyle*) const;
+ const IntSize* progressBarSizes() const;
+ const int* progressBarMargins(NSControlSize) const;
+#endif
+
+private:
+ mutable RetainPtr<NSPopUpButtonCell> m_popupButton;
+ mutable RetainPtr<NSSearchFieldCell> m_search;
+ mutable RetainPtr<NSMenu> m_searchMenuTemplate;
+ mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal;
+ mutable RetainPtr<NSSliderCell> m_sliderThumbVertical;
+ mutable RetainPtr<NSLevelIndicatorCell> m_levelIndicator;
+ mutable RetainPtr<NSTextFieldCell> m_textField;
+
+ bool m_isSliderThumbHorizontalPressed;
+ bool m_isSliderThumbVerticalPressed;
+
+ mutable HashMap<int, RGBA32> m_systemColorCache;
+
+ RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeMacShared_h
diff --git a/Source/WebCore/rendering/RenderThemeMacShared.mm b/Source/WebCore/rendering/RenderThemeMacShared.mm
new file mode 100644
index 000000000..e6074cc26
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeMacShared.mm
@@ -0,0 +1,1835 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#import "config.h"
+#import "RenderThemeMacShared.h"
+
+#import "BitmapImage.h"
+#import "ColorMac.h"
+#import "CSSValueList.h"
+#import "CSSValueKeywords.h"
+#import "Document.h"
+#import "Element.h"
+#import "FileList.h"
+#import "FrameView.h"
+#import "GraphicsContextCG.h"
+#import "HTMLInputElement.h"
+#import "HTMLMediaElement.h"
+#import "HTMLNames.h"
+#import "Image.h"
+#import "ImageBuffer.h"
+#import "LocalCurrentGraphicsContext.h"
+#import "LocalizedStrings.h"
+#import "MediaControlElements.h"
+#import "PaintInfo.h"
+#import "RenderMedia.h"
+#import "RenderMediaControls.h"
+#import "RenderSlider.h"
+#import "RenderSnapshottedPlugIn.h"
+#import "RenderView.h"
+#import "SharedBuffer.h"
+#import "StringTruncator.h"
+#import "StyleResolver.h"
+#import "TimeRanges.h"
+#import "ThemeMac.h"
+#import "WebCoreNSCellExtras.h"
+#import "WebCoreSystemInterface.h"
+#import "UserAgentStyleSheets.h"
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/StdLibExtras.h>
+#import <math.h>
+
+#import "RenderProgress.h"
+
+#if ENABLE(METER_ELEMENT)
+#include "RenderMeter.h"
+#include "HTMLMeterElement.h"
+#endif
+
+using namespace std;
+
+// The methods in this file are specific to the Mac OS X platform.
+
+// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari.
+
+// We estimate the animation rate of a Mac OS X progress bar is 33 fps.
+// Hard code the value here because we haven't found API for it.
+const double progressAnimationFrameRate = 0.033;
+
+// Mac OS X progress bar animation seems to have 256 frames.
+const double progressAnimationNumFrames = 256;
+
+@interface WebCoreRenderThemeNotificationObserver : NSObject
+{
+ WebCore::RenderTheme *_theme;
+}
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme;
+- (void)systemColorsDidChange:(NSNotification *)notification;
+
+@end
+
+@implementation WebCoreRenderThemeNotificationObserver
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme
+{
+ if (!(self = [super init]))
+ return nil;
+
+ _theme = theme;
+ return self;
+}
+
+- (void)systemColorsDidChange:(NSNotification *)unusedNotification
+{
+ ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
+ _theme->platformColorsDidChange();
+}
+
+@end
+
+@interface NSTextFieldCell (WKDetails)
+- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
+@end
+
+
+@interface WebCoreTextFieldCell : NSTextFieldCell
+- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
+@end
+
+@implementation WebCoreTextFieldCell
+- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus
+{
+ // FIXME: This is a post-Lion-only workaround for <rdar://problem/11385461>. When that bug is resolved, we should remove this code.
+ CFMutableDictionaryRef coreUIDrawOptions = CFDictionaryCreateMutableCopy(NULL, 0, [super _coreUIDrawOptionsWithFrame:cellFrame inView:controlView includeFocus:includeFocus]);
+ CFDictionarySetValue(coreUIDrawOptions, @"borders only", kCFBooleanTrue);
+ return (CFDictionaryRef)[NSMakeCollectable(coreUIDrawOptions) autorelease];
+}
+@end
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+enum {
+ topMargin,
+ rightMargin,
+ bottomMargin,
+ leftMargin
+};
+
+enum {
+ topPadding,
+ rightPadding,
+ bottomPadding,
+ leftPadding
+};
+
+RenderThemeMacShared::RenderThemeMacShared()
+ : m_isSliderThumbHorizontalPressed(false)
+ , m_isSliderThumbVerticalPressed(false)
+ , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
+{
+ [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
+ selector:@selector(systemColorsDidChange:)
+ name:NSSystemColorsDidChangeNotification
+ object:nil];
+}
+
+RenderThemeMacShared::~RenderThemeMacShared()
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
+}
+
+Color RenderThemeMacShared::platformActiveSelectionBackgroundColor() const
+{
+ NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeMacShared::platformInactiveSelectionBackgroundColor() const
+{
+ NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeMacShared::platformActiveListBoxSelectionBackgroundColor() const
+{
+ NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeMacShared::platformActiveListBoxSelectionForegroundColor() const
+{
+ return Color::white;
+}
+
+Color RenderThemeMacShared::platformInactiveListBoxSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeMacShared::platformFocusRingColor() const
+{
+ if (usesTestModeFocusRingColor())
+ return oldAquaFocusRingColor();
+
+ return systemColor(CSSValueWebkitFocusRingColor);
+}
+
+Color RenderThemeMacShared::platformInactiveListBoxSelectionBackgroundColor() const
+{
+ return platformInactiveSelectionBackgroundColor();
+}
+
+static FontWeight toFontWeight(NSInteger appKitFontWeight)
+{
+ ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
+ if (appKitFontWeight > 14)
+ appKitFontWeight = 14;
+ else if (appKitFontWeight < 1)
+ appKitFontWeight = 1;
+
+ static FontWeight fontWeights[] = {
+ FontWeight100,
+ FontWeight100,
+ FontWeight200,
+ FontWeight300,
+ FontWeight400,
+ FontWeight500,
+ FontWeight600,
+ FontWeight600,
+ FontWeight700,
+ FontWeight800,
+ FontWeight800,
+ FontWeight900,
+ FontWeight900,
+ FontWeight900
+ };
+ return fontWeights[appKitFontWeight - 1];
+}
+
+void RenderThemeMacShared::systemFont(int cssValueId, FontDescription& fontDescription) const
+{
+ DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
+
+ FontDescription* cachedDesc;
+ NSFont* font = nil;
+ switch (cssValueId) {
+ case CSSValueSmallCaption:
+ cachedDesc = &smallSystemFont;
+ if (!smallSystemFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
+ break;
+ case CSSValueMenu:
+ cachedDesc = &menuFont;
+ if (!menuFont.isAbsoluteSize())
+ font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
+ break;
+ case CSSValueStatusBar:
+ cachedDesc = &labelFont;
+ if (!labelFont.isAbsoluteSize())
+ font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
+ break;
+ case CSSValueWebkitMiniControl:
+ cachedDesc = &miniControlFont;
+ if (!miniControlFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
+ break;
+ case CSSValueWebkitSmallControl:
+ cachedDesc = &smallControlFont;
+ if (!smallControlFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
+ break;
+ case CSSValueWebkitControl:
+ cachedDesc = &controlFont;
+ if (!controlFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+ break;
+ default:
+ cachedDesc = &systemFont;
+ if (!systemFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
+ }
+
+ if (font) {
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ cachedDesc->setIsAbsoluteSize(true);
+ cachedDesc->setGenericFamily(FontDescription::NoFamily);
+ cachedDesc->firstFamily().setFamily([font familyName]);
+ cachedDesc->setSpecifiedSize([font pointSize]);
+ cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
+ cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
+ }
+ fontDescription = *cachedDesc;
+}
+
+static RGBA32 convertNSColorToColor(NSColor *color)
+{
+ NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ if (colorInColorSpace) {
+ static const double scaleFactor = nextafter(256.0, 0.0);
+ return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
+ static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
+ static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
+ }
+
+ // This conversion above can fail if the NSColor in question is an NSPatternColor
+ // (as many system colors are). These colors are actually a repeating pattern
+ // not just a solid color. To work around this we simply draw a 1x1 image of
+ // the color and use that pixel's color. It might be better to use an average of
+ // the colors in the pattern instead.
+ NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+ pixelsWide:1
+ pixelsHigh:1
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSDeviceRGBColorSpace
+ bytesPerRow:4
+ bitsPerPixel:32];
+
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
+ NSEraseRect(NSMakeRect(0, 0, 1, 1));
+ [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
+ [NSGraphicsContext restoreGraphicsState];
+
+ NSUInteger pixel[4];
+ [offscreenRep getPixel:pixel atX:0 y:0];
+
+ [offscreenRep release];
+
+ return makeRGB(pixel[0], pixel[1], pixel[2]);
+}
+
+static RGBA32 menuBackgroundColor()
+{
+ NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+ pixelsWide:1
+ pixelsHigh:1
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSDeviceRGBColorSpace
+ bytesPerRow:4
+ bitsPerPixel:32];
+
+ CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
+ CGRect rect = CGRectMake(0, 0, 1, 1);
+ HIThemeMenuDrawInfo drawInfo;
+ drawInfo.version = 0;
+ drawInfo.menuType = kThemeMenuTypePopUp;
+ HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
+
+ NSUInteger pixel[4];
+ [offscreenRep getPixel:pixel atX:0 y:0];
+
+ [offscreenRep release];
+
+ return makeRGB(pixel[0], pixel[1], pixel[2]);
+}
+
+void RenderThemeMacShared::platformColorsDidChange()
+{
+ m_systemColorCache.clear();
+ RenderTheme::platformColorsDidChange();
+}
+
+Color RenderThemeMacShared::systemColor(int cssValueId) const
+{
+ {
+ HashMap<int, RGBA32>::iterator it = m_systemColorCache.find(cssValueId);
+ if (it != m_systemColorCache.end())
+ return it->value;
+ }
+
+ Color color;
+ switch (cssValueId) {
+ case CSSValueActiveborder:
+ color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+ break;
+ case CSSValueActivecaption:
+ color = convertNSColorToColor([NSColor windowFrameTextColor]);
+ break;
+ case CSSValueAppworkspace:
+ color = convertNSColorToColor([NSColor headerColor]);
+ break;
+ case CSSValueBackground:
+ // Use theme independent default
+ break;
+ case CSSValueButtonface:
+ // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
+ // We may want to change this to use the NSColor in future.
+ color = 0xFFC0C0C0;
+ break;
+ case CSSValueButtonhighlight:
+ color = convertNSColorToColor([NSColor controlHighlightColor]);
+ break;
+ case CSSValueButtonshadow:
+ color = convertNSColorToColor([NSColor controlShadowColor]);
+ break;
+ case CSSValueButtontext:
+ color = convertNSColorToColor([NSColor controlTextColor]);
+ break;
+ case CSSValueCaptiontext:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueGraytext:
+ color = convertNSColorToColor([NSColor disabledControlTextColor]);
+ break;
+ case CSSValueHighlight:
+ color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
+ break;
+ case CSSValueHighlighttext:
+ color = convertNSColorToColor([NSColor selectedTextColor]);
+ break;
+ case CSSValueInactiveborder:
+ color = convertNSColorToColor([NSColor controlBackgroundColor]);
+ break;
+ case CSSValueInactivecaption:
+ color = convertNSColorToColor([NSColor controlBackgroundColor]);
+ break;
+ case CSSValueInactivecaptiontext:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueInfobackground:
+ // There is no corresponding NSColor for this so we use a hard coded value.
+ color = 0xFFFBFCC5;
+ break;
+ case CSSValueInfotext:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueMenu:
+ color = menuBackgroundColor();
+ break;
+ case CSSValueMenutext:
+ color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
+ break;
+ case CSSValueScrollbar:
+ color = convertNSColorToColor([NSColor scrollBarColor]);
+ break;
+ case CSSValueText:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueThreeddarkshadow:
+ color = convertNSColorToColor([NSColor controlDarkShadowColor]);
+ break;
+ case CSSValueThreedshadow:
+ color = convertNSColorToColor([NSColor shadowColor]);
+ break;
+ case CSSValueThreedface:
+ // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
+ // We may want to change this to use the NSColor in future.
+ color = 0xFFC0C0C0;
+ break;
+ case CSSValueThreedhighlight:
+ color = convertNSColorToColor([NSColor highlightColor]);
+ break;
+ case CSSValueThreedlightshadow:
+ color = convertNSColorToColor([NSColor controlLightHighlightColor]);
+ break;
+ case CSSValueWebkitFocusRingColor:
+ color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+ break;
+ case CSSValueWindow:
+ color = convertNSColorToColor([NSColor windowBackgroundColor]);
+ break;
+ case CSSValueWindowframe:
+ color = convertNSColorToColor([NSColor windowFrameColor]);
+ break;
+ case CSSValueWindowtext:
+ color = convertNSColorToColor([NSColor windowFrameTextColor]);
+ break;
+ }
+
+ if (!color.isValid())
+ color = RenderTheme::systemColor(cssValueId);
+
+ if (color.isValid())
+ m_systemColorCache.set(cssValueId, color.rgb());
+
+ return color;
+}
+
+bool RenderThemeMacShared::usesTestModeFocusRingColor() const
+{
+ return WebCore::usesTestModeFocusRingColor();
+}
+
+bool RenderThemeMacShared::isControlStyled(const RenderStyle* style, const BorderData& border,
+ const FillLayer& background, const Color& backgroundColor) const
+{
+ if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
+ return style->border() != border;
+
+ // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
+ // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style
+ // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming
+ // is in effect we treat it like the control is styled.
+ if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
+ return true;
+
+ return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+}
+
+void RenderThemeMacShared::adjustRepaintRect(const RenderObject* o, IntRect& r)
+{
+ ControlPart part = o->style()->appearance();
+
+#if USE(NEW_THEME)
+ switch (part) {
+ case CheckboxPart:
+ case RadioPart:
+ case PushButtonPart:
+ case SquareButtonPart:
+ case DefaultButtonPart:
+ case ButtonPart:
+ case InnerSpinButtonPart:
+ return RenderTheme::adjustRepaintRect(o, r);
+ default:
+ break;
+ }
+#endif
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ if (part == MenulistPart) {
+ setPopupButtonCellState(o, r);
+ IntSize size = popupButtonSizes()[[popupButton() controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(r.width());
+ r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
+ }
+}
+
+IntRect RenderThemeMacShared::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
+{
+ // Only do the inflation if the available width/height are too small. Otherwise try to
+ // fit the glow/check space into the available box's width/height.
+ int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
+ int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
+ IntRect result(r);
+ if (widthDelta < 0) {
+ result.setX(result.x() - margins[leftMargin] * zoomLevel);
+ result.setWidth(result.width() - widthDelta);
+ }
+ if (heightDelta < 0) {
+ result.setY(result.y() - margins[topMargin] * zoomLevel);
+ result.setHeight(result.height() - heightDelta);
+ }
+ return result;
+}
+
+FloatRect RenderThemeMacShared::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
+{
+ FloatRect partRect(inputRect);
+
+ // Compute an offset between the part renderer and the input renderer
+ FloatSize offsetFromInputRenderer;
+ const RenderObject* renderer = partRenderer;
+ while (renderer && renderer != inputRenderer) {
+ RenderObject* containingRenderer = renderer->container();
+ offsetFromInputRenderer -= roundedIntSize(renderer->offsetFromContainer(containingRenderer, LayoutPoint()));
+ renderer = containingRenderer;
+ }
+ // If the input renderer was not a container, something went wrong
+ ASSERT(renderer == inputRenderer);
+ // Move the rect into partRenderer's coords
+ partRect.move(offsetFromInputRenderer);
+ // Account for the local drawing offset (tx, ty)
+ partRect.move(r.x(), r.y());
+
+ return partRect;
+}
+
+void RenderThemeMacShared::updateCheckedState(NSCell* cell, const RenderObject* o)
+{
+ bool oldIndeterminate = [cell state] == NSMixedState;
+ bool indeterminate = isIndeterminate(o);
+ bool checked = isChecked(o);
+
+ if (oldIndeterminate != indeterminate) {
+ [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
+ return;
+ }
+
+ bool oldChecked = [cell state] == NSOnState;
+ if (checked != oldChecked)
+ [cell setState:checked ? NSOnState : NSOffState];
+}
+
+void RenderThemeMacShared::updateEnabledState(NSCell* cell, const RenderObject* o)
+{
+ bool oldEnabled = [cell isEnabled];
+ bool enabled = isEnabled(o);
+ if (enabled != oldEnabled)
+ [cell setEnabled:enabled];
+}
+
+void RenderThemeMacShared::updateFocusedState(NSCell* cell, const RenderObject* o)
+{
+ bool oldFocused = [cell showsFirstResponder];
+ bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
+ if (focused != oldFocused)
+ [cell setShowsFirstResponder:focused];
+}
+
+void RenderThemeMacShared::updatePressedState(NSCell* cell, const RenderObject* o)
+{
+ bool oldPressed = [cell isHighlighted];
+ bool pressed = (o->node() && o->node()->active());
+ if (pressed != oldPressed)
+ [cell setHighlighted:pressed];
+}
+
+bool RenderThemeMacShared::controlSupportsTints(const RenderObject* o) const
+{
+ // An alternate way to implement this would be to get the appropriate cell object
+ // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
+ // that would be that we would match AppKit behavior more closely, but a disadvantage
+ // would be that we would rely on an AppKit SPI method.
+
+ if (!isEnabled(o))
+ return false;
+
+ // Checkboxes only have tint when checked.
+ if (o->style()->appearance() == CheckboxPart)
+ return isChecked(o);
+
+ // For now assume other controls have tint if enabled.
+ return true;
+}
+
+NSControlSize RenderThemeMacShared::controlSizeForFont(RenderStyle* style) const
+{
+ int fontSize = style->fontSize();
+ if (fontSize >= 16)
+ return NSRegularControlSize;
+ if (fontSize >= 11)
+ return NSSmallControlSize;
+ return NSMiniControlSize;
+}
+
+void RenderThemeMacShared::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
+{
+ NSControlSize size;
+ if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
+ minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
+ size = NSRegularControlSize;
+ else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
+ minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
+ size = NSSmallControlSize;
+ else
+ size = NSMiniControlSize;
+ if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
+ [cell setControlSize:size];
+}
+
+IntSize RenderThemeMacShared::sizeForFont(RenderStyle* style, const IntSize* sizes) const
+{
+ if (style->effectiveZoom() != 1.0f) {
+ IntSize result = sizes[controlSizeForFont(style)];
+ return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
+ }
+ return sizes[controlSizeForFont(style)];
+}
+
+IntSize RenderThemeMacShared::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
+{
+ if (style->effectiveZoom() != 1.0f) {
+ IntSize result = sizes[controlSizeForSystemFont(style)];
+ return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
+ }
+ return sizes[controlSizeForSystemFont(style)];
+}
+
+void RenderThemeMacShared::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
+{
+ // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
+ IntSize size = sizeForFont(style, sizes);
+ if (style->width().isIntrinsicOrAuto() && size.width() > 0)
+ style->setWidth(Length(size.width(), Fixed));
+ if (style->height().isAuto() && size.height() > 0)
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+void RenderThemeMacShared::setFontFromControlSize(StyleResolver*, RenderStyle* style, NSControlSize controlSize) const
+{
+ FontDescription fontDescription;
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::SerifFamily);
+
+ NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
+ fontDescription.firstFamily().setFamily([font familyName]);
+ fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
+ fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
+
+ // Reset line height
+ style->setLineHeight(RenderStyle::initialLineHeight());
+
+ if (style->setFontDescription(fontDescription))
+ style->font().update(0);
+}
+
+NSControlSize RenderThemeMacShared::controlSizeForSystemFont(RenderStyle* style) const
+{
+ int fontSize = style->fontSize();
+ if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
+ return NSRegularControlSize;
+ if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
+ return NSSmallControlSize;
+ return NSMiniControlSize;
+}
+
+bool RenderThemeMacShared::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
+ bool useNSTextFieldCell = o->style()->hasAppearance()
+ && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white
+ && !o->style()->hasBackgroundImage();
+
+ // We do not use NSTextFieldCell to draw styled text fields on Lion and SnowLeopard because
+ // there are a number of bugs on those platforms that require NSTextFieldCell to be in charge
+ // of painting its own background. We need WebCore to paint styled backgrounds, so we'll use
+ // this WebCoreSystemInterface function instead.
+ if (!useNSTextFieldCell) {
+ wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
+ return false;
+ }
+#endif
+
+ NSTextFieldCell *textField = this->textField();
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ [textField setEnabled:(isEnabled(o) && !isReadOnlyControl(o))];
+ [textField drawWithFrame:NSRect(r) inView:documentViewFor(o)];
+
+ [textField setControlView:nil];
+
+ return false;
+}
+
+void RenderThemeMacShared::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeMacShared::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
+{
+ if (paintInfo.context->paintingDisabled())
+ return true;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawCapsLockIndicator(localContext.cgContext(), r);
+
+ return false;
+}
+
+bool RenderThemeMacShared::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
+ return false;
+}
+
+void RenderThemeMacShared::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+const int* RenderThemeMacShared::popupButtonMargins() const
+{
+ static const int margins[3][4] =
+ {
+ { 0, 3, 1, 3 },
+ { 0, 3, 2, 3 },
+ { 0, 1, 0, 1 }
+ };
+ return margins[[popupButton() controlSize]];
+}
+
+const IntSize* RenderThemeMacShared::popupButtonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+ return sizes;
+}
+
+const int* RenderThemeMacShared::popupButtonPadding(NSControlSize size) const
+{
+ static const int padding[3][4] =
+ {
+ { 2, 26, 3, 8 },
+ { 2, 23, 3, 8 },
+ { 2, 22, 3, 10 }
+ };
+ return padding[size];
+}
+
+bool RenderThemeMacShared::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ setPopupButtonCellState(o, r);
+
+ NSPopUpButtonCell* popupButton = this->popupButton();
+
+ float zoomLevel = o->style()->effectiveZoom();
+ IntSize size = popupButtonSizes()[[popupButton controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(r.width());
+
+ // Now inflate it to account for the shadow.
+ IntRect inflatedRect = r;
+ if (r.width() >= minimumMenuListSize(o->style()))
+ inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
+ paintInfo.context->clip(inflatedRect);
+
+ if (zoomLevel != 1.0f) {
+ inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
+ inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
+ paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
+ }
+
+ NSView *view = documentViewFor(o);
+ [popupButton drawWithFrame:inflatedRect inView:view];
+#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
+ if (isFocused(o) && o->style()->outlineStyleIsAuto())
+ [popupButton _web_drawFocusRingWithFrame:inflatedRect inView:view];
+#endif
+ [popupButton setControlView:nil];
+
+ return false;
+}
+
+#if ENABLE(METER_ELEMENT)
+
+IntSize RenderThemeMacShared::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
+{
+ if (NoControlPart == renderMeter->style()->appearance())
+ return bounds.size();
+
+ NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
+ // Makes enough room for cell's intrinsic size.
+ NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
+ return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
+ bounds.height() < cellSize.height ? cellSize.height : bounds.height());
+}
+
+bool RenderThemeMacShared::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ if (!renderObject->isMeter())
+ return true;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ [cell drawWithFrame:rect inView:documentViewFor(renderObject)];
+ [cell setControlView:nil];
+ return false;
+}
+
+bool RenderThemeMacShared::supportsMeter(ControlPart part) const
+{
+ switch (part) {
+ case RelevancyLevelIndicatorPart:
+ case DiscreteCapacityLevelIndicatorPart:
+ case RatingLevelIndicatorPart:
+ case MeterPart:
+ case ContinuousCapacityLevelIndicatorPart:
+ return true;
+ default:
+ return false;
+ }
+}
+
+NSLevelIndicatorStyle RenderThemeMacShared::levelIndicatorStyleFor(ControlPart part) const
+{
+ switch (part) {
+ case RelevancyLevelIndicatorPart:
+ return NSRelevancyLevelIndicatorStyle;
+ case DiscreteCapacityLevelIndicatorPart:
+ return NSDiscreteCapacityLevelIndicatorStyle;
+ case RatingLevelIndicatorPart:
+ return NSRatingLevelIndicatorStyle;
+ case MeterPart:
+ case ContinuousCapacityLevelIndicatorPart:
+ default:
+ return NSContinuousCapacityLevelIndicatorStyle;
+ }
+
+}
+
+NSLevelIndicatorCell* RenderThemeMacShared::levelIndicatorFor(const RenderMeter* renderMeter) const
+{
+ RenderStyle* style = renderMeter->style();
+ ASSERT(style->appearance() != NoControlPart);
+
+ if (!m_levelIndicator)
+ m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]);
+ NSLevelIndicatorCell* cell = m_levelIndicator.get();
+
+ HTMLMeterElement* element = renderMeter->meterElement();
+ double value = element->value();
+
+ // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring,
+ // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is.
+ switch (element->gaugeRegion()) {
+ case HTMLMeterElement::GaugeRegionOptimum:
+ // Make meter the green
+ [cell setWarningValue:value + 1];
+ [cell setCriticalValue:value + 2];
+ break;
+ case HTMLMeterElement::GaugeRegionSuboptimal:
+ // Make the meter yellow
+ [cell setWarningValue:value - 1];
+ [cell setCriticalValue:value + 1];
+ break;
+ case HTMLMeterElement::GaugeRegionEvenLessGood:
+ // Make the meter red
+ [cell setWarningValue:value - 2];
+ [cell setCriticalValue:value - 1];
+ break;
+ }
+
+ [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())];
+ [cell setBaseWritingDirection:style->isLeftToRightDirection() ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft];
+ [cell setMinValue:element->min()];
+ [cell setMaxValue:element->max()];
+ RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value];
+ [cell setObjectValue:valueObject.get()];
+
+ return cell;
+}
+
+#endif
+
+#if ENABLE(PROGRESS_ELEMENT)
+const IntSize* RenderThemeMacShared::progressBarSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(0, 20), IntSize(0, 12), IntSize(0, 12) };
+ return sizes;
+}
+
+const int* RenderThemeMacShared::progressBarMargins(NSControlSize controlSize) const
+{
+ static const int margins[3][4] =
+ {
+ { 0, 0, 1, 0 },
+ { 0, 0, 1, 0 },
+ { 0, 0, 1, 0 },
+ };
+ return margins[controlSize];
+}
+
+int RenderThemeMacShared::minimumProgressBarHeight(RenderStyle* style) const
+{
+ return sizeForSystemFont(style, progressBarSizes()).height();
+}
+
+double RenderThemeMacShared::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+ return progressAnimationFrameRate;
+}
+
+double RenderThemeMacShared::animationDurationForProgressBar(RenderProgress*) const
+{
+ return progressAnimationNumFrames * progressAnimationFrameRate;
+}
+
+void RenderThemeMacShared::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeMacShared::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ if (!renderObject->isProgress())
+ return true;
+
+ float zoomLevel = renderObject->style()->effectiveZoom();
+ int controlSize = controlSizeForFont(renderObject->style());
+ IntSize size = progressBarSizes()[controlSize];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(rect.width());
+
+ // Now inflate it to account for the shadow.
+ IntRect inflatedRect = rect;
+ if (rect.height() <= minimumProgressBarHeight(renderObject->style()))
+ inflatedRect = inflateRect(inflatedRect, size, progressBarMargins(controlSize), zoomLevel);
+
+ RenderProgress* renderProgress = toRenderProgress(renderObject);
+ HIThemeTrackDrawInfo trackInfo;
+ trackInfo.version = 0;
+ if (controlSize == NSRegularControlSize)
+ trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar;
+ else
+ trackInfo.kind = renderProgress->position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar;
+
+ trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size());
+ trackInfo.min = 0;
+ trackInfo.max = numeric_limits<SInt32>::max();
+ trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0));
+ trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0));
+ trackInfo.attributes = kThemeTrackHorizontal;
+ trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive;
+ trackInfo.reserved = 0;
+ trackInfo.filler1 = 0;
+
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size(), 1);
+ if (!imageBuffer)
+ return true;
+
+ ContextContainer cgContextContainer(imageBuffer->context());
+ CGContextRef cgContext = cgContextContainer.context();
+ HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ if (!renderProgress->style()->isLeftToRightDirection()) {
+ paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0);
+ paintInfo.context->scale(FloatSize(-1, 1));
+ }
+
+ paintInfo.context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, inflatedRect.location());
+ return false;
+}
+#endif
+
+const float baseFontSize = 11.0f;
+const float baseArrowHeight = 4.0f;
+const float baseArrowWidth = 5.0f;
+const float baseSpaceBetweenArrows = 2.0f;
+const int arrowPaddingLeft = 6;
+const int arrowPaddingRight = 6;
+const int paddingBeforeSeparator = 4;
+const int baseBorderRadius = 5;
+const int styledPopupPaddingLeft = 8;
+const int styledPopupPaddingTop = 1;
+const int styledPopupPaddingBottom = 2;
+
+static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
+ static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
+ static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
+ static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
+ static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+void RenderThemeMacShared::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ if (r.isEmpty())
+ return;
+
+ ContextContainer cgContextContainer(paintInfo.context);
+ CGContextRef context = cgContextContainer.context();
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ RoundedRect border = o->style()->getRoundedBorderFor(r, o->view());
+ int radius = border.radii().topLeft().width();
+
+ CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
+
+ FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
+ struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
+ RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), topFunction.get(), false, false));
+
+ FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
+ struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
+ RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), bottomFunction.get(), false, false));
+
+ struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+ RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false));
+
+ RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
+
+ RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.maxX(), r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false));
+
+ {
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ CGContextClipToRect(context, r);
+ paintInfo.context->addRoundedRectClip(border);
+ context = cgContextContainer.context();
+ CGContextDrawShading(context, mainShading.get());
+ }
+
+ {
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ CGContextClipToRect(context, topGradient);
+ paintInfo.context->addRoundedRectClip(RoundedRect(enclosingIntRect(topGradient), border.radii().topLeft(), border.radii().topRight(), IntSize(), IntSize()));
+ context = cgContextContainer.context();
+ CGContextDrawShading(context, topShading.get());
+ }
+
+ if (!bottomGradient.isEmpty()) {
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ CGContextClipToRect(context, bottomGradient);
+ paintInfo.context->addRoundedRectClip(RoundedRect(enclosingIntRect(bottomGradient), IntSize(), IntSize(), border.radii().bottomLeft(), border.radii().bottomRight()));
+ context = cgContextContainer.context();
+ CGContextDrawShading(context, bottomShading.get());
+ }
+
+ {
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ CGContextClipToRect(context, r);
+ paintInfo.context->addRoundedRectClip(border);
+ context = cgContextContainer.context();
+ CGContextDrawShading(context, leftShading.get());
+ CGContextDrawShading(context, rightShading.get());
+ }
+}
+
+bool RenderThemeMacShared::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
+ r.y() + o->style()->borderTopWidth(),
+ r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
+ r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
+ // Draw the gradients to give the styled popup menu a button appearance
+ paintMenuListButtonGradients(o, paintInfo, bounds);
+
+ // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
+ float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
+ float centerY = bounds.y() + bounds.height() / 2.0f;
+ float arrowHeight = baseArrowHeight * fontScale;
+ float arrowWidth = baseArrowWidth * fontScale;
+ float leftEdge = bounds.maxX() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
+ float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
+
+ if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
+ return false;
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), o->style()->colorSpace());
+ paintInfo.context->setStrokeStyle(NoStroke);
+
+ FloatPoint arrow1[3];
+ arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
+ arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
+ arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
+
+ // Draw the top arrow
+ paintInfo.context->drawConvexPolygon(3, arrow1, true);
+
+ FloatPoint arrow2[3];
+ arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
+ arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
+ arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
+
+ // Draw the bottom arrow
+ paintInfo.context->drawConvexPolygon(3, arrow2, true);
+
+ Color leftSeparatorColor(0, 0, 0, 40);
+ Color rightSeparatorColor(255, 255, 255, 40);
+
+ // FIXME: Should the separator thickness and space be scaled up by fontScale?
+ int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
+ int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
+
+ // Draw the separator to the left of the arrows
+ paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
+ paintInfo.context->setStrokeStyle(SolidStroke);
+ paintInfo.context->setStrokeColor(leftSeparatorColor, ColorSpaceDeviceRGB);
+ paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
+ IntPoint(leftEdgeOfSeparator, bounds.maxY()));
+
+ paintInfo.context->setStrokeColor(rightSeparatorColor, ColorSpaceDeviceRGB);
+ paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
+ IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
+ return false;
+}
+
+static const IntSize* menuListButtonSizes()
+{
+ static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+ return sizes;
+}
+
+void RenderThemeMacShared::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
+{
+ NSControlSize controlSize = controlSizeForFont(style);
+
+ style->resetBorder();
+ style->resetPadding();
+
+ // Height is locked to auto.
+ style->setHeight(Length(Auto));
+
+ // White-space is locked to pre
+ style->setWhiteSpace(PRE);
+
+ // Set the foreground color to black or gray when we have the aqua look.
+ // Cast to RGB32 is to work around a compiler bug.
+ style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
+
+ // Set the button's vertical size.
+ setSizeFromFont(style, menuListButtonSizes());
+
+ // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
+ // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+ // system font for the control size instead.
+ setFontFromControlSize(styleResolver, style, controlSize);
+
+ style->setBoxShadow(nullptr);
+}
+
+int RenderThemeMacShared::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart)
+ return styledPopupPaddingLeft * style->effectiveZoom();
+ return 0;
+}
+
+int RenderThemeMacShared::popupInternalPaddingRight(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart) {
+ float fontScale = style->fontSize() / baseFontSize;
+ float arrowWidth = baseArrowWidth * fontScale;
+ return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
+ }
+ return 0;
+}
+
+int RenderThemeMacShared::popupInternalPaddingTop(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart)
+ return styledPopupPaddingTop * style->effectiveZoom();
+ return 0;
+}
+
+int RenderThemeMacShared::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart)
+ return styledPopupPaddingBottom * style->effectiveZoom();
+ return 0;
+}
+
+void RenderThemeMacShared::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ float fontScale = style->fontSize() / baseFontSize;
+
+ style->resetPadding();
+ style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
+
+ const int minHeight = 15;
+ style->setMinHeight(Length(minHeight, Fixed));
+
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+void RenderThemeMacShared::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
+{
+ NSPopUpButtonCell* popupButton = this->popupButton();
+
+ // Set the control size based off the rectangle we're painting into.
+ setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
+
+ // Update the various states we respond to.
+ updateActiveState(popupButton, o);
+ updateCheckedState(popupButton, o);
+ updateEnabledState(popupButton, o);
+ updatePressedState(popupButton, o);
+#if BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
+ updateFocusedState(popupButton, o);
+#endif
+}
+
+const IntSize* RenderThemeMacShared::menuListSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
+ return sizes;
+}
+
+int RenderThemeMacShared::minimumMenuListSize(RenderStyle* style) const
+{
+ return sizeForSystemFont(style, menuListSizes()).width();
+}
+
+const int trackWidth = 5;
+const int trackRadius = 2;
+
+void RenderThemeMacShared::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeMacShared::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ IntRect bounds = r;
+ float zoomLevel = o->style()->effectiveZoom();
+ float zoomedTrackWidth = trackWidth * zoomLevel;
+
+ if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) {
+ bounds.setHeight(zoomedTrackWidth);
+ bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
+ } else if (o->style()->appearance() == SliderVerticalPart) {
+ bounds.setWidth(zoomedTrackWidth);
+ bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
+ }
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ CGContextRef context = localContext.cgContext();
+ CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
+
+#if ENABLE(DATALIST_ELEMENT)
+ paintSliderTicks(o, paintInfo, r);
+#endif
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ CGContextClipToRect(context, bounds);
+
+ struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+ RetainPtr<CGShadingRef> mainShading;
+ if (o->style()->appearance() == SliderVerticalPart)
+ mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(), bounds.maxY()), CGPointMake(bounds.maxX(), bounds.maxY()), mainFunction.get(), false, false));
+ else
+ mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.maxY()), mainFunction.get(), false, false));
+
+ IntSize radius(trackRadius, trackRadius);
+ paintInfo.context->addRoundedRectClip(RoundedRect(bounds, radius, radius, radius, radius));
+ context = localContext.cgContext();
+ CGContextDrawShading(context, mainShading.get());
+
+ return false;
+}
+
+void RenderThemeMacShared::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
+{
+ RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
+ style->setBoxShadow(nullptr);
+}
+
+const float verticalSliderHeightPadding = 0.1f;
+
+bool RenderThemeMacShared::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
+ ? sliderThumbVertical()
+ : sliderThumbHorizontal();
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ // Update the various states we respond to.
+ updateActiveState(sliderThumbCell, o);
+ updateEnabledState(sliderThumbCell, o);
+ updateFocusedState(sliderThumbCell, (o->node() && o->node()->focusDelegate()->renderer()) ? o->node()->focusDelegate()->renderer() : o);
+
+ // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
+ bool oldPressed;
+ if (o->style()->appearance() == SliderThumbVerticalPart)
+ oldPressed = m_isSliderThumbVerticalPressed;
+ else
+ oldPressed = m_isSliderThumbHorizontalPressed;
+
+ bool pressed = isPressed(o);
+
+ if (o->style()->appearance() == SliderThumbVerticalPart)
+ m_isSliderThumbVerticalPressed = pressed;
+ else
+ m_isSliderThumbHorizontalPressed = pressed;
+
+ if (pressed != oldPressed) {
+ if (pressed)
+ [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
+ else
+ [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
+ }
+
+ FloatRect bounds = r;
+ // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
+ if (o->style()->appearance() == SliderThumbVerticalPart)
+ bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ float zoomLevel = o->style()->effectiveZoom();
+
+ FloatRect unzoomedRect = bounds;
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+#if PLATFORM(CHROMIUM)
+ paintInfo.context->translate(0, unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(1, -1));
+ paintInfo.context->translate(0, -(unzoomedRect.y() + unzoomedRect.height()));
+#endif
+
+ [sliderThumbCell drawInteriorWithFrame:unzoomedRect inView:documentViewFor(o)];
+ [sliderThumbCell setControlView:nil];
+
+ return false;
+}
+
+bool RenderThemeMacShared::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ NSSearchFieldCell* search = this->search();
+
+ setSearchCellState(o, r);
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ IntRect unzoomedRect = r;
+
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ // Set the search button to nil before drawing. Then reset it so we can draw it later.
+ [search setSearchButtonCell:nil];
+
+ [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)];
+
+ [search setControlView:nil];
+ [search resetSearchButtonCell];
+
+ return false;
+}
+
+void RenderThemeMacShared::setSearchCellState(RenderObject* o, const IntRect&)
+{
+ NSSearchFieldCell* search = this->search();
+
+ [search setControlSize:controlSizeForFont(o->style())];
+
+ // Update the various states we respond to.
+ updateActiveState(search, o);
+ updateEnabledState(search, o);
+ updateFocusedState(search, o);
+}
+
+const IntSize* RenderThemeMacShared::searchFieldSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
+ return sizes;
+}
+
+void RenderThemeMacShared::setSearchFieldSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // Use the font size to determine the intrinsic width of the control.
+ setSizeFromFont(style, searchFieldSizes());
+}
+
+void RenderThemeMacShared::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element*) const
+{
+ // Override border.
+ style->resetBorder();
+ const short borderWidth = 2 * style->effectiveZoom();
+ style->setBorderLeftWidth(borderWidth);
+ style->setBorderLeftStyle(INSET);
+ style->setBorderRightWidth(borderWidth);
+ style->setBorderRightStyle(INSET);
+ style->setBorderBottomWidth(borderWidth);
+ style->setBorderBottomStyle(INSET);
+ style->setBorderTopWidth(borderWidth);
+ style->setBorderTopStyle(INSET);
+
+ // Override height.
+ style->setHeight(Length(Auto));
+ setSearchFieldSize(style);
+
+ // Override padding size to match AppKit text positioning.
+ const int padding = 1 * style->effectiveZoom();
+ style->setPaddingLeft(Length(padding, Fixed));
+ style->setPaddingRight(Length(padding, Fixed));
+ style->setPaddingTop(Length(padding, Fixed));
+ style->setPaddingBottom(Length(padding, Fixed));
+
+ NSControlSize controlSize = controlSizeForFont(style);
+ setFontFromControlSize(styleResolver, style, controlSize);
+
+ style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeMacShared::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ Element* input = o->node()->shadowHost();
+ if (!input)
+ input = toElement(o->node());
+
+ if (!input->renderer()->isBox())
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ setSearchCellState(input->renderer(), r);
+
+ NSSearchFieldCell* search = this->search();
+
+ if (input->isEnabledFormControl() && (input->isTextFormControl() && !static_cast<HTMLTextFormControlElement*>(input)->readOnly())) {
+ updateActiveState([search cancelButtonCell], o);
+ updatePressedState([search cancelButtonCell], o);
+ }
+ else if ([[search cancelButtonCell] isHighlighted])
+ [[search cancelButtonCell] setHighlighted:NO];
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
+
+#if ENABLE(INPUT_SPEECH)
+ // Take care of cases where the cancel button was not aligned with the right border of the input element (for e.g.
+ // when speech input is enabled for the input element.
+ IntRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
+ int absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
+ int spaceToRightOfCancelButton = absRight - (r.x() + r.width());
+ localBounds.setX(localBounds.x() - spaceToRightOfCancelButton);
+#endif
+
+ localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+ FloatRect unzoomedRect(localBounds);
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
+ [[search cancelButtonCell] setControlView:nil];
+ return false;
+}
+
+const IntSize* RenderThemeMacShared::cancelButtonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
+ return sizes;
+}
+
+void RenderThemeMacShared::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ IntSize size = sizeForSystemFont(style, cancelButtonSizes());
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(nullptr);
+}
+
+const IntSize* RenderThemeMacShared::resultsButtonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
+ return sizes;
+}
+
+const int emptyResultsOffset = 9;
+void RenderThemeMacShared::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+ style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeMacShared::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&)
+{
+ return false;
+}
+
+void RenderThemeMacShared::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeMacShared::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* input = o->node()->shadowHost();
+ if (!input)
+ input = o->node();
+ if (!input->renderer()->isBox())
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ setSearchCellState(input->renderer(), r);
+
+ NSSearchFieldCell* search = this->search();
+
+ if ([search searchMenuTemplate] != nil)
+ [search setSearchMenuTemplate:nil];
+
+ updateActiveState([search searchButtonCell], o);
+
+ FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
+ localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+ [[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)];
+ [[search searchButtonCell] setControlView:nil];
+ return false;
+}
+
+const int resultsArrowWidth = 5;
+void RenderThemeMacShared::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+ IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+ style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeMacShared::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* input = o->node()->shadowHost();
+ if (!input)
+ input = o->node();
+ if (!input->renderer()->isBox())
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ setSearchCellState(input->renderer(), r);
+
+ NSSearchFieldCell* search = this->search();
+
+ updateActiveState([search searchButtonCell], o);
+
+ if (![search searchMenuTemplate])
+ [search setSearchMenuTemplate:searchMenuTemplate()];
+
+ GraphicsContextStateSaver stateSaver(*paintInfo.context);
+ float zoomLevel = o->style()->effectiveZoom();
+
+ FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
+ localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+ IntRect unzoomedRect(localBounds);
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
+ [[search searchButtonCell] setControlView:nil];
+
+ return false;
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+IntSize RenderThemeMacShared::sliderTickSize() const
+{
+ return IntSize(1, 3);
+}
+
+int RenderThemeMacShared::sliderTickOffsetFromTrackCenter() const
+{
+ return -9;
+}
+#endif
+
+const int sliderThumbWidth = 15;
+const int sliderThumbHeight = 15;
+
+void RenderThemeMacShared::adjustSliderThumbSize(RenderStyle* style, Element*) const
+{
+ float zoomLevel = style->effectiveZoom();
+ if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) {
+ style->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
+ style->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
+ }
+
+#if ENABLE(VIDEO)
+ adjustMediaSliderThumbSize(style);
+#endif
+}
+
+bool RenderThemeMacShared::shouldShowPlaceholderWhenFocused() const
+{
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+ return true;
+#else
+ return false;
+#endif
+}
+
+NSPopUpButtonCell* RenderThemeMacShared::popupButton() const
+{
+ if (!m_popupButton) {
+ m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
+ [m_popupButton.get() setUsesItemFromMenu:NO];
+ [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_popupButton.get();
+}
+
+NSSearchFieldCell* RenderThemeMacShared::search() const
+{
+ if (!m_search) {
+ m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
+ [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
+ [m_search.get() setBezeled:YES];
+ [m_search.get() setEditable:YES];
+ [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_search.get();
+}
+
+NSMenu* RenderThemeMacShared::searchMenuTemplate() const
+{
+ if (!m_searchMenuTemplate)
+ m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
+
+ return m_searchMenuTemplate.get();
+}
+
+NSSliderCell* RenderThemeMacShared::sliderThumbHorizontal() const
+{
+ if (!m_sliderThumbHorizontal) {
+ m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
+ [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
+ [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
+ [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_sliderThumbHorizontal.get();
+}
+
+NSSliderCell* RenderThemeMacShared::sliderThumbVertical() const
+{
+ if (!m_sliderThumbVertical) {
+ m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
+ [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
+ [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
+ [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_sliderThumbVertical.get();
+}
+
+NSTextFieldCell* RenderThemeMacShared::textField() const
+{
+ if (!m_textField) {
+ m_textField.adoptNS([[WebCoreTextFieldCell alloc] initTextCell:@""]);
+ [m_textField.get() setBezeled:YES];
+ [m_textField.get() setEditable:YES];
+ [m_textField.get() setFocusRingType:NSFocusRingTypeExterior];
+#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
+ [m_textField.get() setDrawsBackground:YES];
+ [m_textField.get() setBackgroundColor:[NSColor whiteColor]];
+#else
+ // Post-Lion, WebCore can be in charge of paintinng the background thanks to
+ // the workaround in place for <rdar://problem/11385461>, which is implemented
+ // above as _coreUIDrawOptionsWithFrame.
+ [m_textField.get() setDrawsBackground:NO];
+#endif
+ }
+
+ return m_textField.get();
+}
+
+String RenderThemeMacShared::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
+{
+ if (width <= 0)
+ return String();
+
+ String strToTruncate;
+ if (fileList->isEmpty())
+ strToTruncate = fileListDefaultLabel(multipleFilesAllowed);
+ else if (fileList->length() == 1)
+ strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(fileList->item(0)->path())];
+ else
+ return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
+
+ return StringTruncator::centerTruncate(strToTruncate, width, font, StringTruncator::EnableRoundingHacks);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeWin.cpp b/Source/WebCore/rendering/RenderThemeWin.cpp
index 810a1fca4..49ab18606 100644
--- a/Source/WebCore/rendering/RenderThemeWin.cpp
+++ b/Source/WebCore/rendering/RenderThemeWin.cpp
@@ -785,6 +785,8 @@ void RenderThemeWin::adjustMenuListButtonStyle(StyleResolver* styleResolver, Ren
minHeight = max(minHeight, dropDownBoxMinHeight);
style->setMinHeight(Length(minHeight, Fixed));
+
+ style->setLineHeight(RenderStyle::initialLineHeight());
// White-space is locked to pre
style->setWhiteSpace(PRE);
diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp
index 6c08789d4..5b4eb7358 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/RenderTreeAsText.cpp
@@ -726,7 +726,7 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
// Calculate the clip rects we should use.
LayoutRect layerBounds;
ClipRect damageRect, clipRectToApply, outlineRect;
- l->calculateRects(rootLayer, 0, TemporaryClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+ l->calculateRects(RenderLayer::ClipRectsContext(rootLayer, 0, TemporaryClipRects), paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
// Ensure our lists are up-to-date.
l->updateLayerListsIfNeeded();
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp
index 54f807057..c23a9de20 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp
@@ -44,6 +44,7 @@ using namespace MathMLNames;
RenderMathMLBlock::RenderMathMLBlock(Node* container)
: RenderFlexibleBox(container)
+ , m_ignoreInAccessibilityTree(false)
, m_intrinsicPaddingBefore(0)
, m_intrinsicPaddingAfter(0)
, m_intrinsicPaddingStart(0)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h
index 36e62ad67..51e80ec0a 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h
@@ -48,6 +48,12 @@ public:
virtual bool isRenderMathMLOperator() const { return false; }
virtual bool isRenderMathMLRow() const { return false; }
virtual bool isRenderMathMLMath() const { return false; }
+ virtual bool isRenderMathMLFenced() const { return false; }
+ virtual bool isRenderMathMLFraction() const { return false; }
+ virtual bool isRenderMathMLRoot() const { return false; }
+ virtual bool isRenderMathMLSquareRoot() const { return false; }
+ virtual bool isRenderMathMLSubSup() const { return false; }
+ virtual bool isRenderMathMLUnderOver() const { return false; }
// MathML defines an "embellished operator" as roughly an <mo> that may have subscripts,
// superscripts, underscripts, overscripts, or a denominator (as in d/dx, where "d" is some
@@ -87,8 +93,12 @@ public:
// Create a new RenderMathMLBlock, with a new style inheriting from this->style().
RenderMathMLBlock* createAnonymousMathMLBlock(EDisplay = FLEX);
+ void setIgnoreInAccessibilityTree(bool flag) { m_ignoreInAccessibilityTree = flag; }
+ bool ignoreInAccessibilityTree() const { return m_ignoreInAccessibilityTree; }
+
private:
virtual const char* renderName() const OVERRIDE;
+ bool m_ignoreInAccessibilityTree;
protected:
// Set our logical width to a large value, and compute our children's preferred logical heights.
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
index f35c336eb..96f6cbabc 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
@@ -82,22 +82,23 @@ void RenderMathMLFenced::updateFromElement()
makeFences();
}
-RenderMathMLOperator* RenderMathMLFenced::createMathMLOperator(UChar uChar, OperatorType operatorType)
+RenderMathMLOperator* RenderMathMLFenced::createMathMLOperator(UChar uChar, RenderMathMLOperator::OperatorType operatorType)
{
RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), FLEX);
newStyle->setFlexDirection(FlowColumn);
- newStyle->setMarginEnd(Length((operatorType == Fence ? gFenceMarginEms : gSeparatorMarginEndEms) * style()->fontSize(), Fixed));
- if (operatorType == Fence)
+ newStyle->setMarginEnd(Length((operatorType == RenderMathMLOperator::Fence ? gFenceMarginEms : gSeparatorMarginEndEms) * style()->fontSize(), Fixed));
+ if (operatorType == RenderMathMLOperator::Fence)
newStyle->setMarginStart(Length(gFenceMarginEms * style()->fontSize(), Fixed));
RenderMathMLOperator* newOperator = new (renderArena()) RenderMathMLOperator(node() /* "almost anonymous" */, uChar);
+ newOperator->setOperatorType(operatorType);
newOperator->setStyle(newStyle.release());
return newOperator;
}
void RenderMathMLFenced::makeFences()
{
- RenderMathMLRow::addChild(createMathMLOperator(m_open, Fence), firstChild());
- m_closeFenceRenderer = createMathMLOperator(m_close, Fence);
+ RenderMathMLRow::addChild(createMathMLOperator(m_open, RenderMathMLOperator::Fence), firstChild());
+ m_closeFenceRenderer = createMathMLOperator(m_close, RenderMathMLOperator::Fence);
RenderMathMLRow::addChild(m_closeFenceRenderer);
}
@@ -132,7 +133,7 @@ void RenderMathMLFenced::addChild(RenderObject* child, RenderObject* beforeChild
else
separator = (*m_separators.get())[count - 1];
- separatorRenderer = createMathMLOperator(separator, Separator);
+ separatorRenderer = createMathMLOperator(separator, RenderMathMLOperator::Separator);
}
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h
index 0f0cfff01..a8b73a9eb 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h
@@ -28,6 +28,7 @@
#if ENABLE(MATHML)
+#include "RenderMathMLOperator.h"
#include "RenderMathMLRow.h"
namespace WebCore {
@@ -39,11 +40,10 @@ public:
virtual void updateFromElement();
private:
+ virtual bool isRenderMathMLFenced() const { return true; }
virtual const char* renderName() const { return "RenderMathMLFenced"; }
- // FIXME: OperatorType here will go away when default operator margins are determined by the MathML operator dictionary.
- enum OperatorType { Separator, Fence };
- RenderMathMLOperator* createMathMLOperator(UChar, OperatorType);
+ RenderMathMLOperator* createMathMLOperator(UChar, RenderMathMLOperator::OperatorType);
void makeFences();
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.h b/Source/WebCore/rendering/mathml/RenderMathMLFraction.h
index 4c10e361a..1ec4a0634 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.h
@@ -47,6 +47,7 @@ protected:
virtual void layout();
private:
+ virtual bool isRenderMathMLFraction() const { return true; }
void fixChildStyle(RenderObject* child);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
index 6655cce9a..bde8baf64 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
@@ -43,6 +43,7 @@ RenderMathMLOperator::RenderMathMLOperator(Element* element)
: RenderMathMLBlock(element)
, m_stretchHeight(0)
, m_operator(0)
+ , m_operatorType(Default)
{
}
@@ -50,6 +51,7 @@ RenderMathMLOperator::RenderMathMLOperator(Node* node, UChar operatorChar)
: RenderMathMLBlock(node)
, m_stretchHeight(0)
, m_operator(convertHyphenMinusToMinusSign(operatorChar))
+ , m_operatorType(Default)
{
}
@@ -201,6 +203,8 @@ void RenderMathMLOperator::updateFromElement()
if (stretchDisabled || !shouldStack) {
m_isStacked = false;
RenderBlock* container = new (renderArena()) RenderMathMLBlock(node());
+ // This container doesn't offer any useful information to accessibility.
+ toRenderMathMLBlock(container)->setIgnoreInAccessibilityTree(true);
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(style());
@@ -293,6 +297,7 @@ PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int maxHeight
RenderBlock* RenderMathMLOperator::createGlyph(UChar glyph, int maxHeightForRenderer, int charRelative)
{
RenderBlock* container = new (renderArena()) RenderMathMLBlock(node());
+ toRenderMathMLBlock(container)->setIgnoreInAccessibilityTree(true);
container->setStyle(createStackableStyle(maxHeightForRenderer));
addChild(container);
RenderBlock* parent = container;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
index 40d6b7785..75bb941de 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
@@ -46,7 +46,11 @@ public:
void stretchToHeight(int pixelHeight);
virtual int firstLineBoxBaseline() const OVERRIDE;
-
+
+ enum OperatorType { Default, Separator, Fence };
+ void setOperatorType(OperatorType type) { m_operatorType = type; }
+ OperatorType operatorType() const { return m_operatorType; }
+
protected:
virtual void computePreferredLogicalWidths() OVERRIDE;
PassRefPtr<RenderStyle> createStackableStyle(int maxHeightForRenderer);
@@ -62,6 +66,7 @@ private:
int m_stretchHeight;
bool m_isStacked;
UChar m_operator;
+ OperatorType m_operatorType;
};
inline RenderMathMLOperator* toRenderMathMLOperator(RenderMathMLBlock* block)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
index 2ae303aa8..99cd36594 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
@@ -45,6 +45,7 @@ protected:
virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
private:
+ virtual bool isRenderMathMLRoot() const { return true; }
virtual const char* renderName() const { return "RenderMathMLRoot"; }
virtual void computePreferredLogicalWidths() OVERRIDE;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
index 90e186c6b..39e0aa72c 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
@@ -38,6 +38,7 @@ public:
RenderMathMLSquareRoot(Element*);
private:
+ virtual bool isRenderMathMLSquareRoot() const { return true; }
virtual const char* renderName() const { return "RenderMathMLSquareRoot"; }
};
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
index 640a86e01..082f1a339 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
@@ -44,7 +44,9 @@ protected:
virtual void layout();
private:
+ virtual bool isRenderMathMLSubSup() const { return true; }
void fixAnonymousStyles();
+
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
virtual const char* renderName() const { return "RenderMathMLSubSup"; }
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h
index caf4fc499..4608145c2 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h
@@ -41,6 +41,7 @@ public:
virtual int firstLineBoxBaseline() const OVERRIDE;
private:
+ virtual bool isRenderMathMLUnderOver() const { return true; }
virtual const char* renderName() const { return "RenderMathMLUnderOver"; }
enum UnderOverType { Under, Over, UnderOver };
diff --git a/Source/WebCore/rendering/style/BasicShapes.cpp b/Source/WebCore/rendering/style/BasicShapes.cpp
index 29ca45d01..b21358fdc 100644
--- a/Source/WebCore/rendering/style/BasicShapes.cpp
+++ b/Source/WebCore/rendering/style/BasicShapes.cpp
@@ -36,6 +36,20 @@
namespace WebCore {
+bool BasicShape::canBlend(const BasicShape* other) const
+{
+ // FIXME: Support animations between different shapes in the future.
+ if (type() != other->type())
+ return false;
+
+ // Just polygons with same number of vertices can be animated.
+ if (type() == BasicShape::BASIC_SHAPE_POLYGON
+ && static_cast<const BasicShapePolygon*>(this)->values().size() != static_cast<const BasicShapePolygon*>(other)->values().size())
+ return false;
+
+ return true;
+}
+
void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -47,6 +61,23 @@ void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox)
m_cornerRadiusY.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusY, boundingBox.height())));
}
+PassRefPtr<BasicShape> BasicShapeRectangle::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapeRectangle* o = static_cast<const BasicShapeRectangle*>(other);
+ RefPtr<BasicShapeRectangle> result = BasicShapeRectangle::create();
+ result->setX(m_x.blend(o->x(), progress));
+ result->setY(m_y.blend(o->y(), progress));
+ result->setWidth(m_width.blend(o->width(), progress));
+ result->setHeight(m_height.blend(o->height(), progress));
+ if (!m_cornerRadiusX.isUndefined() && !o->cornerRadiusX().isUndefined())
+ result->setCornerRadiusX(m_cornerRadiusX.blend(o->cornerRadiusX(), progress));
+ if (!m_cornerRadiusY.isUndefined() && !o->cornerRadiusY().isUndefined())
+ result->setCornerRadiusY(m_cornerRadiusY.blend(o->cornerRadiusY(), progress));
+ return result.release();
+}
+
void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -60,6 +91,18 @@ void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
radius * 2));
}
+PassRefPtr<BasicShape> BasicShapeCircle::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapeCircle* o = static_cast<const BasicShapeCircle*>(other);
+ RefPtr<BasicShapeCircle> result = BasicShapeCircle::create();
+ result->setCenterX(m_centerX.blend(o->centerX(), progress));
+ result->setCenterY(m_centerY.blend(o->centerY(), progress));
+ result->setRadius(m_radius.blend(o->radius(), progress));
+ return result.release();
+}
+
void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -73,6 +116,19 @@ void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
radiusY * 2));
}
+PassRefPtr<BasicShape> BasicShapeEllipse::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapeEllipse* o = static_cast<const BasicShapeEllipse*>(other);
+ RefPtr<BasicShapeEllipse> result = BasicShapeEllipse::create();
+ result->setCenterX(m_centerX.blend(o->centerX(), progress));
+ result->setCenterY(m_centerY.blend(o->centerY(), progress));
+ result->setRadiusX(m_radiusX.blend(o->radiusX(), progress));
+ result->setRadiusY(m_radiusY.blend(o->radiusY(), progress));
+ return result.release();
+}
+
void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -90,4 +146,27 @@ void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
}
path.closeSubpath();
}
+
+PassRefPtr<BasicShape> BasicShapePolygon::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapePolygon* o = static_cast<const BasicShapePolygon*>(other);
+ ASSERT(m_values.size() == o->values().size());
+ ASSERT(!(m_values.size() % 2));
+
+ size_t length = m_values.size();
+ RefPtr<BasicShapePolygon> result = BasicShapePolygon::create();
+ if (!length)
+ return result.release();
+
+ result->setWindRule(o->windRule());
+
+ for (size_t i = 0; i < length; i = i + 2) {
+ result->appendPoint(m_values.at(i).blend(o->values().at(i), progress),
+ m_values.at(i + 1).blend(o->values().at(i + 1), progress));
+ }
+
+ return result.release();
+}
}
diff --git a/Source/WebCore/rendering/style/BasicShapes.h b/Source/WebCore/rendering/style/BasicShapes.h
index ad1182676..171d9c1f6 100644
--- a/Source/WebCore/rendering/style/BasicShapes.h
+++ b/Source/WebCore/rendering/style/BasicShapes.h
@@ -52,8 +52,11 @@ public:
BASIC_SHAPE_POLYGON = 4
};
+ bool canBlend(const BasicShape*) const;
+
virtual void path(Path&, const FloatRect&) = 0;
virtual WindRule windRule() const { return RULE_NONZERO; }
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const = 0;
virtual Type type() const = 0;
protected:
@@ -78,7 +81,8 @@ public:
void setCornerRadiusX(Length radiusX) { m_cornerRadiusX = radiusX; }
void setCornerRadiusY(Length radiusY) { m_cornerRadiusY = radiusY; }
- virtual void path(Path&, const FloatRect&);
+ virtual void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
virtual Type type() const { return BASIC_SHAPE_RECTANGLE; }
private:
@@ -107,7 +111,8 @@ public:
void setCenterY(Length centerY) { m_centerY = centerY; }
void setRadius(Length radius) { m_radius = radius; }
- virtual void path(Path&, const FloatRect&);
+ virtual void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
virtual Type type() const { return BASIC_SHAPE_CIRCLE; }
private:
@@ -132,7 +137,8 @@ public:
void setRadiusX(Length radiusX) { m_radiusX = radiusX; }
void setRadiusY(Length radiusY) { m_radiusY = radiusY; }
- virtual void path(Path&, const FloatRect&);
+ virtual void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
virtual Type type() const { return BASIC_SHAPE_ELLIPSE; }
private:
@@ -155,7 +161,9 @@ 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 void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+
virtual WindRule windRule() const { return m_windRule; }
virtual Type type() const { return BASIC_SHAPE_POLYGON; }
diff --git a/Source/WebCore/rendering/style/ExclusionShapeValue.h b/Source/WebCore/rendering/style/ExclusionShapeValue.h
new file mode 100644
index 000000000..5a533af8f
--- /dev/null
+++ b/Source/WebCore/rendering/style/ExclusionShapeValue.h
@@ -0,0 +1,69 @@
+/*
+ * 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 ExclusionShapeValue_h
+#define ExclusionShapeValue_h
+
+#include "BasicShapes.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class ExclusionShapeValue : public RefCounted<ExclusionShapeValue> {
+public:
+ enum ExclusionShapeValueType {
+ // The AUTO value is defined by a null ExclusionShapeValue*
+ SHAPE,
+ OUTSIDE
+ };
+
+ static PassRefPtr<ExclusionShapeValue> createShapeValue(PassRefPtr<BasicShape> shape)
+ {
+ return adoptRef(new ExclusionShapeValue(shape));
+ }
+
+ static PassRefPtr<ExclusionShapeValue> createOutsideValue()
+ {
+ return adoptRef(new ExclusionShapeValue(OUTSIDE));
+ }
+
+ ExclusionShapeValueType type() const { return m_type; }
+ BasicShape* shape() const { return m_shape.get(); }
+ bool operator==(const ExclusionShapeValue& other) const { return type() == other.type(); }
+
+private:
+ ExclusionShapeValue(PassRefPtr<BasicShape> shape) : m_type(SHAPE), m_shape(shape) { }
+ ExclusionShapeValue(ExclusionShapeValueType type) : m_type(type) { }
+ ExclusionShapeValueType m_type;
+ RefPtr<BasicShape> m_shape;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/rendering/style/GridPosition.h b/Source/WebCore/rendering/style/GridPosition.h
new file mode 100644
index 000000000..3f8fe974d
--- /dev/null
+++ b/Source/WebCore/rendering/style/GridPosition.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GridPosition_h
+#define GridPosition_h
+
+namespace WebCore {
+
+enum GridPositionType {
+ AutoPosition,
+ IntegerPosition
+};
+
+class GridPosition {
+public:
+ GridPosition()
+ : m_type(AutoPosition)
+ , m_integerPosition(0)
+ {
+ }
+
+ bool isPositive() const { return integerPosition() > 0; }
+
+ GridPositionType type() const { return m_type; }
+ bool isAuto() const { return m_type == AutoPosition; }
+
+ void setIntegerPosition(int position)
+ {
+ m_type = IntegerPosition;
+ m_integerPosition = position;
+ }
+
+ int integerPosition() const
+ {
+ ASSERT(type() == IntegerPosition);
+ return m_integerPosition;
+ }
+
+ bool operator==(const GridPosition& other) const
+ {
+ return m_type == other.m_type && m_integerPosition == other.m_integerPosition;
+ }
+
+private:
+ GridPositionType m_type;
+ // FIXME: This should probably be a size_t but the spec currently allows any <integer>.
+ int m_integerPosition;
+};
+
+} // namespace WebCore
+
+#endif // GridPosition_h
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp
index 179d32549..d7f41816a 100644
--- a/Source/WebCore/rendering/style/RenderStyle.cpp
+++ b/Source/WebCore/rendering/style/RenderStyle.cpp
@@ -397,8 +397,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
|| rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough
- || rareNonInheritedData->m_wrapMargin != other->rareNonInheritedData->m_wrapMargin
- || rareNonInheritedData->m_wrapPadding != other->rareNonInheritedData->m_wrapPadding)
+ || rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
+ || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
return StyleDifferenceLayout;
if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index a1db870ac..31996fa05 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -34,6 +34,7 @@
#include "ColorSpace.h"
#include "CounterDirectives.h"
#include "DataRef.h"
+#include "ExclusionShapeValue.h"
#include "FontBaseline.h"
#include "FontDescription.h"
#include "GraphicsTypes.h"
@@ -619,6 +620,7 @@ public:
ETextDecoration textDecoration() const { return static_cast<ETextDecoration>(visual->textDecoration); }
#if ENABLE(CSS3_TEXT)
TextDecorationStyle textDecorationStyle() const { return static_cast<TextDecorationStyle>(rareNonInheritedData->m_textDecorationStyle); }
+ ETextAlignLast textAlignLast() const { return static_cast<ETextAlignLast>(rareInheritedData->m_textAlignLast); }
#else
TextDecorationStyle textDecorationStyle() const { return TextDecorationStyleSolid; }
#endif // CSS3_TEXT
@@ -816,8 +818,8 @@ public:
const Vector<Length>& gridColumns() const { return rareNonInheritedData->m_grid->m_gridColumns; }
const Vector<Length>& gridRows() const { return rareNonInheritedData->m_grid->m_gridRows; }
- Length gridItemColumn() const { return rareNonInheritedData->m_gridItem->m_gridColumn; }
- Length gridItemRow() const { return rareNonInheritedData->m_gridItem->m_gridRow; }
+ const GridPosition& gridItemColumn() const { return rareNonInheritedData->m_gridItem->m_gridColumn; }
+ const GridPosition& gridItemRow() const { return rareNonInheritedData->m_gridItem->m_gridRow; }
const ShadowData* boxShadow() const { return rareNonInheritedData->m_boxShadow.get(); }
void getBoxShadowExtent(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const { getShadowExtent(boxShadow(), top, right, bottom, left); }
@@ -1152,6 +1154,7 @@ public:
void setTextDecoration(ETextDecoration v) { SET_VAR(visual, textDecoration, v); }
#if ENABLE(CSS3_TEXT)
void setTextDecorationStyle(TextDecorationStyle v) { SET_VAR(rareNonInheritedData, m_textDecorationStyle, v); }
+ void setTextAlignLast(ETextAlignLast v) { SET_VAR(rareInheritedData, m_textAlignLast, v) }
#endif // CSS3_TEXT
void setDirection(TextDirection v) { inherited_flags._direction = v; }
void setLineHeight(Length specifiedLineHeight);
@@ -1294,8 +1297,8 @@ public:
void setJustifyContent(EJustifyContent p) { SET_VAR(rareNonInheritedData, m_justifyContent, p); }
void setGridColumns(const Vector<Length>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridColumns, lengths); }
void setGridRows(const Vector<Length>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridRows, lengths); }
- void setGridItemColumn(const Length& columnPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridColumn, columnPosition); }
- void setGridItemRow(const Length& rowPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridRow, rowPosition); }
+ void setGridItemColumn(const GridPosition& columnPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridColumn, columnPosition); }
+ void setGridItemRow(const GridPosition& rowPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridRow, rowPosition); }
void setMarqueeIncrement(const Length& f) { SET_VAR(rareNonInheritedData.access()->m_marquee, increment, f); }
void setMarqueeSpeed(int f) { SET_VAR(rareNonInheritedData.access()->m_marquee, speed, f); }
@@ -1453,22 +1456,24 @@ public:
void setKerning(SVGLength k) { accessSVGStyle()->setKerning(k); }
#endif
- void setShapeInside(PassRefPtr<BasicShape> shape)
+ void setShapeInside(PassRefPtr<ExclusionShapeValue> value)
{
- if (rareNonInheritedData->m_shapeInside != shape)
- rareNonInheritedData.access()->m_shapeInside = shape;
+ if (rareNonInheritedData->m_shapeInside == value)
+ return;
+ rareNonInheritedData.access()->m_shapeInside = value;
}
- BasicShape* shapeInside() const { return rareNonInheritedData->m_shapeInside.get(); }
+ ExclusionShapeValue* shapeInside() const { return rareNonInheritedData->m_shapeInside.get(); }
- void setShapeOutside(PassRefPtr<BasicShape> shape)
+ void setShapeOutside(PassRefPtr<ExclusionShapeValue> value)
{
- if (rareNonInheritedData->m_shapeOutside != shape)
- rareNonInheritedData.access()->m_shapeOutside = shape;
+ if (rareNonInheritedData->m_shapeOutside == value)
+ return;
+ rareNonInheritedData.access()->m_shapeOutside = value;
}
- BasicShape* shapeOutside() const { return rareNonInheritedData->m_shapeOutside.get(); }
+ ExclusionShapeValue* shapeOutside() const { return rareNonInheritedData->m_shapeOutside.get(); }
- static BasicShape* initialShapeInside() { return 0; }
- static BasicShape* initialShapeOutside() { return 0; }
+ static ExclusionShapeValue* initialShapeInside() { return 0; }
+ static ExclusionShapeValue* initialShapeOutside() { return 0; }
void setClipPath(PassRefPtr<ClipPathOperation> operation)
{
@@ -1479,13 +1484,13 @@ public:
static ClipPathOperation* initialClipPath() { return 0; }
- Length wrapPadding() const { return rareNonInheritedData->m_wrapPadding; }
- void setWrapPadding(Length wrapPadding) { SET_VAR(rareNonInheritedData, m_wrapPadding, wrapPadding); }
- static Length initialWrapPadding() { return Length(0, Fixed); }
+ Length shapePadding() const { return rareNonInheritedData->m_shapePadding; }
+ void setShapePadding(Length shapePadding) { SET_VAR(rareNonInheritedData, m_shapePadding, shapePadding); }
+ static Length initialShapePadding() { return Length(0, Fixed); }
- Length wrapMargin() const { return rareNonInheritedData->m_wrapMargin; }
- void setWrapMargin(Length wrapMargin) { SET_VAR(rareNonInheritedData, m_wrapMargin, wrapMargin); }
- static Length initialWrapMargin() { return Length(0, Fixed); }
+ Length shapeMargin() const { return rareNonInheritedData->m_shapeMargin; }
+ void setShapeMargin(Length shapeMargin) { SET_VAR(rareNonInheritedData, m_shapeMargin, shapeMargin); }
+ static Length initialShapeMargin() { return Length(0, Fixed); }
bool hasContent() const { return contentData(); }
const ContentData* contentData() const { return rareNonInheritedData->m_content.get(); }
@@ -1611,6 +1616,7 @@ public:
static ETextDecoration initialTextDecoration() { return TDNONE; }
#if ENABLE(CSS3_TEXT)
static TextDecorationStyle initialTextDecorationStyle() { return TextDecorationStyleSolid; }
+ static ETextAlignLast initialTextAlignLast() { return TextAlignLastAuto; }
#endif // CSS3_TEXT
static float initialZoom() { return 1.0f; }
static int initialOutlineOffset() { return 0; }
@@ -1708,8 +1714,8 @@ public:
static Vector<Length> initialGridRows() { return initialGridTrackValue(); }
// 'auto' is the default.
- static Length initialGridItemColumn() { return Length(); }
- static Length initialGridItemRow() { return Length(); }
+ static GridPosition initialGridItemColumn() { return GridPosition(); }
+ static GridPosition initialGridItemRow() { return GridPosition(); }
static unsigned initialTabSize() { return 8; }
diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h
index f9f320996..72e0c4c33 100644
--- a/Source/WebCore/rendering/style/RenderStyleConstants.h
+++ b/Source/WebCore/rendering/style/RenderStyleConstants.h
@@ -346,6 +346,12 @@ enum TextDecorationStyle {
#endif // CSS3_TEXT
};
+#if ENABLE(CSS3_TEXT)
+enum ETextAlignLast {
+ TextAlignLastAuto, TextAlignLastStart, TextAlignLastEnd, TextAlignLastLeft, TextAlignLastRight, TextAlignLastCenter, TextAlignLastJustify
+};
+#endif // CSS3_TEXT
+
enum EPageBreak {
PBAUTO, PBALWAYS, PBAVOID
};
diff --git a/Source/WebCore/rendering/style/StyleGridItemData.h b/Source/WebCore/rendering/style/StyleGridItemData.h
index 721f18726..2f7487b86 100644
--- a/Source/WebCore/rendering/style/StyleGridItemData.h
+++ b/Source/WebCore/rendering/style/StyleGridItemData.h
@@ -32,7 +32,7 @@
#define StyleGridItemData_h
-#include "Length.h"
+#include "GridPosition.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
@@ -54,11 +54,8 @@ public:
return !(*this == o);
}
- // FIXME: For the moment, we only support a subset of the grammar which correspond to:
- // 'auto' | <length>
- // When we add more of the syntax, we will need a dedicated GridPosition class.
- Length m_gridColumn;
- Length m_gridRow;
+ GridPosition m_gridColumn;
+ GridPosition m_gridRow;
private:
StyleGridItemData();
diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
index 168022143..b1ba5986a 100644
--- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -95,6 +95,9 @@ StyleRareInheritedData::StyleRareInheritedData()
, m_imageResolutionSource(RenderStyle::initialImageResolutionSource())
, m_imageResolutionSnap(RenderStyle::initialImageResolutionSnap())
#endif
+#if ENABLE(CSS3_TEXT)
+ , m_textAlignLast(RenderStyle::initialTextAlignLast())
+#endif // CSS3_TEXT
, hyphenationLimitBefore(-1)
, hyphenationLimitAfter(-1)
, hyphenationLimitLines(-1)
@@ -157,6 +160,9 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
, m_imageResolutionSource(o.m_imageResolutionSource)
, m_imageResolutionSnap(o.m_imageResolutionSnap)
#endif
+#if ENABLE(CSS3_TEXT)
+ , m_textAlignLast(o.m_textAlignLast)
+#endif // CSS3_TEXT
, hyphenationString(o.hyphenationString)
, hyphenationLimitBefore(o.hyphenationLimitBefore)
, hyphenationLimitAfter(o.hyphenationLimitAfter)
@@ -246,6 +252,9 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& m_imageResolutionSnap == o.m_imageResolutionSnap
&& m_imageResolution == o.m_imageResolution
#endif
+#if ENABLE(CSS3_TEXT)
+ && m_textAlignLast == o.m_textAlignLast
+#endif // CSS3_TEXT
&& m_lineSnap == o.m_lineSnap
#if ENABLE(CSS_VARIABLES)
&& m_variables == o.m_variables
diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h
index a34dfb2a3..d07e04c33 100644
--- a/Source/WebCore/rendering/style/StyleRareInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h
@@ -110,6 +110,9 @@ public:
unsigned m_imageResolutionSource : 1; // ImageResolutionSource
unsigned m_imageResolutionSnap : 1; // ImageResolutionSnap
#endif
+#if ENABLE(CSS3_TEXT)
+ unsigned m_textAlignLast : 3; // ETextAlignLast
+#endif // CSS3_TEXT
AtomicString hyphenationString;
short hyphenationLimitBefore;
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index 6c898960d..1c6cb1879 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -51,8 +51,8 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, m_pageSize()
, m_shapeInside(RenderStyle::initialShapeInside())
, m_shapeOutside(RenderStyle::initialShapeOutside())
- , m_wrapMargin(RenderStyle::initialWrapMargin())
- , m_wrapPadding(RenderStyle::initialWrapPadding())
+ , m_shapeMargin(RenderStyle::initialShapeMargin())
+ , m_shapePadding(RenderStyle::initialShapePadding())
, m_clipPath(RenderStyle::initialClipPath())
, m_visitedLinkBackgroundColor(RenderStyle::initialBackgroundColor())
, m_order(RenderStyle::initialOrder())
@@ -125,8 +125,8 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_pageSize(o.m_pageSize)
, m_shapeInside(o.m_shapeInside)
, m_shapeOutside(o.m_shapeOutside)
- , m_wrapMargin(o.m_wrapMargin)
- , m_wrapPadding(o.m_wrapPadding)
+ , m_shapeMargin(o.m_shapeMargin)
+ , m_shapePadding(o.m_shapePadding)
, m_clipPath(o.m_clipPath)
, m_visitedLinkBackgroundColor(o.m_visitedLinkBackgroundColor)
, m_visitedLinkOutlineColor(o.m_visitedLinkOutlineColor)
@@ -210,8 +210,8 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_pageSize == o.m_pageSize
&& m_shapeInside == o.m_shapeInside
&& m_shapeOutside == o.m_shapeOutside
- && m_wrapMargin == o.m_wrapMargin
- && m_wrapPadding == o.m_wrapPadding
+ && m_shapeMargin == o.m_shapeMargin
+ && m_shapePadding == o.m_shapePadding
&& m_clipPath == o.m_clipPath
&& m_visitedLinkBackgroundColor == o.m_visitedLinkBackgroundColor
&& m_visitedLinkOutlineColor == o.m_visitedLinkOutlineColor
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
index e3784d4af..c4ac0f6f3 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -30,6 +30,7 @@
#include "CounterDirectives.h"
#include "CursorData.h"
#include "DataRef.h"
+#include "ExclusionShapeValue.h"
#include "FillLayer.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
@@ -137,10 +138,10 @@ public:
LengthSize m_pageSize;
- RefPtr<BasicShape> m_shapeInside;
- RefPtr<BasicShape> m_shapeOutside;
- Length m_wrapMargin;
- Length m_wrapPadding;
+ RefPtr<ExclusionShapeValue> m_shapeInside;
+ RefPtr<ExclusionShapeValue> m_shapeOutside;
+ Length m_shapeMargin;
+ Length m_shapePadding;
RefPtr<ClipPathOperation> m_clipPath;
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
index b4c67b9b2..019204e4e 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
@@ -70,7 +70,7 @@ const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLay
// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
// FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends
// on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
-LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, LayoutPoint*) const
+LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const
{
LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates());
adjustRectForOutlineAndShadow(box);
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
index 50e9f6860..dc2d5da39 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
@@ -53,7 +53,7 @@ public:
virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
- virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, LayoutPoint*) const OVERRIDE;
+ virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const OVERRIDE;
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
index 2eabeeb70..c75015d57 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
@@ -111,10 +111,12 @@ const RenderObject* SVGRenderSupport::pushMappingToContainer(const RenderObject*
// At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
// to map an element from SVG viewport coordinates to CSS box coordinates.
// RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
- if (parent->isSVGRoot())
- geometryMap.push(object, TransformationMatrix(toRenderSVGRoot(parent)->localToBorderBoxTransform()));
- else
- geometryMap.push(object, LayoutSize());
+ if (parent->isSVGRoot()) {
+ TransformationMatrix matrix(object->localToParentTransform());
+ matrix.multiply(toRenderSVGRoot(parent)->localToBorderBoxTransform());
+ geometryMap.push(object, matrix);
+ } else
+ geometryMap.push(object, object->localToParentTransform());
return parent;
}