Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / shapes / RasterShape.cpp
index b8f4b15..958ffab 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "wtf/MathExtras.h"
 
-namespace WebCore {
+namespace blink {
 
 class MarginIntervalGenerator {
 public:
@@ -70,185 +70,70 @@ IntShapeInterval MarginIntervalGenerator::intervalAt(int y) const
 {
     unsigned xInterceptsIndex = abs(y - m_y);
     int dx = (xInterceptsIndex >= m_xIntercepts.size()) ? 0 : m_xIntercepts[xInterceptsIndex];
-    return IntShapeInterval(std::max(0, m_x1 - dx), m_x2 + dx);
+    return IntShapeInterval(m_x1 - dx, m_x2 + dx);
 }
 
-void RasterShapeIntervals::appendInterval(int y, int x1, int x2)
+PassOwnPtr<RasterShapeIntervals> RasterShapeIntervals::computeShapeMarginIntervals(int shapeMargin) const
 {
-    ASSERT(y >= 0 && y < size() && x1 >= 0 && x2 > x1 && (m_intervalLists[y].isEmpty() || x1 > m_intervalLists[y].last().x2()));
+    int marginIntervalsSize = (offset() > shapeMargin) ? size() : size() - offset() * 2 + shapeMargin * 2;
+    OwnPtr<RasterShapeIntervals> result = adoptPtr(new RasterShapeIntervals(marginIntervalsSize, std::max(shapeMargin, offset())));
+    MarginIntervalGenerator marginIntervalGenerator(shapeMargin);
 
-    m_bounds.unite(IntRect(x1, y, x2 - x1, 1));
-    m_intervalLists[y].append(IntShapeInterval(x1, x2));
-}
-
-void RasterShapeIntervals::uniteMarginInterval(int y, const IntShapeInterval& interval)
-{
-    ASSERT(m_intervalLists[y].size() <= 1);
-
-    if (m_intervalLists[y].isEmpty()) {
-        m_intervalLists[y].append(interval);
-    } else {
-        IntShapeInterval& resultInterval = m_intervalLists[y][0];
-        resultInterval.set(std::min(resultInterval.x1(), interval.x1()), std::max(resultInterval.x2(), interval.x2()));
-    }
-
-    m_bounds.unite(IntRect(interval.x1(), y, interval.width(), 1));
-}
-
-static inline bool shapeIntervalsContain(const IntShapeIntervals& intervals, const IntShapeInterval& interval)
-{
-    for (unsigned i = 0; i < intervals.size(); i++) {
-        if (intervals[i].x1() > interval.x2())
-            return false;
-        if (intervals[i].contains(interval))
-            return true;
-    }
-
-    return false;
-}
-
-bool RasterShapeIntervals::contains(const IntRect& rect) const
-{
-    if (!bounds().contains(rect))
-        return false;
-
-    const IntShapeInterval& rectInterval = IntShapeInterval(rect.x(), rect.maxX());
-    for (int y = rect.y(); y < rect.maxY(); y++) {
-        if (!shapeIntervalsContain(intervalsAt(y), rectInterval))
-            return false;
-    }
-
-    return true;
-}
-
-static inline void appendX1Values(const IntShapeIntervals& intervals, int minIntervalWidth, Vector<int>& result)
-{
-    for (unsigned i = 0; i < intervals.size(); i++) {
-        if (intervals[i].width() >= minIntervalWidth)
-            result.append(intervals[i].x1());
-    }
-}
-
-bool RasterShapeIntervals::getIntervalX1Values(int y1, int y2, int minIntervalWidth, Vector<int>& result) const
-{
-    ASSERT(y1 >= 0 && y2 > y1);
-
-    for (int y = y1; y < y2;  y++) {
-        if (intervalsAt(y).isEmpty())
-            return false;
-    }
-
-    appendX1Values(intervalsAt(y1), minIntervalWidth, result);
-    for (int y = y1 + 1; y < y2;  y++) {
-        if (intervalsAt(y) != intervalsAt(y - 1))
-            appendX1Values(intervalsAt(y), minIntervalWidth, result);
-    }
-
-    return true;
-}
-
-bool RasterShapeIntervals::firstIncludedIntervalY(int minY, const IntSize& minSize, LayoutUnit& result) const
-{
-    minY = std::max<int>(bounds().y(), minY);
-
-    ASSERT(minY >= 0 && minY < size());
-
-    if (minSize.isEmpty() || minSize.width() > bounds().width())
-        return false;
-
-    for (int lineY = minY; lineY <= bounds().maxY() - minSize.height(); lineY++) {
-        Vector<int> intervalX1Values;
-        if (!getIntervalX1Values(lineY, lineY + minSize.height(), minSize.width(), intervalX1Values))
+    for (int y = bounds().y(); y < bounds().maxY(); ++y) {
+        const IntShapeInterval& intervalAtY = intervalAt(y);
+        if (intervalAtY.isEmpty())
             continue;
 
-        std::sort(intervalX1Values.begin(), intervalX1Values.end());
+        marginIntervalGenerator.set(y, intervalAtY);
+        int marginY0 = std::max(minY(), y - shapeMargin);
+        int marginY1 = std::min(maxY(), y + shapeMargin + 1);
 
-        IntRect firstFitRect(IntPoint(0, 0), minSize);
-        for (unsigned i = 0; i < intervalX1Values.size(); i++) {
-            int lineX = intervalX1Values[i];
-            if (i > 0 && lineX == intervalX1Values[i - 1])
-                continue;
-            firstFitRect.setLocation(IntPoint(lineX, lineY));
-            if (contains(firstFitRect)) {
-                result = lineY;
-                return true;
-            }
+        for (int marginY = y - 1; marginY >= marginY0; --marginY) {
+            if (marginY > bounds().y() && intervalAt(marginY).contains(intervalAtY))
+                break;
+            result->intervalAt(marginY).unite(marginIntervalGenerator.intervalAt(marginY));
         }
-    }
-
-    return false;
-}
 
-void RasterShapeIntervals::getIncludedIntervals(int y1, int y2, IntShapeIntervals& result) const
-{
-    ASSERT(y2 >= y1);
-
-    if (y1 < bounds().y() || y2 > bounds().maxY())
-        return;
+        result->intervalAt(y).unite(marginIntervalGenerator.intervalAt(y));
 
-    for (int y = y1; y < y2;  y++) {
-        if (intervalsAt(y).isEmpty())
-            return;
+        for (int marginY = y + 1; marginY < marginY1; ++marginY) {
+            if (marginY < bounds().maxY() && intervalAt(marginY).contains(intervalAtY))
+                break;
+            result->intervalAt(marginY).unite(marginIntervalGenerator.intervalAt(marginY));
+        }
     }
 
-    result = intervalsAt(y1);
-    for (int y = y1 + 1; y < y2 && !result.isEmpty();  y++) {
-        IntShapeIntervals intervals;
-        IntShapeInterval::intersectShapeIntervals(result, intervalsAt(y), intervals);
-        result.swap(intervals);
-    }
+    result->initializeBounds();
+    return result.release();
 }
 
-void RasterShapeIntervals::getExcludedIntervals(int y1, int y2, IntShapeIntervals& result) const
+void RasterShapeIntervals::initializeBounds()
 {
-    ASSERT(y2 >= y1);
-
-    if (y2 < bounds().y() || y1 >= bounds().maxY())
-        return;
-
-    for (int y = y1; y < y2;  y++) {
-        if (intervalsAt(y).isEmpty())
-            return;
-    }
-
-    result = intervalsAt(y1);
-    for (int y = y1 + 1; y < y2;  y++) {
-        IntShapeIntervals intervals;
-        IntShapeInterval::uniteShapeIntervals(result, intervalsAt(y), intervals);
-        result.swap(intervals);
+    m_bounds = IntRect();
+    for (int y = minY(); y < maxY(); ++y) {
+        const IntShapeInterval& intervalAtY = intervalAt(y);
+        if (intervalAtY.isEmpty())
+            continue;
+        m_bounds.unite(IntRect(intervalAtY.x1(), y, intervalAtY.width(), 1));
     }
 }
 
-PassOwnPtr<RasterShapeIntervals> RasterShapeIntervals::computeShapeMarginIntervals(unsigned margin) const
+void RasterShapeIntervals::buildBoundsPath(Path& path) const
 {
-    OwnPtr<RasterShapeIntervals> result = adoptPtr(new RasterShapeIntervals(size() + margin));
-    MarginIntervalGenerator marginIntervalGenerator(margin);
-
-    for (int y = bounds().y(); y < bounds().maxY(); ++y) {
-        const IntShapeInterval& intervalAtY = limitIntervalAt(y);
-        if (intervalAtY.isEmpty())
+    int maxY = bounds().maxY();
+    for (int y = bounds().y(); y < maxY; y++) {
+        if (intervalAt(y).isEmpty())
             continue;
 
-        marginIntervalGenerator.set(y, intervalAtY);
-        int marginY0 = std::max(0, clampToPositiveInteger(y - margin));
-        int marginY1 = std::min(result->size() - 1, clampToPositiveInteger(y + margin));
-
-        for (int marginY = y - 1; marginY >= marginY0; --marginY) {
-            if (limitIntervalAt(marginY).contains(intervalAtY))
-                break;
-            result->uniteMarginInterval(marginY, marginIntervalGenerator.intervalAt(marginY));
-        }
-
-        result->uniteMarginInterval(y, marginIntervalGenerator.intervalAt(y));
-
-        for (int marginY = y + 1; marginY <= marginY1; ++marginY) {
-            if (marginY < size() && limitIntervalAt(marginY).contains(intervalAtY))
+        IntShapeInterval extent = intervalAt(y);
+        int endY = y + 1;
+        for (; endY < maxY; endY++) {
+            if (intervalAt(endY).isEmpty() || intervalAt(endY) != extent)
                 break;
-            result->uniteMarginInterval(marginY, marginIntervalGenerator.intervalAt(marginY));
         }
+        path.addRect(FloatRect(extent.x1(), y, extent.width(), endY - y));
+        y = endY - 1;
     }
-
-    return result.release();
 }
 
 const RasterShapeIntervals& RasterShape::marginIntervals() const
@@ -257,58 +142,41 @@ const RasterShapeIntervals& RasterShape::marginIntervals() const
     if (!shapeMargin())
         return *m_intervals;
 
-    unsigned marginBoundaryRadius = std::min(clampToUnsigned(ceil(shapeMargin())), std::max<unsigned>(m_imageSize.width(), m_imageSize.height()));
+    int shapeMarginInt = clampToPositiveInteger(ceil(shapeMargin()));
+    int maxShapeMarginInt = std::max(m_marginRectSize.width(), m_marginRectSize.height()) * sqrtf(2);
     if (!m_marginIntervals)
-        m_marginIntervals = m_intervals->computeShapeMarginIntervals(marginBoundaryRadius);
+        m_marginIntervals = m_intervals->computeShapeMarginIntervals(std::min(shapeMarginInt, maxShapeMarginInt));
 
     return *m_marginIntervals;
 }
 
-const RasterShapeIntervals& RasterShape::paddingIntervals() const
-{
-    ASSERT(shapePadding() >= 0);
-    if (!shapePadding())
-        return *m_intervals;
-
-    // FIXME: Add support for non-zero padding, see https://bugs.webkit.org/show_bug.cgi?id=116348.
-    return *m_intervals;
-}
-
-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));
-}
-
-void RasterShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
+LineSegment RasterShape::getExcludedInterval(LayoutUnit logicalTop, LayoutUnit logicalHeight) const
 {
     const RasterShapeIntervals& intervals = marginIntervals();
     if (intervals.isEmpty())
-        return;
+        return LineSegment();
 
-    IntShapeIntervals excludedIntervals;
-    intervals.getExcludedIntervals(logicalTop, logicalTop + logicalHeight, excludedIntervals);
-    appendLineSegments(excludedIntervals, result);
-}
+    int y1 = logicalTop;
+    int y2 = logicalTop + logicalHeight;
+    ASSERT(y2 >= y1);
+    if (y2 < intervals.bounds().y() || y1 >= intervals.bounds().maxY())
+        return LineSegment();
 
-void RasterShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const
-{
-    const RasterShapeIntervals& intervals = paddingIntervals();
-    if (intervals.isEmpty())
-        return;
+    y1 = std::max(y1, intervals.bounds().y());
+    y2 = std::min(y2, intervals.bounds().maxY());
+    IntShapeInterval excludedInterval;
 
-    IntShapeIntervals includedIntervals;
-    intervals.getIncludedIntervals(logicalTop, logicalTop + logicalHeight, includedIntervals);
-    appendLineSegments(includedIntervals, result);
-}
-
-bool RasterShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const
-{
-    const RasterShapeIntervals& intervals = paddingIntervals();
-    if (intervals.isEmpty())
-        return false;
+    if (y1 == y2) {
+        excludedInterval = intervals.intervalAt(y1);
+    } else {
+        for (int y = y1; y < y2; y++)
+            excludedInterval.unite(intervals.intervalAt(y));
+    }
 
-    return intervals.firstIncludedIntervalY(minLogicalIntervalTop.floor(), flooredIntSize(minLogicalIntervalSize), result);
+    // Note: |marginIntervals()| returns end-point exclusive
+    // intervals. |excludedInterval.x2()| contains the left-most pixel
+    // offset to the right of the calculated union.
+    return LineSegment(excludedInterval.x1(), excludedInterval.x2());
 }
 
-} // namespace WebCore
+} // namespace blink