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)); }
void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { if (m_marginBounds.isEmpty()) return; float y1 = logicalTop; float y2 = logicalTop + logicalHeight; const FloatRect& rect = m_marginBounds.rect(); if (y2 <= rect.y() || y1 >= rect.maxY()) return; if (!m_marginBounds.isRounded()) { result.append(LineSegment(m_marginBounds.rect().x(), m_marginBounds.rect().maxX())); return; } float x1 = rect.maxX(); float x2 = rect.x(); float minXIntercept; float maxXIntercept; if (m_marginBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) { x1 = std::min<float>(x1, minXIntercept); x2 = std::max<float>(x2, maxXIntercept); } if (m_marginBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) { x1 = std::min<float>(x1, minXIntercept); x2 = std::max<float>(x2, maxXIntercept); } ASSERT(x2 >= x1); result.append(LineSegment(x1, x2)); }
void ExclusionPolygon::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const { const FloatPolygon& polygon = shapeMarginBounds(); if (polygon.isEmpty()) return; float y1 = logicalTop; float y2 = y1 + logicalHeight; Vector<ExclusionInterval> y1XIntervals, y2XIntervals; computeXIntersections(polygon, y1, true, y1XIntervals); computeXIntersections(polygon, y2, false, y2XIntervals); Vector<ExclusionInterval> mergedIntervals; mergeExclusionIntervals(y1XIntervals, y2XIntervals, mergedIntervals); Vector<ExclusionInterval> edgeIntervals; computeOverlappingEdgeXProjections(polygon, 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 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())); } }
void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { const FloatPolygon& polygon = shapeMarginBounds(); 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 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) { FloatShapeInterval 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)); } }
void RectangleShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { const FloatRoundedRect& bounds = shapeMarginBounds(); if (bounds.isEmpty()) return; float y1 = logicalTop; float y2 = logicalTop + logicalHeight; if (y2 < bounds.y() || y1 >= bounds.maxY()) return; float x1 = bounds.x(); float x2 = bounds.maxX(); if (bounds.ry() > 0) { if (y2 < bounds.y() + bounds.ry()) { float yi = y2 - bounds.y() - bounds.ry(); float xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry()); x1 = bounds.x() + bounds.rx() - xi; x2 = bounds.maxX() - bounds.rx() + xi; } else if (y1 > bounds.maxY() - bounds.ry()) { float yi = y1 - (bounds.maxY() - bounds.ry()); float xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry()); x1 = bounds.x() + bounds.rx() - xi; x2 = bounds.maxX() - bounds.rx() + xi; } } result.append(LineSegment(x1, x2)); }
void ExclusionRectangle::getExcludedIntervals(float logicalTop, float logicalBottom, SegmentList& result) const { float y1 = minYForLogicalLine(logicalTop, logicalBottom); float y2 = maxYForLogicalLine(logicalTop, logicalBottom); if (y2 < m_y || y1 >= m_y + m_height) return; float x1 = m_x; float x2 = m_x + m_width; if (m_ry > 0) { if (y2 < m_y + m_ry) { float yi = y2 - m_y - m_ry; float xi = ellipseXIntercept(yi, m_rx, m_ry); x1 = m_x + m_rx - xi; x2 = m_x + m_width - m_rx + xi; } else if (y1 > m_y + m_height - m_ry) { float yi = y1 - (m_y + m_height - m_ry); float xi = ellipseXIntercept(yi, m_rx, m_ry); x1 = m_x + m_rx - xi; x2 = m_x + m_width - m_rx + xi; } } result.append(LineSegment(x1, x2)); }
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)); } }
void PolygonShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { float y1 = logicalTop; float y2 = logicalTop + logicalHeight; if (m_polygon.isEmpty() || !m_polygon.boundingBox().overlapsYRange(y1 - shapeMargin(), y2 + shapeMargin())) return; Vector<const FloatPolygonEdge*> overlappingEdges; if (!m_polygon.overlappingEdges(y1 - shapeMargin(), y2 + shapeMargin(), overlappingEdges)) return; FloatShapeInterval excludedInterval; for (unsigned i = 0; i < overlappingEdges.size(); i++) { const FloatPolygonEdge& edge = *(overlappingEdges[i]); if (!shapeMargin()) excludedInterval.unite(OffsetPolygonEdge(edge, FloatSize()).clippedEdgeXRange(y1, y2)); else { 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)); } } if (!excludedInterval.isEmpty()) result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2())); }
void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { const FloatRoundedRect& marginBounds = shapeMarginBounds(); if (marginBounds.isEmpty() || !lineOverlapsShapeMarginBounds(logicalTop, logicalHeight)) return; float y1 = logicalTop; float y2 = logicalTop + logicalHeight; const FloatRect& rect = marginBounds.rect(); if (!marginBounds.isRounded()) { result.append(LineSegment(rect.x(), rect.maxX())); return; } float topCornerMaxY = std::max<float>(marginBounds.topLeftCorner().maxY(), marginBounds.topRightCorner().maxY()); float bottomCornerMinY = std::min<float>(marginBounds.bottomLeftCorner().y(), marginBounds.bottomRightCorner().y()); if (y1 <= topCornerMaxY && y2 >= bottomCornerMinY) { result.append(LineSegment(rect.x(), rect.maxX())); return; } float x1 = rect.maxX(); float x2 = rect.x(); float minXIntercept; float maxXIntercept; if (marginBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) { x1 = std::min<float>(x1, minXIntercept); x2 = std::max<float>(x2, maxXIntercept); } if (marginBounds.xInterceptsAtY(y2, minXIntercept, maxXIntercept)) { x1 = std::min<float>(x1, minXIntercept); x2 = std::max<float>(x2, maxXIntercept); } ASSERT(x2 >= x1); result.append(LineSegment(x1, x2)); }
void BoxShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { if (m_paddingBounds.isEmpty()) return; const FloatRect& rect = m_paddingBounds.rect(); if (logicalTop < rect.y() || logicalTop + logicalHeight > rect.maxY()) return; // FIXME: this method is only a stub, https://bugs.webkit.org/show_bug.cgi?id=124605. result.append(LineSegment(rect.x(), rect.maxX())); }
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)); }
void RasterShapeIntervals::getIncludedIntervals(int y1, int y2, SegmentList& result) const { ASSERT(y2 >= y1); IntRect lineRect(bounds().x(), y1, bounds().width(), y2 - y1); Region lineRegion(lineRect); lineRegion.intersect(m_region); if (lineRegion.isEmpty()) return; const Vector<IntRect>& lineRects = lineRegion.rects(); ASSERT(lineRects.size() > 0); Region segmentsRegion(lineRect); Region intervalsRegion; // The loop below uses Regions to compute the intersection of the horizontal // shape intervals that fall within the line's box. int currentLineY = lineRects[0].y(); int currentLineMaxY = lineRects[0].maxY(); for (unsigned i = 0; i < lineRects.size(); ++i) { int lineY = lineRects[i].y(); ASSERT(lineY >= currentLineY); if (lineY > currentLineMaxY) { // We've encountered a vertical gap in lineRects, there are no included intervals. return; } if (lineY > currentLineY) { currentLineY = lineY; currentLineMaxY = lineRects[i].maxY(); segmentsRegion.intersect(intervalsRegion); intervalsRegion = Region(); } else currentLineMaxY = std::max<int>(currentLineMaxY, lineRects[i].maxY()); intervalsRegion.unite(Region(alignedRect(lineRects[i], y1, y2))); } if (!intervalsRegion.isEmpty()) segmentsRegion.intersect(intervalsRegion); const Vector<IntRect>& segmentRects = segmentsRegion.rects(); for (unsigned i = 0; i < segmentRects.size(); ++i) result.append(LineSegment(segmentRects[i].x(), segmentRects[i].maxX())); }
void RasterShapeIntervals::getExcludedIntervals(int y1, int y2, SegmentList& result) const { ASSERT(y2 >= y1); IntRect lineRect(bounds().x(), y1, bounds().width(), y2 - y1); Region lineRegion(lineRect); lineRegion.intersect(m_region); if (lineRegion.isEmpty()) return; const Vector<IntRect>& lineRects = lineRegion.rects(); ASSERT(lineRects.size() > 0); Region segmentsRegion; for (unsigned i = 0; i < lineRects.size(); i++) segmentsRegion.unite(Region(alignedRect(lineRects[i], y1, y2))); const Vector<IntRect>& segmentRects = segmentsRegion.rects(); for (unsigned i = 0; i < segmentRects.size(); i++) result.append(LineSegment(segmentRects[i].x(), segmentRects[i].maxX() + 1)); }
void ExclusionRectangle::getIncludedIntervals(float logicalTop, float logicalBottom, SegmentList& result) const { float y1 = minYForLogicalLine(logicalTop, logicalBottom); float y2 = maxYForLogicalLine(logicalTop, logicalBottom); if (y1 < m_y || y2 > m_y + m_height) return; float x1 = m_x; float x2 = m_x + m_width; if (m_ry > 0) { bool y1InterceptsCorner = y1 < m_y + m_ry; bool y2InterceptsCorner = y2 > m_y + m_height - m_ry; float xi = 0; if (y1InterceptsCorner && y2InterceptsCorner) { if (y1 < m_height + 2*m_y - y2) { float yi = y1 - m_y - m_ry; xi = ellipseXIntercept(yi, m_rx, m_ry); } else { float yi = y2 - (m_y + m_height - m_ry); xi = ellipseXIntercept(yi, m_rx, m_ry); } } else if (y1InterceptsCorner) { float yi = y1 - m_y - m_ry; xi = ellipseXIntercept(yi, m_rx, m_ry); } else if (y2InterceptsCorner) { float yi = y2 - (m_y + m_height - m_ry); xi = ellipseXIntercept(yi, m_rx, m_ry); } if (y1InterceptsCorner || y2InterceptsCorner) { x1 = m_x + m_rx - xi; x2 = m_x + m_width - m_rx + xi; } } result.append(LineSegment(x1, x2)); }
void RasterShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const { const RasterShapeIntervals& intervals = marginIntervals(); if (intervals.isEmpty()) return; int y1 = logicalTop; int y2 = logicalTop + logicalHeight; ASSERT(y2 >= y1); if (y2 < intervals.bounds().y() || y1 >= intervals.bounds().maxY()) return; y1 = std::max(y1, intervals.bounds().y()); y2 = std::min(y2, intervals.bounds().maxY()); IntShapeInterval excludedInterval; for (int y = y1; y < y2; y++) excludedInterval.unite(intervals.intervalAt(y)); // Note: |marginIntervals()| returns end-point exclusive // intervals. |excludedInterval.x2()| contains the left-most pixel // offset to the right of the calculated union. result.append(LineSegment(excludedInterval.x1(), excludedInterval.x2())); }
static inline void appendLineSegments(const IntShapeIntervals& intervals, SegmentList& result) { for (unsigned i = 0; i < intervals.size(); i++) result.append(LineSegment(intervals[i].x1(), intervals[i].x2() + 1)); }