[ create a new paste ] login | about

Link: http://codepad.org/NmNA0mx3    [ raw code | output | fork ]

C++, pasted on Jan 24:
//
// 誰が得するのかわからない "キャラクタ・グラフィック・ライブラリ"
//                                           + どこかで見たようなOS風 by ミングスレの名無し
//
// 名称: vip32API
// バージョン: 0.2
// 用途目的: 特になし
// 使用方法: main以下を見ると吉
//
// もうちょいまとまったら sourceforge にうpするつもり
//
//#define WINDOWS
#define ONLINE_COMPILER

#include <memory>
#include <vector>
#include <string>
#include <queue>

#include <cstdlib>
#ifdef WINDOWS
#define CLS "cls"
#else
#define CLS "reset"
#endif

#define PIXEL_CHARACTER char
typedef unsigned char byte;
typedef unsigned int uint;

// -------------------------------------------- 固有事情を鑑みて自前スマポ
template<typename T>
struct Auto_Ptr {
	T *ptr;
	Auto_Ptr(): ptr(0) {}
	Auto_Ptr(T *p): ptr(p) {}
	Auto_Ptr(const Auto_Ptr& base)
	{
		ptr = base.ptr;
		const_cast<Auto_Ptr*>(&base)->ptr = NULL;
	}
	~Auto_Ptr() { if(ptr) delete ptr; }
	T* operator->() { return ptr; }
	T& operator=(const Auto_Ptr& right)
	{
		ptr = right.ptr;
		const_cast<Auto_Ptr*>(&right)->ptr = NULL;
		return *ptr;
	}
};

// -------------------------------------------- 最も基本的なBMPならぬ"C"MPサーフェス
#define _GET(cm,x,y) (cm).buff[(x)+(y)*((cm)._w)]
#define _SET(cm,x,y,v) (cm).buff[(x)+(y)*((cm)._w)] = (v)
#define _VALID_X(cm,x) ((x)>=0 && (x)<(cm)._w)
#define _VALID_Y(cm,y) ((y)>=0 && (y)<(cm)._h)

class DrawCtrl;

template<typename _BASE_TYPE>
class _Surface {
friend class DrawCtrl;
private:
	struct {
		_BASE_TYPE *buff;
		_BASE_TYPE space;
		int _w, _h;
	} cm;

	void make(int w, int h);
	void merge(const _Surface &sur, _BASE_TYPE sp);
public:
	int x, y;
	
	_Surface(): x(0), y(0) { cm.buff = cm._w = cm._h = 0; }
	_Surface(int w, int h, _BASE_TYPE spc): x(0), y(0) { cm.space = spc; make(w, h); }
	~_Surface() { delete [] cm.buff; }
	
	_Surface& operator+=(const _Surface& sur);
	_Surface& operator*=(const _Surface& sur);
};

template<typename _BASE_TYPE>
void _Surface<_BASE_TYPE>::make(int w, int h)
{
	cm._w = w;
	cm._h = h;
	uint sz = w * h + 1;
	
	cm.buff = new _BASE_TYPE[sz];
	memset(cm.buff, cm.space, sizeof(_BASE_TYPE) * sz);
}

template<typename _BASE_TYPE>
void _Surface<_BASE_TYPE>::merge(const _Surface<_BASE_TYPE> &sur, _BASE_TYPE sp)
{
	for(int yy = 0; yy < sur.cm._h; ++yy)
	{
		for(int xx = 0; xx < sur.cm._w; ++xx)
		{
			int px = sur.x + xx;
			int py = sur.y + yy;
			if(
				!_VALID_X(cm, px) || !_VALID_Y(cm, py)
				|| (sp != _BASE_TYPE(0) && _GET(sur.cm, xx, yy) == sp)
			) continue;
			_SET(cm, px, py, _GET(sur.cm, xx, yy));
		}
	}
}

// 基本的な重ね合わせだけサポート:上書き
template<typename _BASE_TYPE>
_Surface<_BASE_TYPE>& _Surface<_BASE_TYPE>::operator+=(const _Surface<_BASE_TYPE>& sur)
{
	this->merge(sur, _BASE_TYPE(0));
	return *this;
}

