/* * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Region_h #define Region_h #include <WebCore/IntRect.h> #include <wtf/Vector.h> #include <vector> namespace WebKit { class Region { public: Region(); Region(const WebCore::IntRect&); WebCore::IntRect bounds() const { return m_bounds; } bool isEmpty() const { return m_bounds.isEmpty(); } Vector<WebCore::IntRect> rects() const; void unite(const Region&); void intersect(const Region&); void subtract(const Region&); void translate(const WebCore::IntSize&); #ifndef NDEBUG void dump() const; #endif private: struct Span { Span(int y, size_t segmentIndex) : y(y), segmentIndex(segmentIndex) { } int y; size_t segmentIndex; }; class Shape { public: Shape(); Shape(const WebCore::IntRect&); WebCore::IntRect bounds() const; bool isEmpty() const { return m_spans.isEmpty(); } typedef const Span* SpanIterator; SpanIterator spans_begin() const; SpanIterator spans_end() const; typedef const int* SegmentIterator; SegmentIterator segments_begin(SpanIterator) const; SegmentIterator segments_end(SpanIterator) const; static Shape unionShapes(const Shape& shape1, const Shape& shape2); static Shape intersectShapes(const Shape& shape1, const Shape& shape2); static Shape subtractShapes(const Shape& shape1, const Shape& shape2); void translate(const WebCore::IntSize&); void swap(Shape&); #ifndef NDEBUG void dump() const; #endif private: struct UnionOperation; struct IntersectOperation; struct SubtractOperation; template<typename Operation> static Shape shapeOperation(const Shape& shape1, const Shape& shape2); void appendSegment(int x); void appendSpan(int y); void appendSpan(int y, SegmentIterator begin, SegmentIterator end); void appendSpans(const Shape&, SpanIterator begin, SpanIterator end); bool canCoalesce(SegmentIterator begin, SegmentIterator end); // FIXME: These vectors should have inline sizes. Figure out a good optimal value. Vector<int> m_segments; Vector<Span> m_spans; }; WebCore::IntRect m_bounds; Shape m_shape; }; static inline Region intersect(const Region& a, const Region& b) { Region result(a); result.intersect(b); return result; } static inline Region subtract(const Region& a, const Region& b) { Region result(a); result.subtract(b); return result; } static inline Region translate(const Region& region, const WebCore::IntSize& offset) { Region result(region); result.translate(offset); return result; } } // namespace WebKit #endif // Region_h