Example #1
0
bool ExclusionPolygon::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;
}
Example #2
0
bool ExclusionPolygon::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const
{
    if (minLogicalIntervalSize.width() > m_boundingBox.width())
        return false;

    float minY = std::max(m_boundingBox.y(), minLogicalIntervalTop);
    float maxY = minY + minLogicalIntervalSize.height();

    if (maxY > m_boundingBox.maxY())
        return false;

    Vector<ExclusionPolygon::EdgeInterval> overlappingEdges;
    m_edgeTree.allOverlaps(ExclusionPolygon::EdgeInterval(minLogicalIntervalTop, m_boundingBox.maxY(), 0), overlappingEdges);

    float dx = minLogicalIntervalSize.width() / 2;
    float dy = minLogicalIntervalSize.height() / 2;
    Vector<OffsetPolygonEdge> offsetEdges;

    for (unsigned i = 0; i < overlappingEdges.size(); ++i) {
        const ExclusionPolygonEdge& edge = *static_cast<ExclusionPolygonEdge*>(overlappingEdges[i].data());
        const FloatPoint& vertex1 = edge.vertex1();
        const FloatPoint& vertex2 = edge.vertex2();
        Vector<OffsetPolygonEdge> offsetEdgePair;

        if (vertex2.y() > vertex1.y() ? vertex2.x() >= vertex1.x() : vertex1.x() >= vertex2.x()) {
            offsetEdgePair.append(OffsetPolygonEdge(edge, FloatSize(dx, -dy)));
            offsetEdgePair.append(OffsetPolygonEdge(edge, FloatSize(-dx, dy)));
        } else {
            offsetEdgePair.append(OffsetPolygonEdge(edge, FloatSize(dx, dy)));
            offsetEdgePair.append(OffsetPolygonEdge(edge, FloatSize(-dx, -dy)));
        }

        for (unsigned j = 0; j < offsetEdgePair.size(); ++j)
            if (offsetEdgePair[j].maxY() >= minY)
                offsetEdges.append(offsetEdgePair[j]);
    }

    offsetEdges.append(OffsetPolygonEdge(*this, minLogicalIntervalTop, 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 ((potentialFirstFitLocation.y() >= minLogicalIntervalTop)
                    && (!firstFitFound || aboveOrToTheLeft(potentialFirstFitRect, firstFitRect))
                    && contains(offsetEdgesIntersection)
                    && firstFitRectInPolygon(potentialFirstFitRect, offsetEdges[i].edgeIndex(), offsetEdges[j].edgeIndex())) {
                    firstFitFound = true;
                    firstFitRect = potentialFirstFitRect;
                }
            }
        }
    }

    if (firstFitFound)
        result = firstFitRect.y();
    return firstFitFound;
}