// 基本的な重ね合わせだけサポート:透過合成
template<typename _BASE_TYPE>
_Surface<_BASE_TYPE>& _Surface<_BASE_TYPE>::operator*=(const _Surface<_BASE_TYPE>& sur)
{
	this->merge(sur, cm.space);
	return *this;
}

// -------------------------------------------- ちょっと迷う。設計的に
#define VIDEO_WIDTH 20
#define VIDEO_HEIGHT 20
#define C_SPC 32

typedef PIXEL_CHARACTER _BaseType;
typedef _Surface<_BaseType> Surface;
typedef Auto_Ptr<Surface> _PSurface;
typedef Surface* HSURFACE;

class DrawCtrl;
typedef Auto_Ptr<DrawCtrl> HDC;

class DrawCtrl {
private:
	std::vector<_PSurface> _sur;
	_PSurface _vram;

	HSURFACE create(uint w, uint h, _BaseType spc)
	{
		Surface *sur = new Surface(w, h, spc);
		_sur.push_back(_PSurface(sur));
		return _sur.back().ptr;
	}
public:
	DrawCtrl()
	{
		_vram = _PSurface(new Surface(VIDEO_WIDTH, VIDEO_HEIGHT, C_SPC));
	}

	HSURFACE getPrimarySurface()
	{
		return _vram.ptr;
	}
	
	HSURFACE createSurface(uint w, uint h)
	{
		return create(w, h, C_SPC);
	}

	HSURFACE createCompatibleSurface(HSURFACE base)
	{
		if(base == NULL) base = _vram.ptr;
		return create(base->cm._w, base->cm._h, base->cm.space);
	}

	void clear();
	void paint();
	
	void textOut(HSURFACE sur, int x, int y, const _BaseType *str);
	void drawRect(HSURFACE sur, int x, int y, int w, int h);
};

void DrawCtrl::textOut(HSURFACE sur, int x, int y, const _BaseType *str)
{
	if(!_VALID_Y(sur->cm, y)) return;

	int p = 0;
	for(int i=x; *(str+p) != _BaseType(0) && i< sur->cm._w + x; ++i)
	{
		if(_VALID_X(sur->cm, i)) _SET(sur->cm, i, y, *(str+(p++)));
	}
}

void DrawCtrl::drawRect(HSURFACE sur, int x, int y, int w, int h)
{
	for(int i=x; i<(x+w); ++i)
	{
		if(!_VALID_X(sur->cm, i)) continue;
		if(_VALID_Y(sur->cm, y)) _SET(sur->cm, i, y, _BaseType('#'));
		if(_VALID_Y(sur->cm, y+h-1)) _SET(sur->cm, i, y+h-1, _BaseType('#'));
	}
	for(int i=y; i<(y+h); ++i)
	{
		if(!_VALID_Y(sur->cm, i)) continue;
		if(_VALID_X(sur->cm, x)) _SET(sur->cm, x, i, _BaseType('#'));
		if(_VALID_X(sur->cm, x+w-1)) _SET(sur->cm, x+w-1, i, _BaseType('#'));
	}
}

void DrawCtrl::clear()
{
#ifndef ONLINE_COMPILER
	system(CLS);
#endif
}

void DrawCtrl::paint()
{
	for(int y=0; y<_vram->cm._h; ++y)
	{
		_BaseType *ps = &(_vram->cm.buff[y*_vram->cm._w]);
		_BaseType *pe = ps + _vram->cm._w;
		_BaseType b = *pe;
		*pe = _BaseType(0);
		printf("%s\n", ps);
		*pe = b;
	}
}

// -------------------------------------------- アプリケーション

// -------------------------------------------------------------------
// 定義系 ------------------------------------------------------------

// とりあえずメッセージ
enum WM_MSG { WM_UNDEFINED, WM_CREATE, WM_PAINT, WM_FOO, WM_DESTOROY };

// ハンドル系 TODO: こっちのハンドルは本当にハンドル
typedef unsigned int HANDLE;
typedef HANDLE HWND;
typedef unsigned long WPARAM, LPARAM;

typedef bool (*WndProc)(HWND, WM_MSG, WPARAM, LPARAM);		// ウィンドプロシジャ
typedef struct { std::string name; WndProc proc; } Window;	// なんかウィンドウ

