Пример #1
0
void ExclusionPolygon::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
    const FloatPolygon& polygon = shapePaddingBounds();
    if (polygon.isEmpty())
        return;

    float y1 = logicalTop;
    float y2 = logicalTop + logicalHeight;

    Vector<ExclusionInterval> y1XIntervals, y2XIntervals;
    computeXIntersections(polygon, y1, true, y1XIntervals);
    computeXIntersections(polygon, y2, false, y2XIntervals);

    Vector<ExclusionInterval> commonIntervals;
    intersectExclusionIntervals(y1XIntervals, y2XIntervals, commonIntervals);

    Vector<ExclusionInterval> edgeIntervals;
    computeOverlappingEdgeXProjections(polygon, 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));
    }
}
Пример #2
0
void PolygonShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
    const FloatPolygon& polygon = shapePaddingBounds();
    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 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()));
    }
}
Пример #3
0
void BoxShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
    const FloatRoundedRect& paddingBounds = shapePaddingBounds();
    if (paddingBounds.isEmpty())
        return;

    const FloatRect& rect = paddingBounds.rect();
    float y1 = logicalTop;
    float y2 = logicalTop + logicalHeight;

    if (y1 < rect.y() || y2 > rect.maxY())
        return;

    if (!paddingBounds.isRounded()) {
        result.append(LineSegment(rect.x(), rect.maxX()));
        return;
    }

    float x1 = rect.x();
    float x2 = rect.maxX();
    float minXIntercept;
    float maxXIntercept;

    if (paddingBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) {
        x1 = std::max<float>(x1, minXIntercept);
        x2 = std::min<float>(x2, maxXIntercept);
    }

    if (paddingBounds.xInterceptsAtY(y2, minXIntercept, maxXIntercept)) {
        x1 = std::max<float>(x1, minXIntercept);
        x2 = std::min<float>(x2, maxXIntercept);
    }

    result.append(LineSegment(x1, x2));
}
Пример #4
0
bool RectangleShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
{
    float minIntervalTop = minLogicalIntervalTop;
    float minIntervalHeight = minLogicalIntervalSize.height();
    float minIntervalWidth = minLogicalIntervalSize.width();

    const FloatRoundedRect& bounds = shapePaddingBounds();
    if (bounds.isEmpty() || minIntervalWidth > bounds.width())
        return false;

    float minY = std::max(bounds.y(), minIntervalTop);
    float maxY = minY + minIntervalHeight;

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

    bool intervalOverlapsMinCorner = minY < bounds.y() + bounds.ry();
    bool intervalOverlapsMaxCorner = maxY > bounds.maxY() - bounds.ry();

    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 * bounds.rx() <= bounds.width();
    FloatPoint cornerIntercept = bounds.cornerInterceptForWidth(minIntervalWidth);

    if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDefinesX)) {
        if (intervalFitsWithinCorners || bounds.y() + cornerIntercept.y() < minY) {
            result = minY;
            return true;
        }
        if (minIntervalHeight < bounds.height() - (2 * cornerIntercept.y())) {
            result = ceiledLayoutUnit(bounds.y() + cornerIntercept.y());
            return true;
        }
    }

    if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDefinesX)) {
        if (intervalFitsWithinCorners || minY <=  bounds.maxY() - cornerIntercept.y() - minIntervalHeight) {
            result = minY;
            return true;
        }
    }

    return false;
}
Пример #5
0
void RectangleShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
{
    const FloatRoundedRect& 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();

    if (bounds.ry() > 0) {
        bool y1InterceptsCorner = y1 < bounds.y() + bounds.ry();
        bool y2InterceptsCorner = y2 > bounds.maxY() - bounds.ry();
        float xi = 0;

        if (y1InterceptsCorner && y2InterceptsCorner) {
            if  (y1 < bounds.height() + 2 * bounds.y() - y2) {
                float yi = y1 - bounds.y() - bounds.ry();
                xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
            } else {
                float yi =  y2 - (bounds.maxY() - bounds.ry());
                xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
            }
        } else if (y1InterceptsCorner) {
            float yi = y1 - bounds.y() - bounds.ry();
            xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
        } else if (y2InterceptsCorner) {
            float yi =  y2 - (bounds.maxY() - bounds.ry());
            xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
        }

        if (y1InterceptsCorner || y2InterceptsCorner) {
            x1 = bounds.x() + bounds.rx() - xi;
            x2 = bounds.maxX() - bounds.rx() + xi;
        }
    }

    result.append(LineSegment(x1, x2));
}
Пример #6
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;
}