Blob Blame Raw
#ifndef SURFACE_H
#define SURFACE_H


#include <cassert>
#include <cstddef>

#include "common.h"


class Surface: public Shared {
protected:
	int m_width;
	int m_height;
	int m_pitch;
	Color *m_origin;
	
	Surface();
	Surface(const Surface &);
	Surface& operator= (const Surface &) { return *this; }
	void reset();

public:
	virtual ~Surface() { }
	
	inline int width() const { return m_width; }
	inline int height() const { return m_height; }
	inline int pitch() const { return m_pitch; }
	inline int count() const { return m_width*m_height; }
	inline bool empty() const { return !count(); }
	
	inline Color* origin() { return m_origin; }
	inline const Color* origin() const { return m_origin; }

	inline int data_count()   const { return data_count  (width(), height(), pitch()); }
	inline size_t data_size() const { return data_size   (width(), height(), pitch()); }
	inline int begin_offset() const { return begin_offset(width(), height(), pitch()); }
	inline int end_offset()   const { return end_offset  (width(), height(), pitch()); }
	
	inline Color* data_begin() { return m_origin ? m_origin + begin_offset() : NULL; }
	inline const Color* data_begin() const { return m_origin ? m_origin + begin_offset() : NULL; }
	inline Color* data_end() { return m_origin ? m_origin + end_offset() : NULL; }
	inline const Color* data_end() const { return m_origin ? m_origin + end_offset() : NULL; }
	
	inline Color* row(int index)
		{ assert(index >= 0 && index < m_height); return m_origin + index*m_pitch; }
	inline const Color* row(int index) const
		{ assert(index >= 0 && index < m_height); return m_origin + index*m_pitch; }
	
	inline Color* operator[] (int index) { return row(index); }
	inline const Color* operator[] (int index) const { return row(index); }

	static inline int data_count(int width, int height, int pitch)
		{ return width + abs(pitch)*(height - 1); }
	static inline size_t data_size(int width, int height, int pitch)
		{ return data_count(width, height, pitch)*sizeof(Color); }
	static inline int begin_offset(int width, int height, int pitch)
		{ return pitch > 0 ? 0 : width - data_count(width, height, pitch); }
	static inline int end_offset(int width, int height, int pitch)
		{ return pitch > 0 ? data_count(width, height, pitch) : width; }

	static void copy(int width, int height, const Color *src_origin, Color *dest_origin, int src_pitch = 0, int dest_pitch = 0);
};


class DataSurface: public Surface {
public:
	explicit DataSurface(int width = 0, int height = 0, int pitch = 0, const Color *src_origin = NULL, int src_pitch = 0)
		{ init(width, height, pitch, src_origin, src_pitch); }
	DataSurface(const Surface &other)
		{ *this = other; }
	~DataSurface()
		{ clear(); }
	DataSurface& operator= (const Surface &other)
		{ init(other); return *this; }
	
	void clear();
	void init(int width, int height, int pitch = 0, const Color *src_origin = NULL, int src_pitch = 0);
	inline void init(const Surface &other)
		{ init(other.width(), other.height(), other.pitch(), other.origin(), other.pitch()); }
};


class AliasSurface: public Surface {
public:
	AliasSurface() { }
	AliasSurface(Color *origin, int width, int height, int pitch = 0)
		{ init(origin, width, height, pitch); }
	AliasSurface(const AliasSurface &other)
		{ *this = other; }
	AliasSurface(Surface &other)
		{ init(other); }
	AliasSurface& operator= (const AliasSurface &other)
		{ init(other); return *this; }
	
	inline Color* origin() const { return m_origin; }
	
	void init(Color *origin, int width, int height, int pitch = 0);

	inline void clear() { reset(); }
	inline void init(Surface &other)
		{ init(other.origin(), other.width(), other.height(), other.pitch()); }
	inline void init(const AliasSurface &other)
		{ init(other.origin(), other.width(), other.height(), other.pitch()); }
};


#endif