#ifndef Region_h
#define Region_h
#include "platform/PlatformExport.h"
#include "platform/geometry/IntRect.h"
#include "wtf/Vector.h"
namespace WebCore {
class PLATFORM_EXPORT Region {
public:
Region();
Region(const IntRect&);
IntRect bounds() const { return m_bounds; }
bool isEmpty() const { return m_bounds.isEmpty(); }
bool isRect() const { return m_shape.isRect(); }
Vector<IntRect> rects() const;
void unite(const Region&);
void intersect(const Region&);
void subtract(const Region&);
void translate(const IntSize&);
bool contains(const Region&) const;
bool contains(const IntPoint&) const;
bool intersects(const Region&) const;
unsigned totalArea() const;
#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 IntRect&);
IntRect bounds() const;
bool isEmpty() const { return m_spans.isEmpty(); }
bool isRect() const { return m_spans.size() <= 2 && m_segments.size() <= 2; }
typedef const Span* SpanIterator;
SpanIterator spansBegin() const;
SpanIterator spansEnd() const;
typedef const int* SegmentIterator;
SegmentIterator segmentsBegin(SpanIterator) const;
SegmentIterator segmentsEnd(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 IntSize&);
void swap(Shape&);
struct CompareContainsOperation;
struct CompareIntersectsOperation;
template<typename CompareOperation>
static bool compareShapes(const Shape& shape1, const Shape& shape2);
#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, 32> m_segments;
Vector<Span, 16> m_spans;
friend bool operator==(const Shape&, const Shape&);
};
IntRect m_bounds;
Shape m_shape;
friend bool operator==(const Region&, const Region&);
friend bool operator==(const Shape&, const Shape&);
friend bool operator==(const Span&, const Span&);
};
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 IntSize& offset)
{
Region result(region);
result.translate(offset);
return result;
}
inline bool operator==(const Region& a, const Region& b)
{
return a.m_bounds == b.m_bounds && a.m_shape == b.m_shape;
}
inline bool operator==(const Region::Shape& a, const Region::Shape& b)
{
return a.m_spans == b.m_spans && a.m_segments == b.m_segments;
}
inline bool operator==(const Region::Span& a, const Region::Span& b)
{
return a.y == b.y && a.segmentIndex == b.segmentIndex;
}
}
#endif