diff options
| author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
| commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
| tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/ExclusionPolygon.cpp | |
| parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
| download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz | |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/rendering/ExclusionPolygon.cpp')
| -rw-r--r-- | Source/WebCore/rendering/ExclusionPolygon.cpp | 379 |
1 files changed, 0 insertions, 379 deletions
diff --git a/Source/WebCore/rendering/ExclusionPolygon.cpp b/Source/WebCore/rendering/ExclusionPolygon.cpp deleted file mode 100644 index 21beac1ec..000000000 --- a/Source/WebCore/rendering/ExclusionPolygon.cpp +++ /dev/null @@ -1,379 +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 HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ExclusionPolygon.h" - -#include <wtf/MathExtras.h> - -namespace WebCore { - -enum EdgeIntersectionType { - Normal, - VertexMinY, - VertexMaxY, - VertexYBoth -}; - -struct EdgeIntersection { - const ExclusionPolygonEdge* edge; - FloatPoint point; - EdgeIntersectionType type; -}; - -static inline float determinant(const FloatSize& a, const FloatSize& b) -{ - return a.width() * b.height() - a.height() * b.width(); -} - -static inline bool areCollinearPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2) -{ - return !determinant(p1 - p0, p2 - p0); -} - -static inline bool areCoincidentPoints(const FloatPoint& p0, const FloatPoint& p1) -{ - return p0.x() == p1.x() && p0.y() == p1.y(); -} - -static inline unsigned nextVertexIndex(unsigned vertexIndex, unsigned nVertices, bool clockwise) -{ - return ((clockwise) ? vertexIndex + 1 : vertexIndex - 1 + nVertices) % nVertices; -} - -unsigned ExclusionPolygon::findNextEdgeVertexIndex(unsigned vertexIndex1, bool clockwise) const -{ - unsigned nVertices = numberOfVertices(); - unsigned vertexIndex2 = nextVertexIndex(vertexIndex1, nVertices, clockwise); - - while (vertexIndex2 && areCoincidentPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2))) - vertexIndex2 = nextVertexIndex(vertexIndex2, nVertices, clockwise); - - while (vertexIndex2) { - unsigned vertexIndex3 = nextVertexIndex(vertexIndex2, nVertices, clockwise); - if (!areCollinearPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2), vertexAt(vertexIndex3))) - break; - vertexIndex2 = vertexIndex3; - } - - return vertexIndex2; -} - -ExclusionPolygon::ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule) - : ExclusionShape() - , m_vertices(vertices) - , m_fillRule(fillRule) -{ - unsigned nVertices = numberOfVertices(); - m_edges.resize(nVertices); - m_empty = nVertices < 3; - - if (nVertices) - m_boundingBox.setLocation(vertexAt(0)); - - if (m_empty) - return; - - unsigned minVertexIndex = 0; - for (unsigned i = 1; i < nVertices; ++i) { - const FloatPoint& vertex = vertexAt(i); - if (vertex.y() < vertexAt(minVertexIndex).y() || (vertex.y() == vertexAt(minVertexIndex).y() && vertex.x() < vertexAt(minVertexIndex).x())) - minVertexIndex = i; - } - FloatPoint nextVertex = vertexAt((minVertexIndex + 1) % nVertices); - FloatPoint prevVertex = vertexAt((minVertexIndex + nVertices - 1) % nVertices); - bool clockwise = determinant(vertexAt(minVertexIndex) - prevVertex, nextVertex - prevVertex) > 0; - - unsigned edgeIndex = 0; - unsigned vertexIndex1 = 0; - do { - m_boundingBox.extend(vertexAt(vertexIndex1)); - unsigned vertexIndex2 = findNextEdgeVertexIndex(vertexIndex1, clockwise); - m_edges[edgeIndex].polygon = this; - m_edges[edgeIndex].vertexIndex1 = vertexIndex1; - m_edges[edgeIndex].vertexIndex2 = vertexIndex2; - m_edges[edgeIndex].edgeIndex = edgeIndex; - edgeIndex++; - vertexIndex1 = vertexIndex2; - } while (vertexIndex1); - - if (edgeIndex > 3) { - const ExclusionPolygonEdge& firstEdge = m_edges[0]; - const ExclusionPolygonEdge& lastEdge = m_edges[edgeIndex - 1]; - if (areCollinearPoints(lastEdge.vertex1(), lastEdge.vertex2(), firstEdge.vertex2())) { - m_edges[0].vertexIndex1 = lastEdge.vertexIndex1; - edgeIndex--; - } - } - - m_edges.resize(edgeIndex); - m_empty = m_edges.size() < 3; - - if (m_empty) - return; - - for (unsigned i = 0; i < m_edges.size(); i++) { - ExclusionPolygonEdge* edge = &m_edges[i]; - m_edgeTree.add(EdgeInterval(edge->minY(), edge->maxY(), edge)); - } -} - -static bool computeXIntersection(const ExclusionPolygonEdge* edgePointer, float y, EdgeIntersection& result) -{ - const ExclusionPolygonEdge& 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 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 ExclusionPolygon& polygon = *(intersection.edge->polygon); - const ExclusionPolygonEdge& 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); - } else { - prevVertex = polygon.vertexAt(thisEdge.vertexIndex1); - thisVertex = polygon.vertexAt(thisEdge.vertexIndex2); - nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex2); - } - - return true; -} - -static inline bool appendIntervalX(float x, bool inside, Vector<ExclusionInterval>& result) -{ - if (!inside) - result.append(ExclusionInterval(x)); - else - result[result.size() - 1].x2 = x; - - return !inside; -} - -static bool compareEdgeIntersectionX(const EdgeIntersection& intersection1, const EdgeIntersection& intersection2) -{ - float x1 = intersection1.point.x(); - float x2 = intersection2.point.x(); - return (x1 == x2) ? intersection1.type < intersection2.type : x1 < x2; -} - -void ExclusionPolygon::computeXIntersections(float y, bool isMinY, Vector<ExclusionInterval>& result) const -{ - Vector<ExclusionPolygon::EdgeInterval> overlappingEdges; - m_edgeTree.allOverlaps(ExclusionPolygon::EdgeInterval(y, y, 0), overlappingEdges); - - Vector<EdgeIntersection> intersections; - EdgeIntersection intersection; - for (unsigned i = 0; i < overlappingEdges.size(); i++) { - ExclusionPolygonEdge* edge = static_cast<ExclusionPolygonEdge*>(overlappingEdges[i].data()); - if (computeXIntersection(edge, 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; - } - } - - const ExclusionPolygonEdge& thisEdge = *thisIntersection.edge; - bool evenOddCrossing = !windCount; - - if (fillRule() == RULE_EVENODD) { - windCount += (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? 1 : -1; - evenOddCrossing = evenOddCrossing || !windCount; - } - - if (evenOddCrossing) { - 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) - inside = appendIntervalX(thisIntersection.point.x(), inside, result); - } - - index++; - } -} - -// Return the X projections of the edges that overlap y1,y2. -void ExclusionPolygon::computeEdgeIntersections(float y1, float y2, Vector<ExclusionInterval>& result) const -{ - Vector<ExclusionPolygon::EdgeInterval> overlappingEdges; - m_edgeTree.allOverlaps(ExclusionPolygon::EdgeInterval(y1, y2, 0), overlappingEdges); - - EdgeIntersection intersection; - for (unsigned i = 0; i < overlappingEdges.size(); i++) { - const ExclusionPolygonEdge *edge = static_cast<ExclusionPolygonEdge*>(overlappingEdges[i].data()); - 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(ExclusionInterval(x1, x2)); - } - - sortExclusionIntervals(result); -} - -void ExclusionPolygon::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const -{ - if (isEmpty()) - return; - - float y1 = minYForLogicalLine(logicalTop, logicalHeight); - float y2 = maxYForLogicalLine(logicalTop, logicalHeight); - - Vector<ExclusionInterval> y1XIntervals, y2XIntervals; - computeXIntersections(y1, true, y1XIntervals); - computeXIntersections(y2, false, y2XIntervals); - - Vector<ExclusionInterval> mergedIntervals; - mergeExclusionIntervals(y1XIntervals, y2XIntervals, mergedIntervals); - - Vector<ExclusionInterval> edgeIntervals; - computeEdgeIntersections(y1, y2, edgeIntervals); - - Vector<ExclusionInterval> excludedIntervals; - mergeExclusionIntervals(mergedIntervals, edgeIntervals, excludedIntervals); - - for (unsigned i = 0; i < excludedIntervals.size(); i++) { - ExclusionInterval interval = excludedIntervals[i]; - result.append(LineSegment(interval.x1, interval.x2)); - } -} - -void ExclusionPolygon::getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const -{ - if (isEmpty()) - return; - - float y1 = minYForLogicalLine(logicalTop, logicalHeight); - float y2 = maxYForLogicalLine(logicalTop, logicalHeight); - - Vector<ExclusionInterval> y1XIntervals, y2XIntervals; - computeXIntersections(y1, true, y1XIntervals); - computeXIntersections(y2, false, y2XIntervals); - - Vector<ExclusionInterval> commonIntervals; - intersectExclusionIntervals(y1XIntervals, y2XIntervals, commonIntervals); - - Vector<ExclusionInterval> edgeIntervals; - computeEdgeIntersections(y1, y2, edgeIntervals); - - Vector<ExclusionInterval> includedIntervals; - subtractExclusionIntervals(commonIntervals, edgeIntervals, includedIntervals); - - for (unsigned i = 0; i < includedIntervals.size(); i++) { - ExclusionInterval interval = includedIntervals[i]; - result.append(LineSegment(interval.x1, interval.x2)); - } -} - -} // namespace WebCore |
