#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);
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;
}
}
#endif // Region_h