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; }
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 = ceiledLayoutUnit(firstFitRect.y()); return firstFitFound; }