// メッセージ構造体
typedef struct _tMsg {
	HWND hWnd;
	WM_MSG msg;
	WPARAM wparam;
	LPARAM lparam;
	_tMsg(): msg(WM_UNDEFINED), wparam(0), lparam(0) {}
	_tMsg(HWND h, WM_MSG m, WPARAM wp, LPARAM lp): hWnd(h), msg(m), wparam(wp), lparam(lp) {}
} MSG;

typedef std::queue<MSG> MsgQue;				// メッセージのキュー
typedef std::pair<Window, MsgQue> WinSet;	// ウィンドウとメッセージキューのセット
typedef std::vector<WinSet> EnumWin;		// ウィンドウの列挙
typedef std::vector<HDC> EnumDc;			// 描画領域の列挙


// -------------------------------------------------------------------
// OSの中 ------------------------------------------------------------

EnumWin ew;
EnumDc ed;

HDC& GetDC(HWND hWnd)
{
	return ed[hWnd];
}

HANDLE RegisterWindow(const char *name, WndProc proc)	// 実質CreateWindowの仕事もしてる状態
{
	Window wm = {std::string(name), proc};
	ew.push_back(WinSet(wm, MsgQue()));
	ed.push_back(HDC(new DrawCtrl()));
	return (HANDLE)ew.size()-1;
}

bool GetMessage(HANDLE hWnd, MSG &msg)
{
	if( ew[hWnd].second.size()<1 ) return false;

	MSG m = ew[hWnd].second.front();
	msg.hWnd = hWnd;
	msg.msg = m.msg;
	msg.wparam = m.wparam;
	msg.lparam = m.lparam;

	ew[hWnd].second.pop();

	return true;
}

bool DispatchMessage(MSG &msg)
{
	return ew[msg.hWnd].first.proc(msg.hWnd, msg.msg, msg.wparam, msg.lparam);
}

void os_no_sigoto(HWND hWnd)
{
	// TODO: ここだよねキモ
	ew[hWnd].second.push(MSG(hWnd, WM_CREATE, 0, 0));
	ew[hWnd].second.push(MSG(hWnd, WM_FOO, 0, 0));
	ew[hWnd].second.push(MSG(hWnd, WM_PAINT, 0, 0));
	ew[hWnd].second.push(MSG(hWnd, WM_DESTOROY, 0, 0));
}


// -------------------------------------------------------------------
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// このOSで動かす何らかのアプリケーションコード ----------------------
// ここから下を各PGが、固有のアプリケーションとして書く --------------
// -------------------------------------------------------------------
//
// TODO: 元ネタ32API 風にしてしまうか、それだと *ダサい* から
// 普通にクラスにしてしまうかで、設計的な迷い中
// 上のSurfaceもそうだがハンドルとか言いつつ生ポ。ニュアンス変更予定

// -------------------------------------------- ウィンドプロシジャ
bool proc(HWND hWnd, WM_MSG msg, WPARAM wParam, LPARAM lParam)
{
	static HDC dc;
	static HSURFACE surf;

	switch(msg)
	{
		case WM_CREATE:
		break;
		case WM_FOO:
		break;
		case WM_PAINT:
			dc = GetDC(hWnd);
			dc->drawRect(dc->getPrimarySurface(), 0, 0, VIDEO_WIDTH, VIDEO_HEIGHT);
			
			surf = dc->createCompatibleSurface(NULL);
			dc->drawRect(surf, 2, 2, 20, 20);
			dc->textOut(surf, 1, 3, "-- vipper --");
			
			(*dc->getPrimarySurface()) *= *surf;

			dc->clear();
			dc->paint();
		break;
		case WM_DESTOROY:
		break;
		default:
			// noop
		break;
	}
	
	return true;
}

// -------------------------------------------- メイン:とりあえず動確
int main()
{
	HWND hWnd = RegisterWindow("名前", proc);	// ウィンドウを登録して
	MSG msg;

	os_no_sigoto(hWnd);

	while(GetMessage(hWnd, msg))	// ウィンドウにメッセージがあるか尋ねて
	{
		if(!DispatchMessage(msg)) break;	// あればディスパッチ
	}

	return 0;
}


Output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
####################
#                  #
# ##################
#-- vipper --      #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
# #                #
####################


Create a new paste based on this one


Comments: