summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/rendering/shapes
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/rendering/shapes
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/rendering/shapes')
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp60
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp58
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp506
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h51
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp244
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h71
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp133
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h7
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp161
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h20
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h179
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp121
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h122
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h177
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp297
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h83
18 files changed, 681 insertions, 1717 deletions
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp
index 86c9136ac90..bba80270c55 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.cpp
@@ -42,14 +42,6 @@ LayoutRect BoxShape::shapeMarginLogicalBoundingBox() const
return static_cast<LayoutRect>(marginBounds);
}
-LayoutRect BoxShape::shapePaddingLogicalBoundingBox() const
-{
- FloatRect paddingBounds(m_bounds.rect());
- if (shapePadding() > 0)
- paddingBounds.inflate(-shapePadding());
- return static_cast<LayoutRect>(paddingBounds);
-}
-
FloatRoundedRect BoxShape::shapeMarginBounds() const
{
FloatRoundedRect marginBounds(m_bounds);
@@ -60,24 +52,14 @@ FloatRoundedRect BoxShape::shapeMarginBounds() const
return marginBounds;
}
-FloatRoundedRect BoxShape::shapePaddingBounds() const
-{
- FloatRoundedRect paddingBounds(m_bounds);
- if (shapePadding() > 0) {
- paddingBounds.inflate(-shapePadding());
- paddingBounds.expandRadii(-shapePadding());
- }
- return paddingBounds;
-}
-
void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
const FloatRoundedRect& marginBounds = shapeMarginBounds();
if (marginBounds.isEmpty() || !lineOverlapsShapeMarginBounds(logicalTop, logicalHeight))
return;
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
+ float y1 = logicalTop.toFloat();
+ float y2 = (logicalTop + logicalHeight).toFloat();
const FloatRect& rect = marginBounds.rect();
if (!marginBounds.isRounded()) {
@@ -85,11 +67,25 @@ void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHei
return;
}
+ float topCornerMaxY = std::max<float>(marginBounds.topLeftCorner().maxY(), marginBounds.topRightCorner().maxY());
+ float bottomCornerMinY = std::min<float>(marginBounds.bottomLeftCorner().y(), marginBounds.bottomRightCorner().y());
+
+ if (topCornerMaxY <= bottomCornerMinY && y1 <= topCornerMaxY && y2 >= bottomCornerMinY) {
+ result.append(LineSegment(rect.x(), rect.maxX()));
+ return;
+ }
+
float x1 = rect.maxX();
float x2 = rect.x();
float minXIntercept;
float maxXIntercept;
+ if (y1 <= marginBounds.topLeftCorner().maxY() && y2 >= marginBounds.bottomLeftCorner().y())
+ x1 = rect.x();
+
+ if (y1 <= marginBounds.topRightCorner().maxY() && y2 >= marginBounds.bottomRightCorner().y())
+ x2 = rect.maxX();
+
if (marginBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) {
x1 = std::min<float>(x1, minXIntercept);
x2 = std::max<float>(x2, maxXIntercept);
@@ -104,27 +100,11 @@ void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHei
result.append(LineSegment(x1, x2));
}
-void BoxShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+void BoxShape::buildDisplayPaths(DisplayPaths& paths) const
{
- const FloatRoundedRect& paddingBounds = shapePaddingBounds();
- if (paddingBounds.isEmpty())
- return;
-
- const FloatRect& rect = paddingBounds.rect();
- if (logicalTop < rect.y() || logicalTop + logicalHeight > rect.maxY())
- return;
-
- // FIXME: this method is only a stub, https://bugs.webkit.org/show_bug.cgi?id=124605.
-
- result.append(LineSegment(rect.x(), rect.maxX()));
-}
-
-bool BoxShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize&, LayoutUnit& result) const
-{
- // FIXME: this method is only a stub, https://bugs.webkit.org/show_bug.cgi?id=124606.
-
- result = minLogicalIntervalTop;
- return true;
+ paths.shape.addRoundedRect(m_bounds.rect(), m_bounds.radii().topLeft(), m_bounds.radii().topRight(), m_bounds.radii().bottomLeft(), m_bounds.radii().bottomRight());
+ if (shapeMargin())
+ paths.marginShape.addRoundedRect(shapeMarginBounds().rect(), shapeMarginBounds().radii().topLeft(), shapeMarginBounds().radii().topRight(), shapeMarginBounds().radii().bottomLeft(), shapeMarginBounds().radii().bottomRight());
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h
index 823187a7ca9..06a51489615 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShape.h
@@ -35,7 +35,7 @@
namespace WebCore {
-class BoxShape : public Shape {
+class BoxShape FINAL : public Shape {
public:
BoxShape(const FloatRoundedRect& bounds)
: Shape()
@@ -44,15 +44,12 @@ public:
}
virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE;
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE;
virtual bool isEmpty() const OVERRIDE { return m_bounds.isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths&) const OVERRIDE;
private:
FloatRoundedRect shapeMarginBounds() const;
- FloatRoundedRect shapePaddingBounds() const;
FloatRoundedRect m_bounds;
};
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp
index 9b1f50193f1..74538f391fd 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/BoxShapeTest.cpp
@@ -31,6 +31,8 @@
#include "core/rendering/shapes/BoxShape.h"
+#include "platform/geometry/RoundedRect.h"
+
#include <gtest/gtest.h>
namespace WebCore {
@@ -39,9 +41,9 @@ class BoxShapeTest : public ::testing::Test {
protected:
BoxShapeTest() { }
- PassOwnPtr<Shape> createBoxShape(const LayoutSize& size, float shapeMargin, float shapePadding)
+ PassOwnPtr<Shape> createBoxShape(const RoundedRect& bounds, float shapeMargin)
{
- return Shape::createLayoutBoxShape(size, TopToBottomWritingMode, Length(shapeMargin, Fixed), Length(shapePadding, Fixed));
+ return Shape::createLayoutBoxShape(bounds, TopToBottomWritingMode, shapeMargin);
}
};
@@ -56,8 +58,10 @@ using namespace WebCore;
SegmentList result; \
shapePtr->getExcludedIntervals(lineTop, lineHeight, result); \
EXPECT_EQ(1u, result.size()); \
- EXPECT_EQ(expectedLeft, result[0].logicalLeft); \
- EXPECT_EQ(expectedRight, result[0].logicalRight); \
+ if (result.size() == 1u) { \
+ EXPECT_FLOAT_EQ(expectedLeft, result[0].logicalLeft); \
+ EXPECT_FLOAT_EQ(expectedRight, result[0].logicalRight); \
+ } \
}
#define TEST_NO_EXCLUDED_INTERVAL(shapePtr, lineTop, lineHeight) \
@@ -67,13 +71,21 @@ using namespace WebCore;
EXPECT_EQ(0u, result.size()); \
}
+/* The BoxShape is based on a 100x50 rectangle at 0,0. The shape-margin value is 10,
+ * so the shapeMarginBoundingBox rectangle is 120x70 at -10,-10:
+ *
+ * -10,-10 110,-10
+ * +--------+
+ * | |
+ * +--------+
+ * -10,60 60,60
+ */
TEST_F(BoxShapeTest, zeroRadii)
{
- OwnPtr<Shape> shape = createBoxShape(LayoutSize(100, 50), 10, 20);
+ OwnPtr<Shape> shape = createBoxShape(RoundedRect(0, 0, 100, 50), 10);
EXPECT_FALSE(shape->isEmpty());
EXPECT_EQ(LayoutRect(-10, -10, 120, 70), shape->shapeMarginLogicalBoundingBox());
- EXPECT_EQ(LayoutRect(20, 20, 60, 10), shape->shapePaddingLogicalBoundingBox());
// A BoxShape's bounds include the top edge but not the bottom edge.
// Similarly a "line", specified as top,height to the overlap methods,
@@ -98,16 +110,34 @@ TEST_F(BoxShapeTest, zeroRadii)
TEST_NO_EXCLUDED_INTERVAL(shape, -12, 2);
TEST_NO_EXCLUDED_INTERVAL(shape, 60, 1);
TEST_NO_EXCLUDED_INTERVAL(shape, 100, 200);
+}
+
+/* BoxShape geometry for this test. Corner radii are in parens, x and y intercepts
+ * for the elliptical corners are noted. The rectangle itself is at 0,0 with width and height 100.
+ *
+ * (10, 15) x=10 x=90 (10, 20)
+ * (--+---------+--)
+ * y=15 +--| |-+ y=20
+ * | |
+ * | |
+ * y=85 + -| |- + y=70
+ * (--+---------+--)
+ * (25, 15) x=25 x=80 (20, 30)
+ */
+TEST_F(BoxShapeTest, getIntervals)
+{
+ const RoundedRect::Radii cornerRadii(IntSize(10, 15), IntSize(10, 20), IntSize(25, 15), IntSize(20, 30));
+ OwnPtr<Shape> shape = createBoxShape(RoundedRect(IntRect(0, 0, 100, 100), cornerRadii), 0);
+ EXPECT_FALSE(shape->isEmpty());
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(21, 1));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(20, 0));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(-10, 200));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(25, 35));
- EXPECT_TRUE(shape->lineOverlapsShapePaddingBounds(29, 1));
+ EXPECT_EQ(LayoutRect(0, 0, 100, 100), shape->shapeMarginLogicalBoundingBox());
- EXPECT_FALSE(shape->lineOverlapsShapePaddingBounds(18, 2));
- EXPECT_FALSE(shape->lineOverlapsShapePaddingBounds(30, 1));
- EXPECT_FALSE(shape->lineOverlapsShapePaddingBounds(100, 200));
+ TEST_EXCLUDED_INTERVAL(shape, 10, 95, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 5, 25, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 15, 6, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 20, 50, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 69, 5, 0, 100);
+ TEST_EXCLUDED_INTERVAL(shape, 85, 10, 0, 97.320511f);
}
} // namespace
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp
index 26ddcf3606b..98cd8367e1e 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.cpp
@@ -30,70 +30,11 @@
#include "config.h"
#include "core/rendering/shapes/PolygonShape.h"
-#include "core/rendering/shapes/ShapeInterval.h"
#include "platform/geometry/LayoutPoint.h"
#include "wtf/MathExtras.h"
namespace WebCore {
-enum EdgeIntersectionType {
- Normal,
- VertexMinY,
- VertexMaxY,
- VertexYBoth
-};
-
-struct EdgeIntersection {
- const FloatPolygonEdge* edge;
- FloatPoint point;
- EdgeIntersectionType type;
-};
-
-static inline float leftSide(const FloatPoint& vertex1, const FloatPoint& vertex2, const FloatPoint& point)
-{
- return ((point.x() - vertex1.x()) * (vertex2.y() - vertex1.y())) - ((vertex2.x() - vertex1.x()) * (point.y() - vertex1.y()));
-}
-
-static inline bool isReflexVertex(const FloatPoint& prevVertex, const FloatPoint& vertex, const FloatPoint& nextVertex)
-{
- return leftSide(prevVertex, nextVertex, vertex) < 0;
-}
-
-static bool computeXIntersection(const FloatPolygonEdge* edgePointer, float y, EdgeIntersection& result)
-{
- const FloatPolygonEdge& edge = *edgePointer;
-
- if (edge.minY() > y || edge.maxY() < y)
- return false;
-
- const FloatPoint& vertex1 = edge.vertex1();
- const FloatPoint& vertex2 = edge.vertex2();
- float dy = vertex2.y() - vertex1.y();
-
- float intersectionX;
- EdgeIntersectionType intersectionType;
-
- if (!dy) {
- intersectionType = VertexYBoth;
- intersectionX = edge.minX();
- } else if (y == edge.minY()) {
- intersectionType = VertexMinY;
- intersectionX = (vertex1.y() < vertex2.y()) ? vertex1.x() : vertex2.x();
- } else if (y == edge.maxY()) {
- intersectionType = VertexMaxY;
- intersectionX = (vertex1.y() > vertex2.y()) ? vertex1.x() : vertex2.x();
- } else {
- intersectionType = Normal;
- intersectionX = ((y - vertex1.y()) * (vertex2.x() - vertex1.x()) / dy) + vertex1.x();
- }
-
- result.edge = edgePointer;
- result.type = intersectionType;
- result.point.set(intersectionX, y);
-
- return true;
-}
-
static inline FloatSize inwardEdgeNormal(const FloatPolygonEdge& edge)
{
FloatSize edgeDelta = edge.vertex2() - edge.vertex1();
@@ -110,422 +51,113 @@ static inline FloatSize outwardEdgeNormal(const FloatPolygonEdge& edge)
return -inwardEdgeNormal(edge);
}
-static inline void appendArc(Vector<FloatPoint>& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex, bool padding)
-{
- float startAngle = atan2(startArcVertex.y() - arcCenter.y(), startArcVertex.x() - arcCenter.x());
- float endAngle = atan2(endArcVertex.y() - arcCenter.y(), endArcVertex.x() - arcCenter.x());
- const float twoPI = piFloat * 2;
- if (startAngle < 0)
- startAngle += twoPI;
- if (endAngle < 0)
- endAngle += twoPI;
- float angle = (startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + twoPI - endAngle);
- const float arcSegmentCount = 6; // An even number so that one arc vertex will be eactly arcRadius from arcCenter.
- float arcSegmentAngle = ((padding) ? -angle : twoPI - angle) / arcSegmentCount;
-
- vertices.append(startArcVertex);
- for (unsigned i = 1; i < arcSegmentCount; ++i) {
- float angle = startAngle + arcSegmentAngle * i;
- vertices.append(arcCenter + FloatPoint(cos(angle) * arcRadius, sin(angle) * arcRadius));
- }
- vertices.append(endArcVertex);
-}
-
-static inline void snapVerticesToLayoutUnitGrid(Vector<FloatPoint>& vertices)
-{
- for (unsigned i = 0; i < vertices.size(); ++i)
- vertices[i] = flooredLayoutPoint(vertices[i]);
-}
-
-static inline PassOwnPtr<FloatPolygon> computeShapePaddingBounds(const FloatPolygon& polygon, float padding, WindRule fillRule)
-{
- OwnPtr<Vector<FloatPoint> > paddedVertices = adoptPtr(new Vector<FloatPoint>());
- FloatPoint intersection;
-
- for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) {
- const FloatPolygonEdge& thisEdge = polygon.edgeAt(i);
- const FloatPolygonEdge& prevEdge = thisEdge.previousEdge();
- OffsetPolygonEdge thisOffsetEdge(thisEdge, inwardEdgeNormal(thisEdge) * padding);
- OffsetPolygonEdge prevOffsetEdge(prevEdge, inwardEdgeNormal(prevEdge) * padding);
-
- if (prevOffsetEdge.intersection(thisOffsetEdge, intersection))
- paddedVertices->append(intersection);
- else if (isReflexVertex(prevEdge.vertex1(), thisEdge.vertex1(), thisEdge.vertex2()))
- appendArc(*paddedVertices, thisEdge.vertex1(), padding, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), true);
- }
-
- snapVerticesToLayoutUnitGrid(*paddedVertices);
- return adoptPtr(new FloatPolygon(paddedVertices.release(), fillRule));
-}
-
-static inline PassOwnPtr<FloatPolygon> computeShapeMarginBounds(const FloatPolygon& polygon, float margin, WindRule fillRule)
-{
- OwnPtr<Vector<FloatPoint> > marginVertices = adoptPtr(new Vector<FloatPoint>());
- FloatPoint intersection;
-
- for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) {
- const FloatPolygonEdge& thisEdge = polygon.edgeAt(i);
- const FloatPolygonEdge& prevEdge = thisEdge.previousEdge();
- OffsetPolygonEdge thisOffsetEdge(thisEdge, outwardEdgeNormal(thisEdge) * margin);
- OffsetPolygonEdge prevOffsetEdge(prevEdge, outwardEdgeNormal(prevEdge) * margin);
-
- if (prevOffsetEdge.intersection(thisOffsetEdge, intersection))
- marginVertices->append(intersection);
- else
- appendArc(*marginVertices, thisEdge.vertex1(), margin, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), false);
- }
-
- snapVerticesToLayoutUnitGrid(*marginVertices);
- return adoptPtr(new FloatPolygon(marginVertices.release(), fillRule));
-}
+static inline bool overlapsYRange(const FloatRect& rect, float y1, float y2) { return !rect.isEmpty() && y2 >= y1 && y2 >= rect.y() && y1 <= rect.maxY(); }
-const FloatPolygon& PolygonShape::shapePaddingBounds() const
+float OffsetPolygonEdge::xIntercept(float y) const
{
- ASSERT(shapePadding() >= 0);
- if (!shapePadding() || m_polygon.isEmpty())
- return m_polygon;
+ ASSERT(y >= minY() && y <= maxY());
- if (!m_paddingBounds)
- m_paddingBounds = computeShapePaddingBounds(m_polygon, shapePadding(), m_polygon.fillRule());
+ if (vertex1().y() == vertex2().y() || vertex1().x() == vertex2().x())
+ return minX();
+ if (y == minY())
+ return vertex1().y() < vertex2().y() ? vertex1().x() : vertex2().x();
+ if (y == maxY())
+ return vertex1().y() > vertex2().y() ? vertex1().x() : vertex2().x();
- return *m_paddingBounds;
+ return vertex1().x() + ((y - vertex1().y()) * (vertex2().x() - vertex1().x()) / (vertex2().y() - vertex1().y()));
}
-const FloatPolygon& PolygonShape::shapeMarginBounds() const
+FloatShapeInterval OffsetPolygonEdge::clippedEdgeXRange(float y1, float y2) const
{
- ASSERT(shapeMargin() >= 0);
- if (!shapeMargin() || m_polygon.isEmpty())
- return m_polygon;
+ if (!overlapsYRange(y1, y2) || (y1 == maxY() && minY() <= y1) || (y2 == minY() && maxY() >= y2))
+ return FloatShapeInterval();
- if (!m_marginBounds)
- m_marginBounds = computeShapeMarginBounds(m_polygon, shapeMargin(), m_polygon.fillRule());
+ if (isWithinYRange(y1, y2))
+ return FloatShapeInterval(minX(), maxX());
- return *m_marginBounds;
-}
-
-static inline bool getVertexIntersectionVertices(const EdgeIntersection& intersection, FloatPoint& prevVertex, FloatPoint& thisVertex, FloatPoint& nextVertex)
-{
- if (intersection.type != VertexMinY && intersection.type != VertexMaxY)
- return false;
-
- ASSERT(intersection.edge && intersection.edge->polygon());
- const FloatPolygon& polygon = *(intersection.edge->polygon());
- const FloatPolygonEdge& thisEdge = *(intersection.edge);
+ // Clip the edge line segment to the vertical range y1,y2 and then return
+ // the clipped line segment's horizontal range.
- if ((intersection.type == VertexMinY && (thisEdge.vertex1().y() < thisEdge.vertex2().y()))
- || (intersection.type == VertexMaxY && (thisEdge.vertex1().y() > thisEdge.vertex2().y()))) {
- prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex1());
- thisVertex = polygon.vertexAt(thisEdge.vertexIndex1());
- nextVertex = polygon.vertexAt(thisEdge.vertexIndex2());
+ FloatPoint minYVertex;
+ FloatPoint maxYVertex;
+ if (vertex1().y() < vertex2().y()) {
+ minYVertex = vertex1();
+ maxYVertex = vertex2();
} else {
- prevVertex = polygon.vertexAt(thisEdge.vertexIndex1());
- thisVertex = polygon.vertexAt(thisEdge.vertexIndex2());
- nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex2());
+ minYVertex = vertex2();
+ maxYVertex = vertex1();
}
-
- return true;
-}
-
-static inline bool appendIntervalX(float x, bool inside, FloatShapeIntervals& result)
-{
- if (!inside)
- result.append(FloatShapeInterval(x, x));
- else
- result.last().setX2(x);
-
- return !inside;
+ float xForY1 = (minYVertex.y() < y1) ? xIntercept(y1) : minYVertex.x();
+ float xForY2 = (maxYVertex.y() > y2) ? xIntercept(y2) : maxYVertex.x();
+ return FloatShapeInterval(std::min(xForY1, xForY2), std::max(xForY1, xForY2));
}
-static bool compareEdgeIntersectionX(const EdgeIntersection& intersection1, const EdgeIntersection& intersection2)
+static float circleXIntercept(float y, float radius)
{
- float x1 = intersection1.point.x();
- float x2 = intersection2.point.x();
- return (x1 == x2) ? intersection1.type < intersection2.type : x1 < x2;
+ ASSERT(radius > 0);
+ return radius * sqrt(1 - (y * y) / (radius * radius));
}
-static void computeXIntersections(const FloatPolygon& polygon, float y, bool isMinY, FloatShapeIntervals& result)
+static FloatShapeInterval clippedCircleXRange(const FloatPoint& center, float radius, float y1, float y2)
{
- Vector<const FloatPolygonEdge*> edges;
- if (!polygon.overlappingEdges(y, y, edges))
- return;
-
- Vector<EdgeIntersection> intersections;
- EdgeIntersection intersection;
- for (unsigned i = 0; i < edges.size(); ++i) {
- if (computeXIntersection(edges[i], y, intersection) && intersection.type != VertexYBoth)
- intersections.append(intersection);
- }
-
- if (intersections.size() < 2)
- return;
-
- std::sort(intersections.begin(), intersections.end(), WebCore::compareEdgeIntersectionX);
-
- unsigned index = 0;
- int windCount = 0;
- bool inside = false;
+ if (y1 > center.y() + radius || y2 < center.y() - radius)
+ return FloatShapeInterval();
- while (index < intersections.size()) {
- const EdgeIntersection& thisIntersection = intersections[index];
- if (index + 1 < intersections.size()) {
- const EdgeIntersection& nextIntersection = intersections[index + 1];
- if ((thisIntersection.point.x() == nextIntersection.point.x()) && (thisIntersection.type == VertexMinY || thisIntersection.type == VertexMaxY)) {
- if (thisIntersection.type == nextIntersection.type) {
- // Skip pairs of intersections whose types are VertexMaxY,VertexMaxY and VertexMinY,VertexMinY.
- index += 2;
- } else {
- // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one intersection.
- ++index;
- }
- continue;
- }
- }
-
- bool edgeCrossing = thisIntersection.type == Normal;
- if (!edgeCrossing) {
- FloatPoint prevVertex;
- FloatPoint thisVertex;
- FloatPoint nextVertex;
-
- if (getVertexIntersectionVertices(thisIntersection, prevVertex, thisVertex, nextVertex)) {
- if (nextVertex.y() == y)
- edgeCrossing = (isMinY) ? prevVertex.y() > y : prevVertex.y() < y;
- else if (prevVertex.y() == y)
- edgeCrossing = (isMinY) ? nextVertex.y() > y : nextVertex.y() < y;
- else
- edgeCrossing = true;
- }
- }
+ if (center.y() >= y1 && center.y() <= y2)
+ return FloatShapeInterval(center.x() - radius, center.x() + radius);
- if (edgeCrossing && polygon.fillRule() == RULE_NONZERO) {
- const FloatPolygonEdge& thisEdge = *thisIntersection.edge;
- windCount += (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? 1 : -1;
- }
-
- if (edgeCrossing && (!inside || !windCount))
- inside = appendIntervalX(thisIntersection.point.x(), inside, result);
+ // Clip the circle to the vertical range y1,y2 and return the extent of the clipped circle's
+ // projection on the X axis
- ++index;
- }
+ float xi = circleXIntercept((y2 < center.y() ? y2 : y1) - center.y(), radius);
+ return FloatShapeInterval(center.x() - xi, center.x() + xi);
}
-static bool compareX1(const FloatShapeInterval a, const FloatShapeInterval& b) { return a.x1() < b.x1(); }
-
-static void sortAndMergeShapeIntervals(FloatShapeIntervals& intervals)
+LayoutRect PolygonShape::shapeMarginLogicalBoundingBox() const
{
- std::sort(intervals.begin(), intervals.end(), compareX1);
-
- for (unsigned i = 1; i < intervals.size(); ) {
- const FloatShapeInterval& thisInterval = intervals[i];
- FloatShapeInterval& previousInterval = intervals[i - 1];
- if (thisInterval.overlaps(previousInterval)) {
- previousInterval.setX2(std::max<float>(previousInterval.x2(), thisInterval.x2()));
- intervals.remove(i);
- } else {
- ++i;
- }
- }
+ FloatRect box = m_polygon.boundingBox();
+ box.inflate(shapeMargin());
+ return LayoutRect(box);
}
-static void computeOverlappingEdgeXProjections(const FloatPolygon& polygon, float y1, float y2, FloatShapeIntervals& result)
+void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
- Vector<const FloatPolygonEdge*> edges;
- if (!polygon.overlappingEdges(y1, y2, edges))
- return;
+ float y1 = logicalTop.toFloat();
+ float y2 = logicalTop.toFloat() + logicalHeight.toFloat();
- EdgeIntersection intersection;
- for (unsigned i = 0; i < edges.size(); ++i) {
- const FloatPolygonEdge *edge = edges[i];
- float x1;
- float x2;
+ if (m_polygon.isEmpty() || !overlapsYRange(m_polygon.boundingBox(), y1 - shapeMargin(), y2 + shapeMargin()))
+ return;
- if (edge->minY() < y1) {
- computeXIntersection(edge, y1, intersection);
- x1 = intersection.point.x();
- } else {
- x1 = (edge->vertex1().y() < edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
- }
+ Vector<const FloatPolygonEdge*> overlappingEdges;
+ if (!m_polygon.overlappingEdges(y1 - shapeMargin(), y2 + shapeMargin(), overlappingEdges))
+ return;
- if (edge->maxY() > y2) {
- computeXIntersection(edge, y2, intersection);
- x2 = intersection.point.x();
+ FloatShapeInterval excludedInterval;
+ for (unsigned i = 0; i < overlappingEdges.size(); i++) {
+ const FloatPolygonEdge& edge = *(overlappingEdges[i]);
+ if (edge.maxY() == edge.minY())
+ continue;
+ if (!shapeMargin()) {
+ excludedInterval.unite(OffsetPolygonEdge(edge, FloatSize()).clippedEdgeXRange(y1, y2));
} else {
- x2 = (edge->vertex1().y() > edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
+ excludedInterval.unite(OffsetPolygonEdge(edge, outwardEdgeNormal(edge) * shapeMargin()).clippedEdgeXRange(y1, y2));
+ excludedInterval.unite(OffsetPolygonEdge(edge, inwardEdgeNormal(edge) * shapeMargin()).clippedEdgeXRange(y1, y2));
+ excludedInterval.unite(clippedCircleXRange(edge.vertex1(), shapeMargin(), y1, y2));
}
-
- if (x1 > x2)
- std::swap(x1, x2);
-
- if (x2 > x1)
- result.append(FloatShapeInterval(x1, x2));
}
- sortAndMergeShapeIntervals(result);
-}
-
-void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
-{
- const FloatPolygon& polygon = shapeMarginBounds();
- if (polygon.isEmpty())
- return;
-
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
-
- FloatShapeIntervals y1XIntervals, y2XIntervals;
- computeXIntersections(polygon, y1, true, y1XIntervals);
- computeXIntersections(polygon, y2, false, y2XIntervals);
-
- FloatShapeIntervals mergedIntervals;
- FloatShapeInterval::uniteShapeIntervals(y1XIntervals, y2XIntervals, mergedIntervals);
-
- FloatShapeIntervals edgeIntervals;
- computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
-
- FloatShapeIntervals excludedIntervals;
- FloatShapeInterval::uniteShapeIntervals(mergedIntervals, edgeIntervals, excludedIntervals);
-
- for (unsigned i = 0; i < excludedIntervals.size(); ++i) {
- const FloatShapeInterval& interval = excludedIntervals[i];
- result.append(LineSegment(interval.x1(), interval.x2()));
- }
+ if (!excludedInterval.isEmpty())
+ result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2()));
}
-void PolygonShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+void PolygonShape::buildDisplayPaths(DisplayPaths& paths) const
{
- const FloatPolygon& polygon = shapePaddingBounds();
- if (polygon.isEmpty())
+ if (!m_polygon.numberOfVertices())
return;
-
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
-
- FloatShapeIntervals y1XIntervals, y2XIntervals;
- computeXIntersections(polygon, y1, true, y1XIntervals);
- computeXIntersections(polygon, y2, false, y2XIntervals);
-
- FloatShapeIntervals commonIntervals;
- FloatShapeInterval::intersectShapeIntervals(y1XIntervals, y2XIntervals, commonIntervals);
-
- FloatShapeIntervals edgeIntervals;
- computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
-
- FloatShapeIntervals includedIntervals;
- FloatShapeInterval::subtractShapeIntervals(commonIntervals, edgeIntervals, includedIntervals);
-
- for (unsigned i = 0; i < includedIntervals.size(); ++i) {
- const FloatShapeInterval& interval = includedIntervals[i];
- result.append(LineSegment(interval.x1(), interval.x2()));
- }
-}
-
-static inline bool firstFitRectInPolygon(const FloatPolygon& polygon, const FloatRect& rect, unsigned offsetEdgeIndex1, unsigned offsetEdgeIndex2)
-{
- Vector<const FloatPolygonEdge*> edges;
- if (!polygon.overlappingEdges(rect.y(), rect.maxY(), edges))
- return true;
-
- for (unsigned i = 0; i < edges.size(); ++i) {
- const FloatPolygonEdge* edge = edges[i];
- if (edge->edgeIndex() != offsetEdgeIndex1 && edge->edgeIndex() != offsetEdgeIndex2 && edge->overlapsRect(rect))
- return false;
- }
-
- return true;
-}
-
-static inline bool aboveOrToTheLeft(const FloatRect& r1, const FloatRect& r2)
-{
- if (r1.y() < r2.y())
- return true;
- if (r1.y() == r2.y())
- return r1.x() < r2.x();
- return false;
-}
-
-bool PolygonShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
- float minIntervalTop = minLogicalIntervalTop;
- float minIntervalHeight = minLogicalIntervalSize.height();
- float minIntervalWidth = minLogicalIntervalSize.width();
-
- const FloatPolygon& polygon = shapePaddingBounds();
- const FloatRect boundingBox = polygon.boundingBox();
- if (minIntervalWidth > boundingBox.width())
- return false;
-
- float minY = std::max(boundingBox.y(), minIntervalTop);
- float maxY = minY + minIntervalHeight;
-
- if (maxY > boundingBox.maxY())
- return false;
-
- Vector<const FloatPolygonEdge*> edges;
- polygon.overlappingEdges(minIntervalTop, boundingBox.maxY(), edges);
-
- float dx = minIntervalWidth / 2;
- float dy = minIntervalHeight / 2;
- Vector<OffsetPolygonEdge> offsetEdges;
-
- for (unsigned i = 0; i < edges.size(); ++i) {
- const FloatPolygonEdge& edge = *(edges[i]);
- const FloatPoint& vertex0 = edge.previousEdge().vertex1();
- const FloatPoint& vertex1 = edge.vertex1();
- const FloatPoint& vertex2 = edge.vertex2();
- Vector<OffsetPolygonEdge> offsetEdgeBuffer;
-
- if (vertex2.y() > vertex1.y() ? vertex2.x() >= vertex1.x() : vertex1.x() >= vertex2.x()) {
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(dx, -dy)));
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(-dx, dy)));
- } else {
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(dx, dy)));
- offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(-dx, -dy)));
- }
-
- if (isReflexVertex(vertex0, vertex1, vertex2)) {
- if (vertex2.x() <= vertex1.x() && vertex0.x() <= vertex1.x())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(dx, -dy), FloatSize(dx, dy)));
- else if (vertex2.x() >= vertex1.x() && vertex0.x() >= vertex1.x())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, -dy), FloatSize(-dx, dy)));
- if (vertex2.y() <= vertex1.y() && vertex0.y() <= vertex1.y())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, dy), FloatSize(dx, dy)));
- else if (vertex2.y() >= vertex1.y() && vertex0.y() >= vertex1.y())
- offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, -dy), FloatSize(dx, -dy)));
- }
-
- for (unsigned j = 0; j < offsetEdgeBuffer.size(); ++j) {
- if (offsetEdgeBuffer[j].maxY() >= minY)
- offsetEdges.append(offsetEdgeBuffer[j]);
- }
- }
-
- offsetEdges.append(OffsetPolygonEdge(polygon, minIntervalTop, FloatSize(0, dy)));
-
- FloatPoint offsetEdgesIntersection;
- FloatRect firstFitRect;
- bool firstFitFound = false;
-
- for (unsigned i = 0; i < offsetEdges.size() - 1; ++i) {
- for (unsigned j = i + 1; j < offsetEdges.size(); ++j) {
- if (offsetEdges[i].intersection(offsetEdges[j], offsetEdgesIntersection)) {
- FloatPoint potentialFirstFitLocation(offsetEdgesIntersection.x() - dx, offsetEdgesIntersection.y() - dy);
- FloatRect potentialFirstFitRect(potentialFirstFitLocation, minLogicalIntervalSize);
- if ((offsetEdges[i].basis() == OffsetPolygonEdge::LineTop
- || offsetEdges[j].basis() == OffsetPolygonEdge::LineTop
- || potentialFirstFitLocation.y() >= minIntervalTop)
- && (!firstFitFound || aboveOrToTheLeft(potentialFirstFitRect, firstFitRect))
- && polygon.contains(offsetEdgesIntersection)
- && firstFitRectInPolygon(polygon, potentialFirstFitRect, offsetEdges[i].edgeIndex(), offsetEdges[j].edgeIndex())) {
- firstFitFound = true;
- firstFitRect = potentialFirstFitRect;
- }
- }
- }
- }
-
- if (firstFitFound)
- result = LayoutUnit::fromFloatCeil(firstFitRect.y());
- return firstFitFound;
+ paths.shape.moveTo(m_polygon.vertexAt(0));
+ for (size_t i = 1; i < m_polygon.numberOfVertices(); ++i)
+ paths.shape.addLineTo(m_polygon.vertexAt(i));
+ paths.shape.closeSubpath();
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h
index 38b0d8e75c7..f7171c929f4 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/PolygonShape.h
@@ -31,79 +31,48 @@
#define PolygonShape_h
#include "core/rendering/shapes/Shape.h"
+#include "core/rendering/shapes/ShapeInterval.h"
#include "platform/geometry/FloatPolygon.h"
namespace WebCore {
-class OffsetPolygonEdge : public VertexPair {
+class OffsetPolygonEdge FINAL : public VertexPair {
public:
- enum Basis {
- Edge,
- Vertex,
- LineTop
- };
-
OffsetPolygonEdge(const FloatPolygonEdge& edge, const FloatSize& offset)
: m_vertex1(edge.vertex1() + offset)
, m_vertex2(edge.vertex2() + offset)
- , m_edgeIndex(edge.edgeIndex())
- , m_basis(Edge)
- {
- }
-
- OffsetPolygonEdge(const FloatPoint& reflexVertex, const FloatSize& offset1, const FloatSize& offset2)
- : m_vertex1(reflexVertex + offset1)
- , m_vertex2(reflexVertex + offset2)
- , m_edgeIndex(-1)
- , m_basis(Vertex)
- {
- }
-
- OffsetPolygonEdge(const FloatPolygon& polygon, float minLogicalIntervalTop, const FloatSize& offset)
- : m_vertex1(FloatPoint(polygon.boundingBox().x(), minLogicalIntervalTop) + offset)
- , m_vertex2(FloatPoint(polygon.boundingBox().maxX(), minLogicalIntervalTop) + offset)
- , m_edgeIndex(-1)
- , m_basis(LineTop)
{
}
virtual const FloatPoint& vertex1() const OVERRIDE { return m_vertex1; }
virtual const FloatPoint& vertex2() const OVERRIDE { return m_vertex2; }
- int edgeIndex() const { return m_edgeIndex; }
- Basis basis() const { return m_basis; }
+
+ bool isWithinYRange(float y1, float y2) const { return y1 <= minY() && y2 >= maxY(); }
+ bool overlapsYRange(float y1, float y2) const { return y2 >= minY() && y1 <= maxY(); }
+ float xIntercept(float y) const;
+ FloatShapeInterval clippedEdgeXRange(float y1, float y2) const;
private:
FloatPoint m_vertex1;
FloatPoint m_vertex2;
- int m_edgeIndex;
- Basis m_basis;
};
-class PolygonShape : public Shape {
+class PolygonShape FINAL : public Shape {
WTF_MAKE_NONCOPYABLE(PolygonShape);
public:
PolygonShape(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
: Shape()
, m_polygon(vertices, fillRule)
- , m_marginBounds(nullptr)
- , m_paddingBounds(nullptr)
{
}
- virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapeMarginBounds().boundingBox()); }
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapePaddingBounds().boundingBox()); }
+ virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE;
virtual bool isEmpty() const OVERRIDE { return m_polygon.isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths&) const OVERRIDE;
private:
- const FloatPolygon& shapeMarginBounds() const;
- const FloatPolygon& shapePaddingBounds() const;
-
FloatPolygon m_polygon;
- mutable OwnPtr<FloatPolygon> m_marginBounds;
- mutable OwnPtr<FloatPolygon> m_paddingBounds;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp
index 78b00211519..8dda343bc66 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.cpp
@@ -73,182 +73,67 @@ IntShapeInterval MarginIntervalGenerator::intervalAt(int y) const
return IntShapeInterval(m_x1 - dx, m_x2 + dx);
}
-void RasterShapeIntervals::appendInterval(int y, int x1, int x2)
+PassOwnPtr<RasterShapeIntervals> RasterShapeIntervals::computeShapeMarginIntervals(int shapeMargin) const
{
- ASSERT(x2 > x1 && (intervalsAt(y).isEmpty() || x1 > intervalsAt(y).last().x2()));
- m_bounds.unite(IntRect(x1, y, x2 - x1, 1));
- intervalsAt(y).append(IntShapeInterval(x1, x2));
-}
-
-void RasterShapeIntervals::uniteMarginInterval(int y, const IntShapeInterval& interval)
-{
- ASSERT(intervalsAt(y).size() <= 1); // Each m_intervalLists entry has 0 or one interval.
-
- if (intervalsAt(y).isEmpty()) {
- intervalsAt(y).append(interval);
- } else {
- IntShapeInterval& resultInterval = intervalsAt(y)[0];
- resultInterval.set(std::min(resultInterval.x1(), interval.x1()), std::max(resultInterval.x2(), interval.x2()));
- }
-
- m_bounds.unite(IntRect(interval.x1(), y, interval.width(), 1));
-}
-
-static inline bool shapeIntervalsContain(const IntShapeIntervals& intervals, const IntShapeInterval& interval)
-{
- for (unsigned i = 0; i < intervals.size(); i++) {
- if (intervals[i].x1() > interval.x2())
- return false;
- if (intervals[i].contains(interval))
- return true;
- }
-
- return false;
-}
-
-bool RasterShapeIntervals::contains(const IntRect& rect) const
-{
- if (!bounds().contains(rect))
- return false;
-
- const IntShapeInterval& rectInterval = IntShapeInterval(rect.x(), rect.maxX());
- for (int y = rect.y(); y < rect.maxY(); y++) {
- if (!shapeIntervalsContain(intervalsAt(y), rectInterval))
- return false;
- }
-
- return true;
-}
-
-static inline void appendX1Values(const IntShapeIntervals& intervals, int minIntervalWidth, Vector<int>& result)
-{
- for (unsigned i = 0; i < intervals.size(); i++) {
- if (intervals[i].width() >= minIntervalWidth)
- result.append(intervals[i].x1());
- }
-}
-
-bool RasterShapeIntervals::getIntervalX1Values(int y1, int y2, int minIntervalWidth, Vector<int>& result) const
-{
- ASSERT(y1 >= 0 && y2 > y1);
-
- for (int y = y1; y < y2; y++) {
- if (intervalsAt(y).isEmpty())
- return false;
- }
-
- appendX1Values(intervalsAt(y1), minIntervalWidth, result);
- for (int y = y1 + 1; y < y2; y++) {
- if (intervalsAt(y) != intervalsAt(y - 1))
- appendX1Values(intervalsAt(y), minIntervalWidth, result);
- }
-
- return true;
-}
-
-bool RasterShapeIntervals::firstIncludedIntervalY(int minY, const IntSize& minSize, LayoutUnit& result) const
-{
- minY = std::max<int>(bounds().y(), minY);
-
- ASSERT(minY >= 0 && minY < size());
-
- if (minSize.isEmpty() || minSize.width() > bounds().width())
- return false;
+ int marginIntervalsSize = (offset() > shapeMargin) ? size() : size() - offset() * 2 + shapeMargin * 2;
+ OwnPtr<RasterShapeIntervals> result = adoptPtr(new RasterShapeIntervals(marginIntervalsSize, std::max(shapeMargin, offset())));
+ MarginIntervalGenerator marginIntervalGenerator(shapeMargin);
- for (int lineY = minY; lineY <= bounds().maxY() - minSize.height(); lineY++) {
- Vector<int> intervalX1Values;
- if (!getIntervalX1Values(lineY, lineY + minSize.height(), minSize.width(), intervalX1Values))
+ for (int y = bounds().y(); y < bounds().maxY(); ++y) {
+ const IntShapeInterval& intervalAtY = intervalAt(y);
+ if (intervalAtY.isEmpty())
continue;
- std::sort(intervalX1Values.begin(), intervalX1Values.end());
+ marginIntervalGenerator.set(y, intervalAtY);
+ int marginY0 = std::max(minY(), y - shapeMargin);
+ int marginY1 = std::min(maxY(), y + shapeMargin + 1);
- IntRect firstFitRect(IntPoint(0, 0), minSize);
- for (unsigned i = 0; i < intervalX1Values.size(); i++) {
- int lineX = intervalX1Values[i];
- if (i > 0 && lineX == intervalX1Values[i - 1])
- continue;
- firstFitRect.setLocation(IntPoint(lineX, lineY));
- if (contains(firstFitRect)) {
- result = lineY;
- return true;
- }
+ for (int marginY = y - 1; marginY >= marginY0; --marginY) {
+ if (marginY > bounds().y() && intervalAt(marginY).contains(intervalAtY))
+ break;
+ result->intervalAt(marginY).unite(marginIntervalGenerator.intervalAt(marginY));
}
- }
-
- return false;
-}
-
-void RasterShapeIntervals::getIncludedIntervals(int y1, int y2, IntShapeIntervals& result) const
-{
- ASSERT(y2 >= y1);
- if (y1 < bounds().y() || y2 > bounds().maxY())
- return;
+ result->intervalAt(y).unite(marginIntervalGenerator.intervalAt(y));
- for (int y = y1; y < y2; y++) {
- if (intervalsAt(y).isEmpty())
- return;
+ for (int marginY = y + 1; marginY < marginY1; ++marginY) {
+ if (marginY < bounds().maxY() && intervalAt(marginY).contains(intervalAtY))
+ break;
+ result->intervalAt(marginY).unite(marginIntervalGenerator.intervalAt(marginY));
+ }
}
- result = intervalsAt(y1);
- for (int y = y1 + 1; y < y2 && !result.isEmpty(); y++) {
- IntShapeIntervals intervals;
- IntShapeInterval::intersectShapeIntervals(result, intervalsAt(y), intervals);
- result.swap(intervals);
- }
+ result->initializeBounds();
+ return result.release();
}
-void RasterShapeIntervals::getExcludedIntervals(int y1, int y2, IntShapeIntervals& result) const
+void RasterShapeIntervals::initializeBounds()
{
- ASSERT(y2 >= y1);
-
- if (y2 < bounds().y() || y1 >= bounds().maxY())
- return;
-
- y1 = std::max(y1, bounds().y());
- y2 = std::min(y2, bounds().maxY());
-
- result = intervalsAt(y1);
- for (int y = y1 + 1; y < y2; y++) {
- IntShapeIntervals intervals;
- IntShapeInterval::uniteShapeIntervals(result, intervalsAt(y), intervals);
- result.swap(intervals);
+ m_bounds = IntRect();
+ for (int y = minY(); y < maxY(); ++y) {
+ const IntShapeInterval& intervalAtY = intervalAt(y);
+ if (intervalAtY.isEmpty())
+ continue;
+ m_bounds.unite(IntRect(intervalAtY.x1(), y, intervalAtY.width(), 1));
}
}
-PassOwnPtr<RasterShapeIntervals> RasterShapeIntervals::computeShapeMarginIntervals(unsigned shapeMargin) const
+void RasterShapeIntervals::buildBoundsPath(Path& path) const
{
- OwnPtr<RasterShapeIntervals> result = adoptPtr(new RasterShapeIntervals(size(), shapeMargin));
- MarginIntervalGenerator marginIntervalGenerator(shapeMargin);
-
- int minY = bounds().y();
int maxY = bounds().maxY();
-
- for (int y = minY; y < maxY; ++y) {
- const IntShapeInterval& intervalAtY = limitIntervalAt(y);
- if (intervalAtY.isEmpty())
+ for (int y = bounds().y(); y < maxY; y++) {
+ if (intervalAt(y).isEmpty())
continue;
- marginIntervalGenerator.set(y, intervalAtY);
- int marginY0 = y - clampToInteger(shapeMargin);
- int marginY1 = y + clampToInteger(shapeMargin);
-
- for (int marginY = y - 1; marginY >= marginY0; --marginY) {
- if (marginY > minY && limitIntervalAt(marginY).contains(intervalAtY))
+ IntShapeInterval extent = intervalAt(y);
+ int endY = y + 1;
+ for (; endY < maxY; endY++) {
+ if (intervalAt(endY).isEmpty() || intervalAt(endY) != extent)
break;
- result->uniteMarginInterval(marginY, marginIntervalGenerator.intervalAt(marginY));
- }
-
- result->uniteMarginInterval(y, marginIntervalGenerator.intervalAt(y));
-
- for (int marginY = y + 1; marginY <= marginY1; ++marginY) {
- if (marginY < maxY && limitIntervalAt(marginY).contains(intervalAtY))
- break;
- result->uniteMarginInterval(marginY, marginIntervalGenerator.intervalAt(marginY));
}
+ path.addRect(FloatRect(extent.x1(), y, extent.width(), endY - y));
+ y = endY - 1;
}
-
- return result.release();
}
const RasterShapeIntervals& RasterShape::marginIntervals() const
@@ -257,58 +142,37 @@ const RasterShapeIntervals& RasterShape::marginIntervals() const
if (!shapeMargin())
return *m_intervals;
- unsigned marginBoundaryRadius = std::min(clampToUnsigned(ceil(shapeMargin())), std::max<unsigned>(m_imageSize.width(), m_imageSize.height()));
+ int shapeMarginInt = clampToPositiveInteger(ceil(shapeMargin()));
+ int maxShapeMarginInt = std::max(m_marginRectSize.width(), m_marginRectSize.height()) * sqrtf(2);
if (!m_marginIntervals)
- m_marginIntervals = m_intervals->computeShapeMarginIntervals(marginBoundaryRadius);
+ m_marginIntervals = m_intervals->computeShapeMarginIntervals(std::min(shapeMarginInt, maxShapeMarginInt));
return *m_marginIntervals;
}
-const RasterShapeIntervals& RasterShape::paddingIntervals() const
-{
- ASSERT(shapePadding() >= 0);
- if (!shapePadding())
- return *m_intervals;
-
- // FIXME: Add support for non-zero padding, see https://bugs.webkit.org/show_bug.cgi?id=116348.
- return *m_intervals;
-}
-
-static inline void appendLineSegments(const IntShapeIntervals& intervals, SegmentList& result)
-{
- for (unsigned i = 0; i < intervals.size(); i++)
- result.append(LineSegment(intervals[i].x1(), intervals[i].x2() + 1));
-}
-
void RasterShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
const RasterShapeIntervals& intervals = marginIntervals();
if (intervals.isEmpty())
return;
- IntShapeIntervals excludedIntervals;
- intervals.getExcludedIntervals(logicalTop, logicalTop + logicalHeight, excludedIntervals);
- appendLineSegments(excludedIntervals, result);
-}
-
-void RasterShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
-{
- const RasterShapeIntervals& intervals = paddingIntervals();
- if (intervals.isEmpty())
+ int y1 = logicalTop;
+ int y2 = logicalTop + logicalHeight;
+ ASSERT(y2 >= y1);
+ if (y2 < intervals.bounds().y() || y1 >= intervals.bounds().maxY())
return;
- IntShapeIntervals includedIntervals;
- intervals.getIncludedIntervals(logicalTop, logicalTop + logicalHeight, includedIntervals);
- appendLineSegments(includedIntervals, result);
-}
+ y1 = std::max(y1, intervals.bounds().y());
+ y2 = std::min(y2, intervals.bounds().maxY());
+ IntShapeInterval excludedInterval;
-bool RasterShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
- const RasterShapeIntervals& intervals = paddingIntervals();
- if (intervals.isEmpty())
- return false;
+ for (int y = y1; y < y2; y++)
+ excludedInterval.unite(intervals.intervalAt(y));
- return intervals.firstIncludedIntervalY(minLogicalIntervalTop.floor(), flooredIntSize(minLogicalIntervalSize), result);
+ // Note: |marginIntervals()| returns end-point exclusive
+ // intervals. |excludedInterval.x2()| contains the left-most pixel
+ // offset to the right of the calculated union.
+ result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2()));
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h
index 903eabb0527..0ca8d8a5ba9 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RasterShape.h
@@ -40,74 +40,69 @@ namespace WebCore {
class RasterShapeIntervals {
public:
- RasterShapeIntervals(unsigned size, unsigned shapeMargin = 0)
- : m_shapeMargin(shapeMargin)
+ RasterShapeIntervals(unsigned size, int offset = 0)
+ : m_offset(offset)
{
- m_intervalLists.resize(size + shapeMargin * 2);
+ m_intervals.resize(clampTo<int>(size));
}
+ void initializeBounds();
const IntRect& bounds() const { return m_bounds; }
bool isEmpty() const { return m_bounds.isEmpty(); }
- void appendInterval(int y, int x1, int x2);
- void getIncludedIntervals(int y1, int y2, IntShapeIntervals& result) const;
- void getExcludedIntervals(int y1, int y2, IntShapeIntervals& result) const;
- bool firstIncludedIntervalY(int minY, const IntSize& minSize, LayoutUnit& result) const;
- PassOwnPtr<RasterShapeIntervals> computeShapeMarginIntervals(unsigned shapeMargin) const;
-
-private:
- int size() const { return m_intervalLists.size(); }
-
- IntShapeIntervals& intervalsAt(int y)
+ IntShapeInterval& intervalAt(int y)
{
- ASSERT(y + m_shapeMargin >= 0 && y + m_shapeMargin < m_intervalLists.size());
- return m_intervalLists[y + m_shapeMargin];
+ ASSERT(y + m_offset >= 0 && static_cast<unsigned>(y + m_offset) < m_intervals.size());
+ return m_intervals[y + m_offset];
}
- const IntShapeIntervals& intervalsAt(int y) const
+ const IntShapeInterval& intervalAt(int y) const
{
- ASSERT(y + m_shapeMargin >= 0 && y + m_shapeMargin < m_intervalLists.size());
- return m_intervalLists[y + m_shapeMargin];
+ ASSERT(y + m_offset >= 0 && static_cast<unsigned>(y + m_offset) < m_intervals.size());
+ return m_intervals[y + m_offset];
}
- IntShapeInterval limitIntervalAt(int y) const
- {
- const IntShapeIntervals& intervals = intervalsAt(y);
- return intervals.size() ? IntShapeInterval(intervals[0].x1(), intervals.last().x2()) : IntShapeInterval();
- }
+ PassOwnPtr<RasterShapeIntervals> computeShapeMarginIntervals(int shapeMargin) const;
+
+ void buildBoundsPath(Path&) const;
+
+private:
+ int size() const { return m_intervals.size(); }
+ int offset() const { return m_offset; }
+ int minY() const { return -m_offset; }
+ int maxY() const { return -m_offset + m_intervals.size(); }
- bool contains(const IntRect&) const;
- bool getIntervalX1Values(int minY, int maxY, int minIntervalWidth, Vector<int>& result) const;
- void uniteMarginInterval(int y, const IntShapeInterval&);
IntRect m_bounds;
- Vector<IntShapeIntervals> m_intervalLists;
- unsigned m_shapeMargin;
+ Vector<IntShapeInterval> m_intervals;
+ int m_offset;
};
-class RasterShape : public Shape {
+class RasterShape FINAL : public Shape {
WTF_MAKE_NONCOPYABLE(RasterShape);
public:
- RasterShape(PassOwnPtr<RasterShapeIntervals> intervals, const IntSize& imageSize)
- : Shape()
- , m_intervals(intervals)
- , m_imageSize(imageSize)
+ RasterShape(PassOwnPtr<RasterShapeIntervals> intervals, const IntSize& marginRectSize)
+ : m_intervals(intervals)
+ , m_marginRectSize(marginRectSize)
{
+ m_intervals->initializeBounds();
}
virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(marginIntervals().bounds()); }
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(paddingIntervals().bounds()); }
virtual bool isEmpty() const OVERRIDE { return m_intervals->isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths& paths) const OVERRIDE
+ {
+ m_intervals->buildBoundsPath(paths.shape);
+ if (shapeMargin())
+ marginIntervals().buildBoundsPath(paths.marginShape);
+ }
private:
const RasterShapeIntervals& marginIntervals() const;
- const RasterShapeIntervals& paddingIntervals() const;
OwnPtr<RasterShapeIntervals> m_intervals;
mutable OwnPtr<RasterShapeIntervals> m_marginIntervals;
- IntSize m_imageSize;
+ IntSize m_marginRectSize;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp
index efe1f69831b..eaf51424c83 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.cpp
@@ -40,26 +40,6 @@ static inline float ellipseXIntercept(float y, float rx, float ry)
return rx * sqrt(1 - (y * y) / (ry * ry));
}
-static inline float ellipseYIntercept(float x, float rx, float ry)
-{
- ASSERT(rx > 0);
- return ry * sqrt(1 - (x * x) / (rx * rx));
-}
-
-FloatRect RectangleShape::shapePaddingBounds() const
-{
- ASSERT(shapePadding() >= 0);
- if (!shapePadding() || isEmpty())
- return m_bounds;
-
- float boundsX = x() + std::min(width() / 2, shapePadding());
- float boundsY = y() + std::min(height() / 2, shapePadding());
- float boundsWidth = std::max(0.0f, width() - shapePadding() * 2);
- float boundsHeight = std::max(0.0f, height() - shapePadding() * 2);
-
- return FloatRect(boundsX, boundsY, boundsWidth, boundsHeight);
-}
-
FloatRect RectangleShape::shapeMarginBounds() const
{
ASSERT(shapeMargin() >= 0);
@@ -79,8 +59,8 @@ void RectangleShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logi
if (bounds.isEmpty())
return;
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
+ float y1 = logicalTop.toFloat();
+ float y2 = (logicalTop + logicalHeight).toFloat();
if (y2 < bounds.y() || y1 >= bounds.maxY())
return;
@@ -108,112 +88,11 @@ void RectangleShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logi
result.append(LineSegment(x1, x2));
}
-void RectangleShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+void RectangleShape::buildDisplayPaths(DisplayPaths& paths) const
{
- const FloatRect& bounds = shapePaddingBounds();
- if (bounds.isEmpty())
- return;
-
- float y1 = logicalTop;
- float y2 = logicalTop + logicalHeight;
-
- if (y1 < bounds.y() || y2 > bounds.maxY())
- return;
-
- float x1 = bounds.x();
- float x2 = bounds.maxX();
-
- float paddingRadiusX = std::max(0.0f, rx() - shapePadding());
- float paddingRadiusY = std::max(0.0f, ry() - shapePadding());
-
- if (paddingRadiusX > 0) {
- bool y1InterceptsCorner = y1 < bounds.y() + paddingRadiusY;
- bool y2InterceptsCorner = y2 > bounds.maxY() - paddingRadiusY;
- float xi = 0;
-
- if (y1InterceptsCorner && y2InterceptsCorner) {
- if (y1 < bounds.height() + 2 * bounds.y() - y2) {
- float yi = y1 - bounds.y() - paddingRadiusY;
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- } else {
- float yi = y2 - (bounds.maxY() - paddingRadiusY);
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- }
- } else if (y1InterceptsCorner) {
- float yi = y1 - bounds.y() - paddingRadiusY;
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- } else if (y2InterceptsCorner) {
- float yi = y2 - (bounds.maxY() - paddingRadiusY);
- xi = ellipseXIntercept(yi, paddingRadiusX, paddingRadiusY);
- }
-
- if (y1InterceptsCorner || y2InterceptsCorner) {
- x1 = bounds.x() + paddingRadiusX - xi;
- x2 = bounds.maxX() - paddingRadiusX + xi;
- }
- }
-
- result.append(LineSegment(x1, x2));
-}
-
-static FloatPoint cornerInterceptForWidth(float width, float widthAtIntercept, float rx, float ry)
-{
- float xi = (width - widthAtIntercept) / 2;
- float yi = ry - ellipseYIntercept(rx - xi, rx, ry);
- return FloatPoint(xi, yi);
-}
-
-bool RectangleShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
- float minIntervalTop = minLogicalIntervalTop;
- float minIntervalHeight = minLogicalIntervalSize.height();
- float minIntervalWidth = minLogicalIntervalSize.width();
-
- const FloatRect& bounds = shapePaddingBounds();
- if (bounds.isEmpty() || minIntervalWidth > bounds.width())
- return false;
-
- float minY = LayoutUnit::fromFloatCeil(std::max(bounds.y(), minIntervalTop));
- float maxY = minY + minIntervalHeight;
-
- if (maxY > bounds.maxY())
- return false;
-
- float paddingRadiusX = std::max(0.0f, rx() - shapePadding());
- float paddingRadiusY = std::max(0.0f, ry() - shapePadding());
-
- bool intervalOverlapsMinCorner = minY < bounds.y() + paddingRadiusY;
- bool intervalOverlapsMaxCorner = maxY > bounds.maxY() - paddingRadiusY;
-
- if (!intervalOverlapsMinCorner && !intervalOverlapsMaxCorner) {
- result = minY;
- return true;
- }
-
- float centerY = bounds.y() + bounds.height() / 2;
- bool minCornerDefinesX = fabs(centerY - minY) > fabs(centerY - maxY);
- bool intervalFitsWithinCorners = minIntervalWidth + 2 * paddingRadiusX <= bounds.width();
- FloatPoint cornerIntercept = cornerInterceptForWidth(bounds.width(), minIntervalWidth, paddingRadiusX, paddingRadiusY);
-
- if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDefinesX)) {
- if (intervalFitsWithinCorners || bounds.y() + cornerIntercept.y() < minY) {
- result = minY;
- return true;
- }
- if (minIntervalHeight < bounds.height() - (2 * cornerIntercept.y())) {
- result = LayoutUnit::fromFloatCeil(bounds.y() + cornerIntercept.y());
- return true;
- }
- }
-
- if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDefinesX)) {
- if (intervalFitsWithinCorners || minY <= bounds.maxY() - cornerIntercept.y() - minIntervalHeight) {
- result = minY;
- return true;
- }
- }
-
- return false;
+ paths.shape.addRoundedRect(m_bounds, m_radii);
+ if (shapeMargin())
+ paths.marginShape.addRoundedRect(shapeMarginBounds(), FloatSize(m_radii.width() + shapeMargin(), m_radii.height() + shapeMargin()));
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h
index 9a9dae5522e..d47471da48f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/RectangleShape.h
@@ -39,7 +39,7 @@
namespace WebCore {
-class RectangleShape : public Shape {
+class RectangleShape FINAL : public Shape {
public:
RectangleShape(const FloatRect& bounds, const FloatSize& radii)
: Shape()
@@ -49,15 +49,12 @@ public:
}
virtual LayoutRect shapeMarginLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapeMarginBounds()); }
- virtual LayoutRect shapePaddingLogicalBoundingBox() const OVERRIDE { return static_cast<LayoutRect>(shapePaddingBounds()); }
virtual bool isEmpty() const OVERRIDE { return m_bounds.isEmpty(); }
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const OVERRIDE;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit&) const OVERRIDE;
+ virtual void buildDisplayPaths(DisplayPaths&) const OVERRIDE;
private:
FloatRect shapeMarginBounds() const;
- FloatRect shapePaddingBounds() const;
float rx() const { return m_radii.width(); }
float ry() const { return m_radii.height(); }
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
index ffe05053133..6e382254b9a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
@@ -30,14 +30,16 @@
#include "config.h"
#include "core/rendering/shapes/Shape.h"
+#include "core/css/BasicShapeFunctions.h"
#include "core/fetch/ImageResource.h"
#include "core/rendering/shapes/BoxShape.h"
#include "core/rendering/shapes/PolygonShape.h"
#include "core/rendering/shapes/RasterShape.h"
#include "core/rendering/shapes/RectangleShape.h"
+#include "core/rendering/style/RenderStyle.h"
#include "platform/LengthFunctions.h"
-#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/FloatSize.h"
+#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/WindRule.h"
#include "wtf/MathExtras.h"
@@ -45,18 +47,12 @@
namespace WebCore {
-static PassOwnPtr<Shape> createBoxShape(const FloatRoundedRect& bounds)
+static PassOwnPtr<Shape> createInsetShape(const FloatRoundedRect& bounds)
{
ASSERT(bounds.rect().width() >= 0 && bounds.rect().height() >= 0);
return adoptPtr(new BoxShape(bounds));
}
-static PassOwnPtr<Shape> createRectangleShape(const FloatRect& bounds, const FloatSize& radii)
-{
- ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0);
- return adoptPtr(new RectangleShape(bounds, radii));
-}
-
static PassOwnPtr<Shape> createCircleShape(const FloatPoint& center, float radius)
{
ASSERT(radius >= 0);
@@ -99,55 +95,22 @@ static inline FloatSize physicalSizeToLogical(const FloatSize& size, WritingMode
return size.transposedSize();
}
-static inline void ensureRadiiDoNotOverlap(FloatRect &bounds, FloatSize &radii)
-{
- float widthRatio = bounds.width() / (2 * radii.width());
- float heightRatio = bounds.height() / (2 * radii.height());
- float reductionRatio = std::min<float>(widthRatio, heightRatio);
- if (reductionRatio < 1) {
- radii.setWidth(reductionRatio * radii.width());
- radii.setHeight(reductionRatio * radii.height());
- }
-}
-
-PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, Length margin, Length padding)
+PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, float margin)
{
ASSERT(basicShape);
bool horizontalWritingMode = isHorizontalWritingMode(writingMode);
- float boxWidth = horizontalWritingMode ? logicalBoxSize.width() : logicalBoxSize.height();
- float boxHeight = horizontalWritingMode ? logicalBoxSize.height() : logicalBoxSize.width();
+ float boxWidth = horizontalWritingMode ? logicalBoxSize.width().toFloat() : logicalBoxSize.height().toFloat();
+ float boxHeight = horizontalWritingMode ? logicalBoxSize.height().toFloat() : logicalBoxSize.width().toFloat();
OwnPtr<Shape> shape;
switch (basicShape->type()) {
- case BasicShape::BasicShapeRectangleType: {
- const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape);
- FloatRect bounds(
- floatValueForLength(rectangle->x(), boxWidth),
- floatValueForLength(rectangle->y(), boxHeight),
- floatValueForLength(rectangle->width(), boxWidth),
- floatValueForLength(rectangle->height(), boxHeight));
- FloatSize cornerRadii(
- floatValueForLength(rectangle->cornerRadiusX(), boxWidth),
- floatValueForLength(rectangle->cornerRadiusY(), boxHeight));
- ensureRadiiDoNotOverlap(bounds, cornerRadii);
- FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxSize.height(), writingMode);
-
- shape = createRectangleShape(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
- break;
- }
-
case BasicShape::BasicShapeCircleType: {
const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape);
- float centerX = floatValueForLength(circle->centerX(), boxWidth);
- float centerY = floatValueForLength(circle->centerY(), boxHeight);
- // This method of computing the radius is as defined in SVG
- // (http://www.w3.org/TR/SVG/coords.html#Units). It bases the radius
- // off of the diagonal of the box and ensures that if the box is
- // square, the radius is equal to half the diagonal.
- float radius = floatValueForLength(circle->radius(), sqrtf((boxWidth * boxWidth + boxHeight * boxHeight) / 2));
- FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode);
+ FloatPoint center = floatPointForCenterCoordinate(circle->centerX(), circle->centerY(), FloatSize(boxWidth, boxHeight));
+ float radius = circle->floatValueForRadiusInBox(FloatSize(boxWidth, boxHeight));
+ FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
shape = createCircleShape(logicalCenter, radius);
break;
@@ -155,14 +118,12 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
case BasicShape::BasicShapeEllipseType: {
const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape);
- float centerX = floatValueForLength(ellipse->centerX(), boxWidth);
- float centerY = floatValueForLength(ellipse->centerY(), boxHeight);
- float radiusX = floatValueForLength(ellipse->radiusX(), boxWidth);
- float radiusY = floatValueForLength(ellipse->radiusY(), boxHeight);
- FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode);
- FloatSize logicalRadii = physicalSizeToLogical(FloatSize(radiusX, radiusY), writingMode);
-
- shape = createEllipseShape(logicalCenter, logicalRadii);
+ FloatPoint center = floatPointForCenterCoordinate(ellipse->centerX(), ellipse->centerY(), FloatSize(boxWidth, boxHeight));
+ float radiusX = ellipse->floatValueForRadiusInBox(ellipse->radiusX(), center.x(), boxWidth);
+ float radiusY = ellipse->floatValueForRadiusInBox(ellipse->radiusY(), center.y(), boxHeight);
+ FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
+
+ shape = createEllipseShape(logicalCenter, FloatSize(radiusX, radiusY));
break;
}
@@ -176,28 +137,31 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
FloatPoint vertex(
floatValueForLength(values.at(i), boxWidth),
floatValueForLength(values.at(i + 1), boxHeight));
- (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height(), writingMode);
+ (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height().toFloat(), writingMode);
}
shape = createPolygonShape(vertices.release(), polygon->windRule());
break;
}
- case BasicShape::BasicShapeInsetRectangleType: {
- const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape);
- float left = floatValueForLength(rectangle->left(), boxWidth);
- float top = floatValueForLength(rectangle->top(), boxHeight);
- FloatRect bounds(
- left,
- top,
- boxWidth - left - floatValueForLength(rectangle->right(), boxWidth),
- boxHeight - top - floatValueForLength(rectangle->bottom(), boxHeight));
- FloatSize cornerRadii(
- floatValueForLength(rectangle->cornerRadiusX(), boxWidth),
- floatValueForLength(rectangle->cornerRadiusY(), boxHeight));
- ensureRadiiDoNotOverlap(bounds, cornerRadii);
- FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxSize.height(), writingMode);
-
- shape = createRectangleShape(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
+ case BasicShape::BasicShapeInsetType: {
+ const BasicShapeInset& inset = *static_cast<const BasicShapeInset*>(basicShape);
+ float left = floatValueForLength(inset.left(), boxWidth);
+ float top = floatValueForLength(inset.top(), boxHeight);
+ float right = floatValueForLength(inset.right(), boxWidth);
+ float bottom = floatValueForLength(inset.bottom(), boxHeight);
+ FloatRect rect(left, top, std::max<float>(boxWidth - left - right, 0), std::max<float>(boxHeight - top - bottom, 0));
+ FloatRect logicalRect = physicalRectToLogical(rect, logicalBoxSize.height().toFloat(), writingMode);
+
+ FloatSize boxSize(boxWidth, boxHeight);
+ FloatSize topLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topLeftRadius(), boxSize), writingMode);
+ FloatSize topRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topRightRadius(), boxSize), writingMode);
+ FloatSize bottomLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomLeftRadius(), boxSize), writingMode);
+ FloatSize bottomRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomRightRadius(), boxSize), writingMode);
+ FloatRoundedRect::Radii cornerRadii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ cornerRadii.scale(calcBorderRadiiConstraintScaleFor(logicalRect, cornerRadii));
+
+ shape = createInsetShape(FloatRoundedRect(logicalRect, cornerRadii));
break;
}
@@ -206,61 +170,60 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
}
shape->m_writingMode = writingMode;
- shape->m_margin = floatValueForLength(margin, 0);
- shape->m_padding = floatValueForLength(padding, 0);
+ shape->m_margin = margin;
return shape.release();
}
-PassOwnPtr<Shape> Shape::createShape(const StyleImage* styleImage, float threshold, const LayoutSize&, WritingMode writingMode, Length margin, Length padding)
+PassOwnPtr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin)
{
- ASSERT(styleImage && styleImage->isImageResource() && styleImage->cachedImage() && styleImage->cachedImage()->image());
+ IntRect imageRect = pixelSnappedIntRect(imageR);
+ IntRect marginRect = pixelSnappedIntRect(marginR);
+ OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(marginRect.height(), -marginRect.y()));
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size());
- Image* image = styleImage->cachedImage()->image();
- const IntSize& imageSize = image->size();
- OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(imageSize.height()));
- OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageSize);
if (imageBuffer) {
GraphicsContext* graphicsContext = imageBuffer->context();
- graphicsContext->drawImage(image, IntPoint());
+ graphicsContext->drawImage(image, IntRect(IntPoint(), imageRect.size()));
- RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageSize));
- unsigned pixelArrayLength = pixelArray->length();
+ RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageRect.size()));
unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
uint8_t alphaPixelThreshold = threshold * 255;
- ASSERT(static_cast<unsigned>(imageSize.width() * imageSize.height() * 4) == pixelArrayLength);
+ ASSERT(static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArray->length());
+
+ int minBufferY = std::max(0, marginRect.y() - imageRect.y());
+ int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
- for (int y = 0; y < imageSize.height(); ++y) {
+ for (int y = minBufferY; y < maxBufferY; ++y) {
int startX = -1;
- for (int x = 0; x < imageSize.width() && pixelArrayOffset < pixelArrayLength; ++x, pixelArrayOffset += 4) {
+ for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
uint8_t alpha = pixelArray->item(pixelArrayOffset);
- if ((startX == -1) && alpha > alphaPixelThreshold) {
+ bool alphaAboveThreshold = alpha > alphaPixelThreshold;
+ if (startX == -1 && alphaAboveThreshold) {
startX = x;
- } else if (startX != -1 && (alpha <= alphaPixelThreshold || x == imageSize.width() - 1)) {
- intervals->appendInterval(y, startX, x);
+ } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
+ int endX = alphaAboveThreshold ? x + 1 : x;
+ intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
startX = -1;
}
}
}
}
- OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), imageSize));
+ OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), marginRect.size()));
rasterShape->m_writingMode = writingMode;
- rasterShape->m_margin = floatValueForLength(margin, 0);
- rasterShape->m_padding = floatValueForLength(padding, 0);
+ rasterShape->m_margin = margin;
return rasterShape.release();
}
-PassOwnPtr<Shape> Shape::createLayoutBoxShape(const LayoutSize& logicalSize, WritingMode writingMode, const Length& margin, const Length& padding)
+PassOwnPtr<Shape> Shape::createLayoutBoxShape(const RoundedRect& roundedRect, WritingMode writingMode, float margin)
{
- FloatRect rect(0, 0, logicalSize.width(), logicalSize.height());
- FloatSize radii(0, 0);
- FloatRoundedRect bounds(rect, radii, radii, radii, radii);
- OwnPtr<Shape> shape = createBoxShape(bounds);
+ FloatRect rect(0, 0, roundedRect.rect().width(), roundedRect.rect().height());
+ FloatRoundedRect bounds(rect, roundedRect.radii());
+ OwnPtr<Shape> shape = createInsetShape(bounds);
shape->m_writingMode = writingMode;
- shape->m_margin = floatValueForLength(margin, 0);
- shape->m_padding = floatValueForLength(padding, 0);
+ shape->m_margin = margin;
return shape.release();
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h
index de9aef9f99d..fb649957671 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.h
@@ -33,6 +33,8 @@
#include "core/rendering/style/BasicShapes.h"
#include "core/rendering/style/StyleImage.h"
#include "platform/geometry/LayoutRect.h"
+#include "platform/geometry/RoundedRect.h"
+#include "platform/graphics/Path.h"
#include "platform/text/WritingMode.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/Vector.h"
@@ -60,24 +62,25 @@ typedef Vector<LineSegment> SegmentList;
class Shape {
public:
- static PassOwnPtr<Shape> createShape(const BasicShape*, const LayoutSize& logicalBoxSize, WritingMode, Length margin, Length padding);
- static PassOwnPtr<Shape> createShape(const StyleImage*, float threshold, const LayoutSize& logicalBoxSize, WritingMode, Length margin, Length padding);
- static PassOwnPtr<Shape> createLayoutBoxShape(const LayoutSize& logicalBoxSize, WritingMode, const Length& margin, const Length& padding);
+ struct DisplayPaths {
+ Path shape;
+ Path marginShape;
+ };
+ static PassOwnPtr<Shape> createShape(const BasicShape*, const LayoutSize& logicalBoxSize, WritingMode, float margin);
+ static PassOwnPtr<Shape> createRasterShape(Image*, float threshold, const LayoutRect& imageRect, const LayoutRect& marginRect, WritingMode, float margin);
+ static PassOwnPtr<Shape> createLayoutBoxShape(const RoundedRect&, WritingMode, float margin);
virtual ~Shape() { }
virtual LayoutRect shapeMarginLogicalBoundingBox() const = 0;
- virtual LayoutRect shapePaddingLogicalBoundingBox() const = 0;
virtual bool isEmpty() const = 0;
- virtual void getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const = 0;
virtual void getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList&) const = 0;
- virtual bool firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const = 0;
+
bool lineOverlapsShapeMarginBounds(LayoutUnit lineTop, LayoutUnit lineHeight) const { return lineOverlapsBoundingBox(lineTop, lineHeight, shapeMarginLogicalBoundingBox()); }
- bool lineOverlapsShapePaddingBounds(LayoutUnit lineTop, LayoutUnit lineHeight) const { return lineOverlapsBoundingBox(lineTop, lineHeight, shapePaddingLogicalBoundingBox()); }
+ virtual void buildDisplayPaths(DisplayPaths&) const = 0;
protected:
float shapeMargin() const { return m_margin; }
- float shapePadding() const { return m_padding; }
private:
bool lineOverlapsBoundingBox(LayoutUnit lineTop, LayoutUnit lineHeight, const LayoutRect& rect) const
@@ -89,7 +92,6 @@ private:
WritingMode m_writingMode;
float m_margin;
- float m_padding;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp
deleted file mode 100644
index e2668712991..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "core/rendering/shapes/ShapeInfo.h"
-
-#include "core/rendering/RenderRegion.h"
-
-namespace WebCore {
-
-bool checkShapeImageOrigin(Document& document, ImageResource& imageResource)
-{
- if (imageResource.isAccessAllowed(document.securityOrigin()))
- return true;
-
- const KURL& url = imageResource.url();
- String urlString = url.isNull() ? "''" : url.elidedString();
- document.addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + ".");
-
- return false;
-}
-
-template<class RenderType>
-const Shape* ShapeInfo<RenderType>::computedShape() const
-{
- if (Shape* shape = m_shape.get())
- return shape;
-
- WritingMode writingMode = m_renderer->style()->writingMode();
- Length margin = m_renderer->style()->shapeMargin();
- Length padding = m_renderer->style()->shapePadding();
- float shapeImageThreshold = m_renderer->style()->shapeImageThreshold();
- const ShapeValue* shapeValue = this->shapeValue();
- ASSERT(shapeValue);
-
- switch (shapeValue->type()) {
- case ShapeValue::Shape:
- ASSERT(shapeValue->shape());
- m_shape = Shape::createShape(shapeValue->shape(), m_shapeLogicalSize, writingMode, margin, padding);
- break;
- case ShapeValue::Image:
- ASSERT(shapeValue->image());
- m_shape = Shape::createShape(shapeValue->image(), shapeImageThreshold, m_shapeLogicalSize, writingMode, margin, padding);
- break;
- case ShapeValue::Box:
- m_shape = Shape::createLayoutBoxShape(m_shapeLogicalSize, writingMode, margin, padding);
- break;
- case ShapeValue::Outside:
- // Outside should have already resolved to a different shape value.
- ASSERT_NOT_REACHED();
- }
-
- ASSERT(m_shape);
- return m_shape.get();
-}
-
-template<class RenderType>
-SegmentList ShapeInfo<RenderType>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
-{
- ASSERT(lineHeight >= 0);
- SegmentList segments;
-
- getIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
-
- for (size_t i = 0; i < segments.size(); i++) {
- segments[i].logicalLeft += logicalLeftOffset();
- segments[i].logicalRight += logicalLeftOffset();
- }
-
- return segments;
-}
-
-template class ShapeInfo<RenderBlock>;
-template class ShapeInfo<RenderBox>;
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h
deleted file mode 100644
index 1314f3409c1..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInfo.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-* Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* 1. Redistributions of source code must retain the above
-* copyright notice, this list of conditions and the following
-* disclaimer.
-* 2. Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials
-* provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
-* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
-
-#ifndef ShapeInfo_h
-#define ShapeInfo_h
-
-#include "core/rendering/shapes/Shape.h"
-#include "core/rendering/style/RenderStyle.h"
-#include "core/rendering/style/ShapeValue.h"
-#include "platform/LayoutUnit.h"
-#include "platform/geometry/FloatRect.h"
-#include "wtf/OwnPtr.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-template<class KeyType, class InfoType>
-class MappedInfo {
-public:
- static InfoType* ensureInfo(const KeyType* key)
- {
- InfoMap& infoMap = MappedInfo<KeyType, InfoType>::infoMap();
- if (InfoType* info = infoMap.get(key))
- return info;
- typename InfoMap::AddResult result = infoMap.add(key, InfoType::createInfo(key));
- return result.iterator->value.get();
- }
- static void removeInfo(const KeyType* key) { infoMap().remove(key); }
- static InfoType* info(const KeyType* key) { return infoMap().get(key); }
-private:
- typedef HashMap<const KeyType*, OwnPtr<InfoType> > InfoMap;
- static InfoMap& infoMap()
- {
- DEFINE_STATIC_LOCAL(InfoMap, staticInfoMap, ());
- return staticInfoMap;
- }
-};
-
-template<class RenderType>
-class ShapeInfo {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- virtual ~ShapeInfo() { }
-
- void setShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight)
- {
- if (shapeValue()->type() == ShapeValue::Box) {
- switch (shapeValue()->layoutBox()) {
- case MarginBox:
- logicalHeight += m_renderer->marginLogicalHeight();
- logicalWidth += m_renderer->marginLogicalWidth();
- break;
- case BorderBox:
- break;
- case PaddingBox:
- logicalHeight -= m_renderer->borderLogicalHeight();
- logicalWidth -= m_renderer->borderLogicalWidth();
- break;
- case ContentBox:
- logicalHeight -= m_renderer->borderAndPaddingLogicalHeight();
- logicalWidth -= m_renderer->borderAndPaddingLogicalWidth();
- break;
- }
- } else if (m_renderer->style()->boxSizing() == CONTENT_BOX) {
- logicalHeight -= m_renderer->borderAndPaddingLogicalHeight();
- logicalWidth -= m_renderer->borderAndPaddingLogicalWidth();
- }
-
- LayoutSize newLogicalSize(logicalWidth, logicalHeight);
- if (m_shapeLogicalSize == newLogicalSize)
- return;
- dirtyShapeSize();
- m_shapeLogicalSize = newLogicalSize;
- }
-
- SegmentList computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const;
-
- LayoutUnit shapeLogicalTop() const { return computedShapeLogicalBoundingBox().y() + logicalTopOffset(); }
- LayoutUnit shapeLogicalBottom() const { return computedShapeLogicalBoundingBox().maxY() + logicalTopOffset(); }
- LayoutUnit shapeLogicalLeft() const { return computedShapeLogicalBoundingBox().x() + logicalLeftOffset(); }
- LayoutUnit shapeLogicalRight() const { return computedShapeLogicalBoundingBox().maxX() + logicalLeftOffset(); }
- LayoutUnit shapeLogicalWidth() const { return computedShapeLogicalBoundingBox().width(); }
- LayoutUnit shapeLogicalHeight() const { return computedShapeLogicalBoundingBox().height(); }
-
- LayoutUnit logicalLineTop() const { return m_shapeLineTop + logicalTopOffset(); }
- LayoutUnit logicalLineBottom() const { return m_shapeLineTop + m_lineHeight + logicalTopOffset(); }
-
- LayoutUnit shapeContainingBlockHeight() const { return (m_renderer->style()->boxSizing() == CONTENT_BOX) ? (m_shapeLogicalSize.height() + m_renderer->borderAndPaddingLogicalHeight()) : m_shapeLogicalSize.height(); }
-
- virtual bool lineOverlapsShapeBounds() const = 0;
-
- void dirtyShapeSize() { m_shape.clear(); }
- bool shapeSizeDirty() { return !m_shape.get(); }
- const RenderType* owner() const { return m_renderer; }
- LayoutSize shapeSize() const { return m_shapeLogicalSize; }
-
-protected:
- ShapeInfo(const RenderType* renderer): m_renderer(renderer) { }
-
- const Shape* computedShape() const;
-
- virtual LayoutRect computedShapeLogicalBoundingBox() const = 0;
- virtual ShapeValue* shapeValue() const = 0;
- virtual void getIntervals(LayoutUnit, LayoutUnit, SegmentList&) const = 0;
-
- LayoutUnit logicalTopOffset() const
- {
- if (shapeValue()->type() == ShapeValue::Box) {
- switch (shapeValue()->layoutBox()) {
- case MarginBox:
- return -m_renderer->marginBefore();
- case BorderBox:
- return LayoutUnit();
- case PaddingBox:
- return m_renderer->borderBefore();
- case ContentBox:
- return m_renderer->borderAndPaddingBefore();
- }
- }
- return m_renderer->style()->boxSizing() == CONTENT_BOX ? m_renderer->borderAndPaddingBefore() : LayoutUnit();
- }
-
- LayoutUnit logicalLeftOffset() const
- {
- if (shapeValue()->type() == ShapeValue::Box) {
- switch (shapeValue()->layoutBox()) {
- case MarginBox:
- return -m_renderer->marginStart();
- case BorderBox:
- return LayoutUnit();
- case PaddingBox:
- return m_renderer->borderStart();
- case ContentBox:
- return m_renderer->borderAndPaddingStart();
- }
- }
- return (m_renderer->style()->boxSizing() == CONTENT_BOX && !m_renderer->isRenderRegion()) ? m_renderer->borderAndPaddingStart() : LayoutUnit();
- }
-
- LayoutUnit m_shapeLineTop;
- LayoutUnit m_lineHeight;
-
- const RenderType* m_renderer;
-
-private:
- mutable OwnPtr<Shape> m_shape;
- LayoutSize m_shapeLogicalSize;
-};
-
-bool checkShapeImageOrigin(Document&, ImageResource&);
-
-}
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp
deleted file mode 100644
index 301200b19e7..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "core/rendering/shapes/ShapeInsideInfo.h"
-
-#include "core/rendering/InlineIterator.h"
-#include "core/rendering/RenderBlock.h"
-
-namespace WebCore {
-
-LineSegmentRange::LineSegmentRange(const InlineIterator& start, const InlineIterator& end)
- : start(start.root(), start.object(), start.offset())
- , end(end.root(), end.object(), end.offset())
- {
- }
-
-bool ShapeInsideInfo::isEnabledFor(const RenderBlock* renderer)
-{
- ShapeValue* shapeValue = renderer->style()->resolvedShapeInside();
- if (!shapeValue)
- return false;
-
- switch (shapeValue->type()) {
- case ShapeValue::Shape:
- return shapeValue->shape() && shapeValue->shape()->type() != BasicShape::BasicShapeInsetRectangleType;
- case ShapeValue::Image:
- return shapeValue->isImageValid() && checkShapeImageOrigin(renderer->document(), *(shapeValue->image()->cachedImage()));
- case ShapeValue::Box:
- case ShapeValue::Outside:
- return false;
- }
-
- return false;
-}
-
-bool ShapeInsideInfo::updateSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight)
-{
- bool result = updateSegmentsForLine(lineOffset.height(), lineHeight);
- for (size_t i = 0; i < m_segments.size(); i++) {
- m_segments[i].logicalLeft -= lineOffset.width();
- m_segments[i].logicalRight -= lineOffset.width();
- }
- return result;
-}
-
-bool ShapeInsideInfo::updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
-{
- ASSERT(lineHeight >= 0);
- m_shapeLineTop = lineTop - logicalTopOffset();
- m_lineHeight = lineHeight;
- m_segments.clear();
- m_segmentRanges.clear();
-
- if (lineOverlapsShapeBounds())
- m_segments = computeSegmentsForLine(lineTop, lineHeight);
-
- return m_segments.size();
-}
-
-bool ShapeInsideInfo::adjustLogicalLineTop(float minSegmentWidth)
-{
- const Shape* shape = computedShape();
- if (!shape || m_lineHeight <= 0 || logicalLineTop() > shapeLogicalBottom())
- return false;
-
- LayoutUnit newLineTop;
- if (shape->firstIncludedIntervalLogicalTop(m_shapeLineTop, LayoutSize(minSegmentWidth, m_lineHeight), newLineTop)) {
- if (newLineTop > m_shapeLineTop) {
- m_shapeLineTop = newLineTop;
- return true;
- }
- }
-
- return false;
-}
-
-ShapeValue* ShapeInsideInfo::shapeValue() const
-{
- return m_renderer->style()->resolvedShapeInside();
-}
-
-LayoutUnit ShapeInsideInfo::computeFirstFitPositionForFloat(const LayoutSize floatSize) const
-{
- if (!computedShape() || !floatSize.width() || shapeLogicalBottom() < logicalLineTop())
- return 0;
-
- LayoutUnit firstFitPosition = 0;
- if (computedShape()->firstIncludedIntervalLogicalTop(m_shapeLineTop, floatSize, firstFitPosition) && (m_shapeLineTop <= firstFitPosition))
- return firstFitPosition;
-
- return 0;
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h
deleted file mode 100644
index 0f0f3855266..00000000000
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInsideInfo.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef ShapeInsideInfo_h
-#define ShapeInsideInfo_h
-
-#include "core/rendering/shapes/ShapeInfo.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-class InlineIterator;
-class RenderBlock;
-class RenderObject;
-
-struct LineSegmentIterator {
- RenderObject* root;
- RenderObject* object;
- unsigned offset;
- LineSegmentIterator(RenderObject* root, RenderObject* object, unsigned offset)
- : root(root)
- , object(object)
- , offset(offset)
- {
- }
-};
-
-struct LineSegmentRange {
- LineSegmentIterator start;
- LineSegmentIterator end;
- LineSegmentRange(const InlineIterator& start, const InlineIterator& end);
-};
-
-typedef Vector<LineSegmentRange> SegmentRangeList;
-
-class ShapeInsideInfo FINAL : public ShapeInfo<RenderBlock> {
-public:
- static PassOwnPtr<ShapeInsideInfo> createInfo(const RenderBlock* renderer) { return adoptPtr(new ShapeInsideInfo(renderer)); }
-
- static bool isEnabledFor(const RenderBlock* renderer);
-
- bool updateSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight);
- bool updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
-
- bool hasSegments() const
- {
- return lineOverlapsShapeBounds() && m_segments.size();
- }
- const SegmentList& segments() const
- {
- ASSERT(hasSegments());
- return m_segments;
- }
- SegmentRangeList& segmentRanges() { return m_segmentRanges; }
- const SegmentRangeList& segmentRanges() const { return m_segmentRanges; }
- const LineSegment* currentSegment() const
- {
- if (!hasSegments())
- return 0;
- ASSERT(m_segmentRanges.size() < m_segments.size());
- return &m_segments[m_segmentRanges.size()];
- }
- void clearSegments() { m_segments.clear(); }
- bool adjustLogicalLineTop(float minSegmentWidth);
- LayoutUnit computeFirstFitPositionForFloat(const LayoutSize) const;
-
- void setNeedsLayout(bool value) { m_needsLayout = value; }
- bool needsLayout() { return m_needsLayout; }
-
- virtual bool lineOverlapsShapeBounds() const OVERRIDE
- {
- return computedShape()->lineOverlapsShapePaddingBounds(m_shapeLineTop, m_lineHeight);
- }
-
-protected:
- virtual LayoutRect computedShapeLogicalBoundingBox() const OVERRIDE { return computedShape()->shapePaddingLogicalBoundingBox(); }
- virtual ShapeValue* shapeValue() const OVERRIDE;
- virtual void getIntervals(LayoutUnit lineTop, LayoutUnit lineHeight, SegmentList& segments) const OVERRIDE
- {
- return computedShape()->getIncludedIntervals(lineTop, lineHeight, segments);
- }
-
-private:
- ShapeInsideInfo(const RenderBlock* renderer)
- : ShapeInfo<RenderBlock> (renderer)
- , m_needsLayout(false)
- { }
-
- SegmentRangeList m_segmentRanges;
- bool m_needsLayout;
- SegmentList m_segments;
-};
-
-}
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h
index efeb7d862c0..47c20178f0f 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeInterval.h
@@ -38,29 +38,27 @@ template <typename T>
class ShapeInterval {
WTF_MAKE_FAST_ALLOCATED;
public:
- ShapeInterval(T x1 = 0, T x2 = 0)
- : m_x1(x1)
- , m_x2(x2)
+ ShapeInterval()
+ : m_x1(-1)
+ , m_x2(-2)
{
- ASSERT(x2 >= x1);
+ // The initial values of m_x1,x2 don't matter (unless you're looking
+ // at them in the debugger) so long as isUndefined() is true.
+ ASSERT(isUndefined());
}
- T x1() const { return m_x1; }
- T x2() const { return m_x2; }
- T width() const { return m_x2 - m_x1; }
- bool isEmpty() const { return m_x1 == m_x2; }
-
- void setX1(T x1)
+ ShapeInterval(T x1, T x2)
+ : m_x1(x1)
+ , m_x2(x2)
{
- ASSERT(m_x2 >= x1);
- m_x1 = x1;
+ ASSERT(x2 >= x1);
}
- void setX2(T x2)
- {
- ASSERT(x2 >= m_x1);
- m_x2 = x2;
- }
+ bool isUndefined() const { return m_x2 < m_x1; }
+ T x1() const { return isUndefined() ? 0 : m_x1; }
+ T x2() const { return isUndefined() ? 0 : m_x2; }
+ T width() const { return isUndefined() ? 0 : m_x2 - m_x1; }
+ bool isEmpty() const { return isUndefined() ? true : m_x1 == m_x2; }
void set(T x1, T x2)
{
@@ -71,155 +69,34 @@ public:
bool overlaps(const ShapeInterval<T>& interval) const
{
+ if (isUndefined() || interval.isUndefined())
+ return false;
return x2() >= interval.x1() && x1() <= interval.x2();
}
bool contains(const ShapeInterval<T>& interval) const
{
+ if (isUndefined() || interval.isUndefined())
+ return false;
return x1() <= interval.x1() && x2() >= interval.x2();
}
- ShapeInterval<T> intersect(const ShapeInterval<T>& interval) const
- {
- ASSERT(overlaps(interval));
- return ShapeInterval<T>(std::max<T>(x1(), interval.x1()), std::min<T>(x2(), interval.x2()));
- }
-
- typedef Vector<ShapeInterval<T> > ShapeIntervals;
- typedef typename ShapeIntervals::const_iterator const_iterator;
- typedef typename ShapeIntervals::iterator iterator;
-
- static void uniteShapeIntervals(const ShapeIntervals& a, const ShapeIntervals& b, ShapeIntervals& result)
- {
- ASSERT(shapeIntervalsAreSortedAndDisjoint(a) && shapeIntervalsAreSortedAndDisjoint(b));
-
- if (a.isEmpty() || a == b) {
- result.appendRange(b.begin(), b.end());
- return;
- }
-
- if (b.isEmpty()) {
- result.appendRange(a.begin(), a.end());
- return;
- }
-
- const_iterator aNext = a.begin();
- const_iterator bNext = b.begin();
-
- while (aNext != a.end() || bNext != b.end()) {
- const_iterator next = (bNext == b.end() || (aNext != a.end() && aNext->x1() < bNext->x1())) ? aNext++ : bNext++;
- if (result.isEmpty() || !result.last().overlaps(*next))
- result.append(*next);
- else
- result.last().setX2(std::max<T>(result.last().x2(), next->x2()));
- }
- }
-
- static void intersectShapeIntervals(const ShapeIntervals& a, const ShapeIntervals& b, ShapeIntervals& result)
- {
- ASSERT(shapeIntervalsAreSortedAndDisjoint(a) && shapeIntervalsAreSortedAndDisjoint(b));
-
- if (a.isEmpty() || b.isEmpty())
- return;
-
- if (a == b) {
- result.appendRange(a.begin(), a.end());
- return;
- }
-
- const_iterator aNext = a.begin();
- const_iterator bNext = b.begin();
- const_iterator working = aNext->x1() < bNext->x1() ? aNext++ : bNext++;
-
- while (aNext != a.end() || bNext != b.end()) {
- const_iterator next = (bNext == b.end() || (aNext != a.end() && aNext->x1() < bNext->x1())) ? aNext++ : bNext++;
- if (working->overlaps(*next)) {
- result.append(working->intersect(*next));
- if (next->x2() > working->x2())
- working = next;
- } else {
- working = next;
- }
- }
- }
+ bool operator==(const ShapeInterval<T>& other) const { return x1() == other.x1() && x2() == other.x2(); }
+ bool operator!=(const ShapeInterval<T>& other) const { return !operator==(other); }
- static void subtractShapeIntervals(const ShapeIntervals& a, const ShapeIntervals& b, ShapeIntervals& result)
+ void unite(const ShapeInterval<T>& interval)
{
- ASSERT(shapeIntervalsAreSortedAndDisjoint(a) && shapeIntervalsAreSortedAndDisjoint(b));
-
- if (a.isEmpty() || a == b)
- return;
-
- if (b.isEmpty()) {
- result.appendRange(a.begin(), a.end());
+ if (interval.isUndefined())
return;
- }
-
- const_iterator aNext = a.begin();
- const_iterator bNext = b.begin();
- ShapeInterval<T> aValue = *aNext;
- ShapeInterval<T> bValue = *bNext;
-
- do {
- bool aIncrement = false;
- bool bIncrement = false;
-
- if (bValue.contains(aValue)) {
- aIncrement = true;
- } else if (aValue.contains(bValue)) {
- if (bValue.x1() > aValue.x1())
- result.append(ShapeInterval<T>(aValue.x1(), bValue.x1()));
- if (aValue.x2() > bValue.x2())
- aValue.setX1(bValue.x2());
- else
- aIncrement = true;
- bIncrement = true;
- } else if (aValue.overlaps(bValue)) {
- if (aValue.x1() < bValue.x1()) {
- result.append(ShapeInterval<T>(aValue.x1(), bValue.x1()));
- aIncrement = true;
- } else {
- aValue.setX1(bValue.x2());
- bIncrement = true;
- }
- } else {
- if (aValue.x1() < bValue.x1()) {
- result.append(aValue);
- aIncrement = true;
- } else {
- bIncrement = true;
- }
- }
-
- if (aIncrement && ++aNext != a.end())
- aValue = *aNext;
- if (bIncrement && ++bNext != b.end())
- bValue = *bNext;
-
- } while (aNext != a.end() && bNext != b.end());
-
- if (aNext != a.end()) {
- result.append(aValue);
- result.appendRange(++aNext, a.end());
- }
+ if (isUndefined())
+ set(interval.x1(), interval.x2());
+ else
+ set(std::min<T>(x1(), interval.x1()), std::max<T>(x2(), interval.x2()));
}
- bool operator==(const ShapeInterval<T>& other) const { return x1() == other.x1() && x2() == other.x2(); }
- bool operator!=(const ShapeInterval<T>& other) const { return !operator==(other); }
-
private:
T m_x1;
T m_x2;
-
- static bool shapeIntervalsAreSortedAndDisjoint(const ShapeIntervals& intervals)
- {
- for (unsigned i = 1; i < intervals.size(); i++) {
- if (intervals[i - 1].x2() > intervals[i].x1())
- return false;
- }
-
- return true;
- }
};
typedef ShapeInterval<int> IntShapeInterval;
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp
index 98bea9a0a16..216d3091acf 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.cpp
@@ -33,48 +33,269 @@
#include "core/rendering/FloatingObjects.h"
#include "core/rendering/RenderBlockFlow.h"
#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderImage.h"
+#include "platform/LengthFunctions.h"
namespace WebCore {
-bool ShapeOutsideInfo::isEnabledFor(const RenderBox* box)
+
+CSSBoxType referenceBox(const ShapeValue& shapeValue)
+{
+ if (shapeValue.cssBox() == BoxMissing)
+ return MarginBox;
+ return shapeValue.cssBox();
+}
+
+void ShapeOutsideInfo::setReferenceBoxLogicalSize(LayoutSize newReferenceBoxLogicalSize)
+{
+ bool isHorizontalWritingMode = m_renderer.containingBlock()->style()->isHorizontalWritingMode();
+ switch (referenceBox(*m_renderer.style()->shapeOutside())) {
+ case MarginBox:
+ if (isHorizontalWritingMode)
+ newReferenceBoxLogicalSize.expand(m_renderer.marginWidth(), m_renderer.marginHeight());
+ else
+ newReferenceBoxLogicalSize.expand(m_renderer.marginHeight(), m_renderer.marginWidth());
+ break;
+ case BorderBox:
+ break;
+ case PaddingBox:
+ if (isHorizontalWritingMode)
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderWidth(), m_renderer.borderHeight());
+ else
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderHeight(), m_renderer.borderWidth());
+ break;
+ case ContentBox:
+ if (isHorizontalWritingMode)
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingWidth(), m_renderer.borderAndPaddingHeight());
+ else
+ newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingHeight(), m_renderer.borderAndPaddingWidth());
+ break;
+ case BoxMissing:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ if (m_referenceBoxLogicalSize == newReferenceBoxLogicalSize)
+ return;
+ markShapeAsDirty();
+ m_referenceBoxLogicalSize = newReferenceBoxLogicalSize;
+}
+
+static bool checkShapeImageOrigin(Document& document, const StyleImage& styleImage)
{
- ShapeValue* shapeValue = box->style()->shapeOutside();
- if (!box->isFloating() || !shapeValue)
+ if (styleImage.isGeneratedImage())
+ return true;
+
+ ASSERT(styleImage.cachedImage());
+ ImageResource& imageResource = *(styleImage.cachedImage());
+ if (imageResource.isAccessAllowed(document.securityOrigin()))
+ return true;
+
+ const KURL& url = imageResource.url();
+ String urlString = url.isNull() ? "''" : url.elidedString();
+ document.addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + ".");
+
+ return false;
+}
+
+static LayoutRect getShapeImageMarginRect(const RenderBox& renderBox, const LayoutSize& referenceBoxLogicalSize)
+{
+ LayoutPoint marginBoxOrigin(-renderBox.marginLogicalLeft() - renderBox.borderAndPaddingLogicalLeft(), -renderBox.marginBefore() - renderBox.borderBefore() - renderBox.paddingBefore());
+ LayoutSize marginBoxSizeDelta(renderBox.marginLogicalWidth() + renderBox.borderAndPaddingLogicalWidth(), renderBox.marginLogicalHeight() + renderBox.borderAndPaddingLogicalHeight());
+ return LayoutRect(marginBoxOrigin, referenceBoxLogicalSize + marginBoxSizeDelta);
+}
+
+PassOwnPtr<Shape> ShapeOutsideInfo::createShapeForImage(StyleImage* styleImage, float shapeImageThreshold, WritingMode writingMode, float margin) const
+{
+ const IntSize& imageSize = m_renderer.calculateImageIntrinsicDimensions(styleImage, roundedIntSize(m_referenceBoxLogicalSize), RenderImage::ScaleByEffectiveZoom);
+ styleImage->setContainerSizeForRenderer(&m_renderer, imageSize, m_renderer.style()->effectiveZoom());
+
+ const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referenceBoxLogicalSize);
+ const LayoutRect& imageRect = (m_renderer.isRenderImage())
+ ? toRenderImage(&m_renderer)->replacedContentRect()
+ : LayoutRect(LayoutPoint(), imageSize);
+
+ ASSERT(!styleImage->isPendingImage());
+ RefPtr<Image> image = styleImage->image(const_cast<RenderBox*>(&m_renderer), imageSize);
+
+ return Shape::createRasterShape(image.get(), shapeImageThreshold, imageRect, marginRect, writingMode, margin);
+}
+
+const Shape& ShapeOutsideInfo::computedShape() const
+{
+ if (Shape* shape = m_shape.get())
+ return *shape;
+
+ const RenderStyle& style = *m_renderer.style();
+ ASSERT(m_renderer.containingBlock());
+ const RenderStyle& containingBlockStyle = *m_renderer.containingBlock()->style();
+
+ WritingMode writingMode = containingBlockStyle.writingMode();
+ LayoutUnit maximumValue = m_renderer.containingBlock() ? m_renderer.containingBlock()->contentWidth() : LayoutUnit();
+ float margin = floatValueForLength(m_renderer.style()->shapeMargin(), maximumValue.toFloat());
+
+ float shapeImageThreshold = style.shapeImageThreshold();
+ ASSERT(style.shapeOutside());
+ const ShapeValue& shapeValue = *style.shapeOutside();
+
+ switch (shapeValue.type()) {
+ case ShapeValue::Shape:
+ ASSERT(shapeValue.shape());
+ m_shape = Shape::createShape(shapeValue.shape(), m_referenceBoxLogicalSize, writingMode, margin);
+ break;
+ case ShapeValue::Image:
+ ASSERT(shapeValue.isImageValid());
+ m_shape = createShapeForImage(shapeValue.image(), shapeImageThreshold, writingMode, margin);
+ break;
+ case ShapeValue::Box: {
+ const RoundedRect& shapeRect = style.getRoundedBorderFor(LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize), m_renderer.view());
+ m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin);
+ break;
+ }
+ }
+
+ ASSERT(m_shape);
+ return *m_shape;
+}
+
+SegmentList ShapeOutsideInfo::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
+{
+ ASSERT(lineHeight >= 0);
+ SegmentList segments;
+
+ computedShape().getExcludedIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
+
+ for (size_t i = 0; i < segments.size(); i++) {
+ segments[i].logicalLeft += logicalLeftOffset();
+ segments[i].logicalRight += logicalLeftOffset();
+ }
+
+ return segments;
+}
+
+inline LayoutUnit borderBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
+{
+ switch (writingMode) {
+ case TopToBottomWritingMode: return renderer.borderTop();
+ case BottomToTopWritingMode: return renderer.borderBottom();
+ case LeftToRightWritingMode: return renderer.borderLeft();
+ case RightToLeftWritingMode: return renderer.borderRight();
+ }
+
+ ASSERT_NOT_REACHED();
+ return renderer.borderBefore();
+}
+
+inline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
+{
+ switch (writingMode) {
+ case TopToBottomWritingMode: return renderer.borderTop() + renderer.paddingTop();
+ case BottomToTopWritingMode: return renderer.borderBottom() + renderer.paddingBottom();
+ case LeftToRightWritingMode: return renderer.borderLeft() + renderer.paddingLeft();
+ case RightToLeftWritingMode: return renderer.borderRight() + renderer.paddingRight();
+ }
+
+ ASSERT_NOT_REACHED();
+ return renderer.borderAndPaddingBefore();
+}
+
+LayoutUnit ShapeOutsideInfo::logicalTopOffset() const
+{
+ switch (referenceBox(*m_renderer.style()->shapeOutside())) {
+ case MarginBox: return -m_renderer.marginBefore(m_renderer.containingBlock()->style());
+ case BorderBox: return LayoutUnit();
+ case PaddingBox: return borderBeforeInWritingMode(m_renderer, m_renderer.containingBlock()->style()->writingMode());
+ case ContentBox: return borderAndPaddingBeforeInWritingMode(m_renderer, m_renderer.containingBlock()->style()->writingMode());
+ case BoxMissing: break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return LayoutUnit();
+}
+
+inline LayoutUnit borderStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
+{
+ if (style->isHorizontalWritingMode()) {
+ if (style->isLeftToRightDirection())
+ return renderer.borderLeft();
+
+ return renderer.borderRight();
+ }
+ if (style->isLeftToRightDirection())
+ return renderer.borderTop();
+
+ return renderer.borderBottom();
+}
+
+inline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
+{
+ if (style->isHorizontalWritingMode()) {
+ if (style->isLeftToRightDirection())
+ return renderer.borderLeft() + renderer.paddingLeft();
+
+ return renderer.borderRight() + renderer.paddingRight();
+ }
+ if (style->isLeftToRightDirection())
+ return renderer.borderTop() + renderer.paddingTop();
+
+ return renderer.borderBottom() + renderer.paddingBottom();
+}
+
+LayoutUnit ShapeOutsideInfo::logicalLeftOffset() const
+{
+ switch (referenceBox(*m_renderer.style()->shapeOutside())) {
+ case MarginBox: return -m_renderer.marginStart(m_renderer.containingBlock()->style());
+ case BorderBox: return LayoutUnit();
+ case PaddingBox: return borderStartWithStyleForWritingMode(m_renderer, m_renderer.containingBlock()->style());
+ case ContentBox: return borderAndPaddingStartWithStyleForWritingMode(m_renderer, m_renderer.containingBlock()->style());
+ case BoxMissing: break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return LayoutUnit();
+}
+
+
+bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box)
+{
+ ShapeValue* shapeValue = box.style()->shapeOutside();
+ if (!box.isFloating() || !shapeValue)
return false;
switch (shapeValue->type()) {
case ShapeValue::Shape:
return shapeValue->shape();
case ShapeValue::Image:
- return shapeValue->isImageValid() && checkShapeImageOrigin(box->document(), *(shapeValue->image()->cachedImage()));
+ return shapeValue->isImageValid() && checkShapeImageOrigin(box.document(), *(shapeValue->image()));
case ShapeValue::Box:
return true;
- case ShapeValue::Outside:
- return false;
}
return false;
}
-void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow* containingBlock, const FloatingObject* floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight)
+void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight)
{
- LayoutUnit shapeTop = containingBlock->logicalTopForFloat(floatingObject) + std::max(LayoutUnit(), containingBlock->marginBeforeForChild(m_renderer));
- LayoutUnit floatRelativeLineTop = lineTop - shapeTop;
+ LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(&m_renderer);
+ LayoutUnit borderBoxLineTop = lineTop - borderBoxTop;
- if (shapeSizeDirty() || m_lineTop != floatRelativeLineTop || m_lineHeight != lineHeight) {
- m_lineTop = floatRelativeLineTop;
- m_shapeLineTop = floatRelativeLineTop - logicalTopOffset();
+ if (isShapeDirty() || m_borderBoxLineTop != borderBoxLineTop || m_lineHeight != lineHeight) {
+ m_borderBoxLineTop = borderBoxLineTop;
+ m_referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
m_lineHeight = lineHeight;
- LayoutUnit floatMarginBoxWidth = containingBlock->logicalWidthForFloat(floatingObject);
+ LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject);
if (lineOverlapsShapeBounds()) {
- SegmentList segments = computeSegmentsForLine(floatRelativeLineTop, lineHeight);
+ SegmentList segments = computeSegmentsForLine(borderBoxLineTop, lineHeight);
if (segments.size()) {
- LayoutUnit rawLeftMarginBoxDelta = segments.first().logicalLeft + containingBlock->marginStartForChild(m_renderer);
- m_leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth);
+ LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(&m_renderer) : containingBlock.marginEndForChild(&m_renderer);
+ LayoutUnit rawLeftMarginBoxDelta = segments.first().logicalLeft + logicalLeftMargin;
+ m_leftMarginBoxDelta = clampToLayoutUnit(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth);
- LayoutUnit rawRightMarginBoxDelta = segments.last().logicalRight - containingBlock->logicalWidthForChild(m_renderer) - containingBlock->marginEndForChild(m_renderer);
- m_rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
+ LayoutUnit logicalRightMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginEndForChild(&m_renderer) : containingBlock.marginStartForChild(&m_renderer);
+ LayoutUnit rawRightMarginBoxDelta = segments.last().logicalRight - containingBlock.logicalWidthForChild(&m_renderer) - logicalRightMargin;
+ m_rightMarginBoxDelta = clampToLayoutUnit(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
+ m_lineOverlapsShape = true;
return;
}
}
@@ -82,19 +303,45 @@ void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow*
// Lines that do not overlap the shape should act as if the float
// wasn't there for layout purposes. So we set the deltas to remove the
// entire width of the float.
- // FIXME: The latest CSS Shapes spec says that in this case, the
- // content should interact with previously stacked floats on the line
- // as if this outermost float did not exist. Perhaps obviously, this
- // solution cannot do that, and will be revisted when that part of the
- // spec is implemented.
m_leftMarginBoxDelta = floatMarginBoxWidth;
m_rightMarginBoxDelta = -floatMarginBoxWidth;
+ m_lineOverlapsShape = false;
}
}
-ShapeValue* ShapeOutsideInfo::shapeValue() const
+LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const
+{
+ LayoutRect physicalBoundingBox = computedShape().shapeMarginLogicalBoundingBox();
+ physicalBoundingBox.setX(physicalBoundingBox.x() + logicalLeftOffset());
+
+ if (m_renderer.style()->isFlippedBlocksWritingMode())
+ physicalBoundingBox.setY(m_renderer.logicalHeight() - physicalBoundingBox.maxY());
+ else
+ physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset());
+
+ if (!m_renderer.style()->isHorizontalWritingMode())
+ physicalBoundingBox = physicalBoundingBox.transposedRect();
+ else
+ physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset());
+
+ return physicalBoundingBox;
+}
+
+FloatPoint ShapeOutsideInfo::shapeToRendererPoint(FloatPoint point) const
+{
+ FloatPoint result = FloatPoint(point.x() + logicalLeftOffset(), point.y() + logicalTopOffset());
+ if (m_renderer.style()->isFlippedBlocksWritingMode())
+ result.setY(m_renderer.logicalHeight() - result.y());
+ if (!m_renderer.style()->isHorizontalWritingMode())
+ result = result.transposedPoint();
+ return result;
+}
+
+FloatSize ShapeOutsideInfo::shapeToRendererSize(FloatSize size) const
{
- return m_renderer->style()->shapeOutside();
+ if (!m_renderer.style()->isHorizontalWritingMode())
+ return size.transposedSize();
+ return size;
}
}
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h
index 82b31f65f69..36276e91fdb 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/ShapeOutsideInfo.h
@@ -30,8 +30,13 @@
#ifndef ShapeOutsideInfo_h
#define ShapeOutsideInfo_h
-#include "core/rendering/shapes/ShapeInfo.h"
+#include "core/rendering/shapes/Shape.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/ShapeValue.h"
+#include "platform/geometry/FloatRect.h"
#include "platform/geometry/LayoutSize.h"
+#include "wtf/OwnPtr.h"
+#include "wtf/Vector.h"
namespace WebCore {
@@ -39,35 +44,85 @@ class RenderBlockFlow;
class RenderBox;
class FloatingObject;
-class ShapeOutsideInfo FINAL : public ShapeInfo<RenderBox>, public MappedInfo<RenderBox, ShapeOutsideInfo> {
+class ShapeOutsideInfo FINAL {
+ WTF_MAKE_FAST_ALLOCATED;
public:
+ void setReferenceBoxLogicalSize(LayoutSize);
+
+ SegmentList computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const;
+
+ LayoutUnit shapeLogicalTop() const { return computedShape().shapeMarginLogicalBoundingBox().y() + logicalTopOffset(); }
+ LayoutUnit shapeLogicalBottom() const { return computedShape().shapeMarginLogicalBoundingBox().maxY() + logicalTopOffset(); }
+ LayoutUnit shapeLogicalLeft() const { return computedShape().shapeMarginLogicalBoundingBox().x() + logicalLeftOffset(); }
+ LayoutUnit shapeLogicalRight() const { return computedShape().shapeMarginLogicalBoundingBox().maxX() + logicalLeftOffset(); }
+ LayoutUnit shapeLogicalWidth() const { return computedShape().shapeMarginLogicalBoundingBox().width(); }
+ LayoutUnit shapeLogicalHeight() const { return computedShape().shapeMarginLogicalBoundingBox().height(); }
+
+ LayoutUnit logicalLineTop() const { return m_referenceBoxLineTop + logicalTopOffset(); }
+ LayoutUnit logicalLineBottom() const { return m_referenceBoxLineTop + m_lineHeight + logicalTopOffset(); }
+
LayoutUnit leftMarginBoxDelta() const { return m_leftMarginBoxDelta; }
LayoutUnit rightMarginBoxDelta() const { return m_rightMarginBoxDelta; }
+ bool lineOverlapsShape() const { return m_lineOverlapsShape; }
- void updateDeltasForContainingBlockLine(const RenderBlockFlow*, const FloatingObject*, LayoutUnit lineTop, LayoutUnit lineHeight);
+ static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox& renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); }
+ static bool isEnabledFor(const RenderBox&);
+ void updateDeltasForContainingBlockLine(const RenderBlockFlow&, const FloatingObject&, LayoutUnit lineTop, LayoutUnit lineHeight);
- static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox* renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); }
- static bool isEnabledFor(const RenderBox*);
+ bool lineOverlapsShapeBounds() const
+ {
+ return computedShape().lineOverlapsShapeMarginBounds(m_referenceBoxLineTop, m_lineHeight);
+ }
- virtual bool lineOverlapsShapeBounds() const OVERRIDE
+ static ShapeOutsideInfo& ensureInfo(const RenderBox& key)
{
- return computedShape()->lineOverlapsShapeMarginBounds(m_shapeLineTop, m_lineHeight);
+ InfoMap& infoMap = ShapeOutsideInfo::infoMap();
+ if (ShapeOutsideInfo* info = infoMap.get(&key))
+ return *info;
+ InfoMap::AddResult result = infoMap.add(&key, ShapeOutsideInfo::createInfo(key));
+ return *result.storedValue->value;
}
+ static void removeInfo(const RenderBox& key) { infoMap().remove(&key); }
+ static ShapeOutsideInfo* info(const RenderBox& key) { return infoMap().get(&key); }
+
+ void markShapeAsDirty() { m_shape.clear(); }
+ bool isShapeDirty() { return !m_shape.get(); }
+ LayoutSize shapeSize() const { return m_referenceBoxLogicalSize; }
+
+ LayoutRect computedShapePhysicalBoundingBox() const;
+ FloatPoint shapeToRendererPoint(FloatPoint) const;
+ FloatSize shapeToRendererSize(FloatSize) const;
+ const Shape& computedShape() const;
protected:
- virtual LayoutRect computedShapeLogicalBoundingBox() const OVERRIDE { return computedShape()->shapeMarginLogicalBoundingBox(); }
- virtual ShapeValue* shapeValue() const OVERRIDE;
- virtual void getIntervals(LayoutUnit lineTop, LayoutUnit lineHeight, SegmentList& segments) const OVERRIDE
+ ShapeOutsideInfo(const RenderBox& renderer)
+ : m_renderer(renderer)
+ , m_lineOverlapsShape(false)
+ { }
+
+private:
+ PassOwnPtr<Shape> createShapeForImage(StyleImage*, float shapeImageThreshold, WritingMode, float margin) const;
+
+ LayoutUnit logicalTopOffset() const;
+ LayoutUnit logicalLeftOffset() const;
+
+ typedef HashMap<const RenderBox*, OwnPtr<ShapeOutsideInfo> > InfoMap;
+ static InfoMap& infoMap()
{
- return computedShape()->getExcludedIntervals(lineTop, lineHeight, segments);
+ DEFINE_STATIC_LOCAL(InfoMap, staticInfoMap, ());
+ return staticInfoMap;
}
-private:
- ShapeOutsideInfo(const RenderBox* renderer) : ShapeInfo<RenderBox>(renderer) { }
+ LayoutUnit m_referenceBoxLineTop;
+ LayoutUnit m_lineHeight;
+ const RenderBox& m_renderer;
+ mutable OwnPtr<Shape> m_shape;
+ LayoutSize m_referenceBoxLogicalSize;
LayoutUnit m_leftMarginBoxDelta;
LayoutUnit m_rightMarginBoxDelta;
- LayoutUnit m_lineTop;
+ LayoutUnit m_borderBoxLineTop;
+ bool m_lineOverlapsShape;
};
}