Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / shapes / PolygonShape.cpp
index 2e69638..17f9df0 100644 (file)
 #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,421 +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());
-    if (startAngle < 0)
-        startAngle += twoPiFloat;
-    if (endAngle < 0)
-        endAngle += twoPiFloat;
-    float angle = (startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + twoPiFloat - endAngle);
-    const float arcSegmentCount = 6; // An even number so that one arc vertex will be eactly arcRadius from arcCenter.
-    float arcSegmentAngle =  ((padding) ? -angle : twoPiFloat - 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 bool overlapsYRange(const FloatRect& rect, float y1, float y2) { return !rect.isEmpty() && y2 >= y1 && y2 >= rect.y() && y1 <= rect.maxY(); }
 
-static inline PassOwnPtr<FloatPolygon> computeShapePaddingBounds(const FloatPolygon& polygon, float padding, WindRule fillRule)
+float OffsetPolygonEdge::xIntercept(float y) const
 {
-    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);
+    ASSERT(y >= minY() && y <= maxY());
 
-        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);
-    }
+    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();
 
-    snapVerticesToLayoutUnitGrid(*paddedVertices);
-    return adoptPtr(new FloatPolygon(paddedVertices.release(), fillRule));
+    return vertex1().x() + ((y - vertex1().y()) * (vertex2().x() - vertex1().x()) / (vertex2().y() - vertex1().y()));
 }
 
-static inline PassOwnPtr<FloatPolygon> computeShapeMarginBounds(const FloatPolygon& polygon, float margin, WindRule fillRule)
+FloatShapeInterval OffsetPolygonEdge::clippedEdgeXRange(float y1, float y2) const
 {
-    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 (!overlapsYRange(y1, y2) || (y1 == maxY() && vertex2().y() < vertex1().y()))
+        return FloatShapeInterval();
 
-        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));
-}
+    if (isWithinYRange(y1, y2))
+        return FloatShapeInterval(minX(), maxX());
 
-const FloatPolygon& PolygonShape::shapePaddingBounds() const
-{
-    ASSERT(shapePadding() >= 0);
-    if (!shapePadding() || m_polygon.isEmpty())
-        return m_polygon;
+    // Clip the edge line segment to the vertical range y1,y2 and then return
+    // the clipped line segment's horizontal range.
 
-    if (!m_paddingBounds)
-        m_paddingBounds = computeShapePaddingBounds(m_polygon, shapePadding(), m_polygon.fillRule());
-
-    return *m_paddingBounds;
-}
-
-const FloatPolygon& PolygonShape::shapeMarginBounds() const
-{
-    ASSERT(shapeMargin() >= 0);
-    if (!shapeMargin() || m_polygon.isEmpty())
-        return m_polygon;
-
-    if (!m_marginBounds)
-        m_marginBounds = computeShapeMarginBounds(m_polygon, shapeMargin(), m_polygon.fillRule());
-
-    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);
-
-    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;
-
-    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 (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);
-
-        ++index;
-    }
-}
+    if (y1 > center.y() + radius || y2 < center.y() - radius)
+        return FloatShapeInterval();
 
-static bool compareX1(const FloatShapeInterval a, const FloatShapeInterval& b) { return a.x1() < b.x1(); }
+    if (center.y() >= y1 && center.y() <= y2)
+        return FloatShapeInterval(center.x() - radius, center.x() + radius);
 
-static void sortAndMergeShapeIntervals(FloatShapeIntervals& intervals)
-{
-    std::sort(intervals.begin(), intervals.end(), compareX1);
+    // Clip the circle to the vertical range y1,y2 and return the extent of the clipped circle's
+    // projection on the X axis
 
-    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;
-        }
-    }
+    float xi =  circleXIntercept((y2 < center.y() ? y2 : y1) - center.y(), radius);
+    return FloatShapeInterval(center.x() - xi, center.x() + xi);
 }
 
-static void computeOverlappingEdgeXProjections(const FloatPolygon& polygon, float y1, float y2, FloatShapeIntervals& result)
+LayoutRect PolygonShape::shapeMarginLogicalBoundingBox() const
 {
-    Vector<const FloatPolygonEdge*> edges;
-    if (!polygon.overlappingEdges(y1, y2, edges))
-        return;
-
-    EdgeIntersection intersection;
-    for (unsigned i = 0; i < edges.size(); ++i) {
-        const FloatPolygonEdge *edge = edges[i];
-        float x1;
-        float x2;
-
-        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();
-        }
-
-        if (edge->maxY() > y2) {
-            computeXIntersection(edge, y2, intersection);
-            x2 = intersection.point.x();
-        } else {
-            x2 = (edge->vertex1().y() > edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
-        }
-
-        if (x1 > x2)
-            std::swap(x1, x2);
-
-        if (x2 > x1)
-            result.append(FloatShapeInterval(x1, x2));
-    }
-
-    sortAndMergeShapeIntervals(result);
+    FloatRect box = m_polygon.boundingBox();
+    box.inflate(shapeMargin());
+    return LayoutRect(box);
 }
 
 void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
 {
-    const FloatPolygon& polygon = shapeMarginBounds();
-    if (polygon.isEmpty())
-        return;
-
     float y1 = logicalTop.toFloat();
-    float y2 = (logicalTop + logicalHeight).toFloat();
-
-    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()));
-    }
-}
+    float y2 = logicalTop.toFloat() + logicalHeight.toFloat();
 
-void PolygonShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
-{
-    const FloatPolygon& polygon = shapePaddingBounds();
-    if (polygon.isEmpty())
+    if (m_polygon.isEmpty() || !overlapsYRange(m_polygon.boundingBox(), y1 - shapeMargin(), y2 + shapeMargin()))
         return;
 
-    float y1 = logicalTop.toFloat();
-    float y2 = (logicalTop + logicalHeight).toFloat();
-
-    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 FloatSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
-    float minIntervalTop = minLogicalIntervalTop.toFloat();
-    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;
+    Vector<const FloatPolygonEdge*> overlappingEdges;
+    if (!m_polygon.overlappingEdges(y1 - shapeMargin(), y2 + shapeMargin(), overlappingEdges))
+        return;
 
-        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)));
+    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 {
-            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]);
+            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));
         }
     }
 
-    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 (!excludedInterval.isEmpty())
+        result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2()));
+}
 
-    if (firstFitFound)
-        result = LayoutUnit::fromFloatCeil(firstFitRect.y());
-    return firstFitFound;
+void PolygonShape::buildDisplayPaths(DisplayPaths& paths) const
+{
+    if (!m_polygon.numberOfVertices())
+        return;
+    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