/*	
 *	cliprend.h
 *
 *	描画ライブラリを定義します。
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2008 Naoyuki Sawa
 *
 *	* Wed Feb 13 06:00:00 JST 2002 Naoyuki Sawa
 *	- 作成開始。
 *	* Wed Jun 28 00:56:31 JST 2006 Naoyuki Sawa
 *	- mesh_load()の宣言を追加しました。
 *	* Wed Jan 10 14:39:19 JST 2007 Naoyuki Sawa
 *	- surface_stretch()を追加しました。
 *	* Mon Mar 12 00:13:49 JST 2007 Naoyuki Sawa
 *	- render_rectangle_dark()→render_rectangle_shadow()に名前変更しました。
 *	* Sun Jul 15 23:00:19 JST 2007 Naoyuki Sawa
 *	- render_rectangle_shadow()のコメントが間違っていたのを修正しました。
 *	  コードには変更ありません。
 *	* Thu Sep 27 16:44:15 JST 2007 Naoyuki Sawa
 *	- RENDER構造体とRENDERCONTEXT構造体の全体をレイアウト固定とするコメントを追記しました。
 *	  コードには変更ありません。
 *	* Wed Oct 17 12:30:13 JST 2007 Naoyuki Sawa
 *	- surface_stretch()をASM化しました。
 *	  使用方法の注意点は、FRAM4領域を使用しているAPI(pceLCDTrans(),pceFileWriteSct()等)と同様です。
 *	  詳細は、ASM版surface_stretch()のコード上のコメントを参照してください。
 *	* Mon Nov 05 15:54:07 JST 2007 Naoyuki Sawa
 *	- soft_focus()を追加しました。
 *	* Fri Dec 28 20:39:14 JST 2007 Naoyuki Sawa
 *	- render_rectangle_clip()を追加しました。
 *	* Tue Jan 01 21:17:37 JST 2008 Naoyuki Sawa
 *	- DSLPARAM構造体の、fore_colorとback_colorの順序を入れ替えました。
 *	* Sun Jan 13 13:34:20 JST 2008 Naoyuki Sawa
 *	- draw_primitive_wz()をframdp1.cへ、draw_primitive_woz()をframdp2.cへ、移動しました。
 *	  draw_primitive_wz()とdraw_primitive_woz()を、今後、アセンブラ化するための準備です。
 *	- この変更に伴い、いくつかの細かな変更を行いました。
 *	  変更箇所は、cliprend.hとclipren3.cを、「2008/01/13」で検索してください。
 *	* Mon Jan 14 23:18:06 JST 2008 Naoyuki Sawa
 *	- draw_primitive_woz()を廃止し、draw_primitive_wz()に統合し、関数名をdraw_primitive()に変更しました。
 *	  詳しくは、framdprm.cのコメントを参照してください。
 */
#ifndef __CLIP_REND_H__
#define __CLIP_REND_H__

/* REND_NOASMを定義するとCルーチン、定義しなければasmルーチンを使います。 */
#undef REND_NOASM	/* まず確実に未定義にした上で… */
//#define REND_NOASM	/* 必要に応じて定義してください（定義すると遅くなります） */

/*****************************************************************************
 *	
 *****************************************************************************/

#ifdef PIECE
typedef PBMP_FILEHEADER	TEXTUREHEADER;
typedef PIECE_BMP	TEXTURE;
#else /*PIECE*/
typedef struct _TEXTUREHEADER {		/* PBMP_FILEHEADERにバイナリ互換 */
	unsigned long head;		/* + 0,4 シグネチャ'PBMP'        */
	unsigned long fsize;		/* + 4,4 ファイルサイズ          */
	unsigned char bpp;		/* + 8,1 ビット深度              */
	unsigned char mask;		/* + 9,1 マスク深度              */
	short w;			/* +10,2 幅                      */
	short h;			/* +12,2 高さ                    */
					/* +14,2 パディング              */
	unsigned long buf_size;		/* +16,4 データサイズ            */
					/* =20                           */
} TEXTUREHEADER;
typedef struct _TEXTURE {		/* PIECE_BMPにバイナリ互換 */
	TEXTUREHEADER header;		/* + 0,20 ヘッダ           */
	unsigned char* buf;		/* +20, 4 ビットデータ     */
	unsigned char* mask;		/* +24, 4 マスクデータ     */
					/* =28                     */
} TEXTURE;
#endif /*PIECE*/

/* SURFACE構造体は、PIECE_VRAM構造体の上位バイナリ互換です。
 * PIECE_VRAMへのポインタを要求する関数に、SURFACEへのポインタを渡せます。
 */
typedef struct _SURFACE {		/* 描画先サーフェイス   */
	short w;			/* + 0,2 幅             */
	short h;			/* + 2,2 高さ           */
	unsigned char* vbuff;		/* + 4,4 カラーバッファ */
	/* ↑ここまでPIECE_VRAM互換。↓これ以降は拡張部分です。 */
	unsigned char* zbuff;		/* + 8,4 Ｚバッファ     */
					/* =12                  */
} SURFACE;

typedef struct _VERTEX {		/* ポリゴン頂点          */
	short x;			/* +0,2 水平ピクセル座標 */
	short y;			/* +2,2 垂直ピクセル座標 */
	unsigned char s;		/* +4,1 水平テクセル座標 */
	unsigned char t;		/* +5,1 垂直テクセル座標 */
} VERTEX;				/* =6                    */

typedef struct _TCOORD {		/* テクスチャ座標 */
	unsigned char s;		/* +0,1 水平座標  */
	unsigned char t;		/* +1,1 垂直座標  */
					/* =2             */
} TCOORD;

typedef struct _FACEVERTEX {		/* フェイス頂点                  */
	unsigned char iv;		/* +0,1 頂点座標インデクス       */
	unsigned char ic;		/* +1,1 テクスチャ座標インデクス */
} FACEVERTEX;

typedef struct _FACE {			/* フェイス                      */
	unsigned char nfv;		/* +0,1    頂点の数              */
	unsigned char c;		/* +1,1    カラー                */
	/*FACEVERTEX fv[nfv];*/		/* +2,2nfv フェイス頂点リスト    */
					/* =2+2nfv                       */
} FACE;

typedef struct _MESH {			/* メッシュ                             */
	unsigned char nv;		/* +0,1            頂点座標の数         */
	unsigned char nc;		/* +1,1            テクスチャ座標の数   */
	unsigned char nf;		/* +2,1            フェイスの数         */
	unsigned char reserved;		/* +3,1            (予約)               */
	/*vector v[nv];*/		/* +4,12nv         頂点座標リスト       */
	/*TCOORD c[nc];*/		/* +4+12nv,2nc     テクスチャ座標リスト */
	/*FACE f[nf];*/			/* +4+12nv+2nc,(?) フェイスリスト       */
					/* =4+12nv+2nc+(?)                      */
} MESH;

/*****************************************************************************
 *	内部使用
 *****************************************************************************/

/* クリッピング用頂点 */
typedef struct _CLIPVERTEX {
	fixed x, y, z;		/* + 0,12 頂点座標       */
	fixed s, t;		/* +12, 8 テクスチャ座標 */
				/* =20                   */
} CLIPVERTEX;

/* 描画用頂点 */
typedef struct _RENDVERTEX {
	unsigned short x, y;	/* + 0,4 頂点座標               */
	unsigned short z;	/* + 4,2 Ｚ値(8.8bit)           */
	unsigned short s, t;	/* + 6,4 テクスチャ座標(8.8bit) */
				/* =10                          */
} RENDVERTEX;

///* DDA */
//typedef struct _DDA {
//	int n;			/* + 0,4 端数の増加量     */
//	int d;			/* + 4,4 端数             */
//	int u;			/* + 8,4 毎回の変化量     */
//	int v;			/* +12,4 繰上げ時の変化量 */
//				/* =16                    */
//} DDA;
//→2003/12/28: 他のモジュールでも使うことがあるので、clipmisc.hへ移動しました。

/* draw_scanline_*_*()へ引き渡すパラメータの構造体です。
 * draw_scanline_*_*()はアセンブラで高速化するので、確実にオフセット固定とするために、この構造体を用意しました。
 */
typedef struct _DSLPARAM {
	/* サーフェイス */
	unsigned short surface_w;			/*  0, 2: 幅 */
	unsigned short surface_h;			/*  2, 2: 高さ */
	unsigned char* surface_vbuff;			/*  4, 4: カラーバッファ */
	unsigned char* surface_zbuff;			/*  8, 4: Ｚバッファ */
	/* テクスチャ */
	unsigned short texture_w;			/* 12, 2: 幅 */
	unsigned short texture_h;			/* 14, 2: 高さ */
	unsigned char* texture_buf;			/* 16, 4: イメージ */
	unsigned char* texture_mask;			/* 20, 4: マスク */
	/* カラー */
//{{2008/01/01:変更
//	unsigned char back_color;			/* 24, 1: 背景色 */
//	unsigned char fore_color;			/* 25, 1: 前景色 */
//↓ * Tue Jan 01 21:17:37 JST 2008 Naoyuki Sawa
//↓ - DSLPARAM構造体の、fore_colorとback_colorの順序を入れ替えました。
//↓   必須では有りませんが、DRW_CLR()のパラメータ順と一致させて、解り易くするためです。
//↓ - 現時点で、これらのフィールドを参照していたモジュールは、以下のとおりです。
//↓	framds11.c … スキャンライン描画関数（Ｚ比較あり・テクスチャなし）
//↓	framds12.c … スキャンライン描画関数（Ｚ比較あり・1bitテクスチャ）
//↓	framds13.c … スキャンライン描画関数（Ｚ比較あり・1bitmaskテクスチャ）
//↓	framds21.c … スキャンライン描画関数（Ｚ比較なし・テクスチャなし）
//↓	framds22.c … スキャンライン描画関数（Ｚ比較なし・1bitテクスチャ）
//↓	framds23.c … スキャンライン描画関数（Ｚ比較なし・1bitmaskテクスチャ）
//↓   framds11.c、framds21.cは既にアセンブラ化していたので、オフセットを修正しました。
//↓   framds12.c、framds13.c、framds22.c、framds23.cはまだアセンブラ化していないので、
//↓   今回の変更に伴う修正は必要ありませんでした。
	unsigned char fore_color;			/* 24, 1: 前景色 */
	unsigned char back_color;			/* 25, 1: 背景色 */
//}}2008/01/01:変更
} DSLPARAM;

/* スキャンライン描画関数の本体です。アプリケーションから直接利用しないで下さい。 */
typedef void (*DSLPROC)(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);
void draw_primitive(RENDVERTEX vertices[/*n_vertices*/], int n_vertices, DSLPARAM* param, DSLPROC draw_scanline); /* framdprm.c {{2008/01/14:追加}} */ 
/* (Ｚコンペアあり) */
//void draw_primitive_wz(RENDVERTEX vertices[/*n_vertices*/], int n_vertices, DSLPARAM* param, DSLPROC draw_scanline);	/* framdp1.c {{2008/01/13:追加}} */ /* {{2008/01/14:削除}} */
void draw_scanline_wz_color(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds11.c */
void draw_scanline_wz_1bit(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds12.c */
void draw_scanline_wz_1bitmask(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds13.c */
void draw_scanline_wz_2bit(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds14.c */
void draw_scanline_wz_2bitmask(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds15.c */
/* (Ｚコンペアなし) */
//void draw_primitive_woz(RENDVERTEX vertices[/*n_vertices*/], int n_vertices, DSLPARAM* param, DSLPROC draw_scanline);	/* framdp2.c {{2008/01/13:追加}} */ /* {{2008/01/14:削除}} */
void draw_scanline_woz_color(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds21.c */
void draw_scanline_woz_1bit(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds22.c */
void draw_scanline_woz_1bitmask(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds23.c */
void draw_scanline_woz_2bit(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds24.c */
void draw_scanline_woz_2bitmask(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param);	/* framds25.c */

/****************************************************************************
 *	スキャンライン描画関数用マクロ定義
 ****************************************************************************/

/* draw_primitive_*()用 DDAセットアップ */
#define DRAW_PRIMITIVE_SETUP(i) \
	side->cur.i = v0->i; \
	if(v0->i <= v1->i) { \
		side->i.n = (v1->i - v0->i) % side->ny; \
		side->i.d = -side->ny; \
		side->i.u = (v1->i - v0->i) / side->ny; \
		side->i.v = 1; \
	} else { \
		side->i.n = (v0->i - v1->i) % side->ny; \
		side->i.d = -side->ny; \
		side->i.u = -((v0->i - v1->i) / side->ny); \
		side->i.v = -1; \
	}

/* draw_primitive_*()用 DDAステップ実行 */
#define DRAW_PRIMITIVE_STEP(i) \
	side->cur.i += side->i.u; \
	side->i.d += side->i.n * 2; \
	if(side->i.d >= 0) { \
		side->cur.i += side->i.v; \
		side->i.d -= side->ny * 2; \
	}

/* draw_scanline_*_*()用 DDAセットアップ */
#define DRAW_SCANLINE_SETUP(i) \
	cur.i = v0->i; \
	if(v0->i <= v1->i) { \
		i.n = (v1->i - v0->i) % nx; \
		i.d = -nx; \
		i.u = (v1->i - v0->i) / nx; \
		i.v = 1; \
	} else { \
		i.n = (v0->i - v1->i) % nx; \
		i.d = -nx; \
		i.u = -((v0->i - v1->i) / nx); \
		i.v = -1; \
	}

/* draw_scanline_*_*()用 DDAステップ実行 */
#define DRAW_SCANLINE_STEP(i) \
	cur.i += i.u; \
	i.d += i.n * 2; \
	if(i.d >= 0) { \
		cur.i += i.v; \
		i.d -= nx * 2; \
	}

/*****************************************************************************
 *	
 *****************************************************************************/

/* テクスチャ構造体を初期化します。
 * [in]
 *	texture		初期化するテクスチャ構造体。
 *	data		PBMPファイルイメージの先頭アドレス。
 * [out]
 *	戻り値		引数textureの値をそのまま返します。
 * [note]
 *	* TEXTURE構造体はPIECE_BMP構造体と同じ(typedef)なので、
 *	  この関数はPIECE_BMP構造体の初期化にも利用できます。
 */
TEXTURE* texture_init(TEXTURE* texture, const void* data);

/* テクスチャ構造体配列を初期化します。
 * [in]
 *	texture		初期化するテクスチャ構造体配列の先頭アドレス。
 *	texture_count	初期化するテクスチャ構造体配列の要素数。
 *	...		PBMPファイルイメージの先頭アドレスを列挙してください。
 *			列挙数はtexture_countで指定した数と同じでなければいけません。
 * [note]
 *	* 複数のテクスチャを利用するアプリケーションのためのユーティリティ関数です。
 *	  次の例のように使ってください。
 *
 *		extern const unsigned char PAT0[];
 *		extern const unsigned char PAT1[];
 *		TEXTURE texture_table[2];
 *		void init() {
 *			texture_table_init(texture_table, 2, PAT0, PAT1);
 *			// texture_table[0]はPAT0を使って初期化されました。
 *			// texture_table[1]はPAT1を使って初期化されました。
 *		}
 */
void texture_table_init(TEXTURE texture[], int texture_count, ...);

/* サーフェイスをクリアします。
 * [in]
 *	surface		サーフェイス構造体。
 *	color		背景色。
 * [note]
 *	* カラーバッファ(vbuff)がNULLでなければ、背景色でクリアします。
 *	* Ｚバッファ(zbuff)がNULLでなければ、0xFFでクリアします。
 */
void surface_clear(SURFACE* surface, int color);

/* ピクセルカラーを取得します。
 * [in]
 *	surface		サーフェイス構造体。
 *	x,y		ピクセル座標。
 * [out]
 *	戻り値		ピクセルカラー。
 *			サーフェイス外のピクセル座標なら、-1を返します。
 * [note]
 *	* この関数は、render_point()と対を成します。
 */
int surface_point(SURFACE* surface, int x, int y);

/* 転送元サーフェイス全体を、転送先サーフェイス全体へ、補間コピーします。
 * [in]
 *	dst		転送先サーフェイス。
 *	src		転送元サーフェイス。
 * [note]
 *	* 転送先、転送元のサーフェイスサイズは任意です。
 *	  たとえば、水平方向拡大、垂直方向縮小のような場合でも、問題無く処理できます。
 *	* 通常の4色表示でも、高速切替16色表示でも利用できます。
 *	  リニア補間と加重平均のアルゴリズムなので、本関数は階調数を意識していません。
 *	* 拡大・縮小に同じアルゴリズムを使用しています。
 *	  拡大は一般的なリニア補間ですが、縮小は範囲内全ピクセルの加重平均となります。
 *	  特に、縮小の負荷が高いので、注意してください。
 *	* 本関数は、拡大も縮小も低速で、リアルタイムゲームに利用することは難しいです。
 *	  以下に、テスト結果を記録しておきます。
 *	----------------------------------------------------------------------------------------------------------------------------
 *	* テスト環境
 *	  スタック SRAM
 *	  コード SRAM
 *	  TURBO ON 48MHz
 *	  16階調表示 OFF
 *	* テスト結果
 *	   63x 43 -> 128x88 (拡大) 0.16秒
 *	  128x 88 -> 128x88 (等倍) 0.12秒
 *	  255x255 -> 128x88 (縮小) 0.53秒
 *	* 考察
 *	- 本関数は、あまり力を入れて高速化しませんでした。
 *	  もし、多少、高速化できたとしても、リアルタイムゲームで毎フレームストレッチを実行できる速度には、ほど遠いと考えたからです。
 *	- スタックを高速RAMに配置したり、コードを高速RAMに配置すれば、速度が改善できますが、せいぜい二倍程度であり、高速化不足です。
 *	  また、ストレッチを効果的に使うには、16階調表示との併用が必要ですが、その場合、高速切替の負荷で、さらに速度が遅くなります。
 *	- 以上の理由により、高速化をあきらめて、単純な実装を維持することにしました。
 *	  本関数は、静的な画像を描画した任意サイズのサーフェイスを、メインサーフェイスにストレッチするような用途に利用してください。
 *	- ★注意★本関数の実装とは直接関係ありませんが、255×255を超えるサーフェイスの利用には注意してください。
 *	  render_object()はpceLCDDrawObject()を利用しており、pceLCDDrawObject()はRECTPの制限のため、255×255を超えられないからです。
 *	----------------------------------------------------------------------------------------------------------------------------
 *	* Wed Oct 17 12:30:13 JST 2007 Naoyuki Sawa
 *	- surface_stretch()をASM化しました。
 *	  使用方法の注意点は、FRAM4領域を使用しているAPI(pceLCDTrans(),pceFileWriteSct()等)と同様です。
 *	  詳細は、ASM版surface_stretch()のコード上のコメントを参照してください。
 */
void surface_stretch(SURFACE* dst, SURFACE* src);

/* サーフェイス全体に、ソフトフォーカスをかけます。
 * [in]
 *	surface		ソフトフォーカスをかけるサーフェイス。
 *			ソフトフォーカス処理をのための中間バッファとして、_def_vbuffを利用しています。
 *			そのため、11264(=128*88)ピクセル以上のサーフェイスを指定することはできません。
 *			本関数の呼び出しによって、_def_vbuffの内容は破壊されます。
 *	x		水平方向のソフトフォーカスの度合い。
 *	y		垂直方向のソフトフォーカスの度合い。
 *			ソフトフォーカスの度合いは「効果無し:1.0⇔0.0:最大効果」です。
 *			1.0超過、または、0.0未満を指定した場合は、この範囲に切り詰めます。
 * [note]
 *	- surface_stretch()の応用例です。
 *	  サーフェイスを縮小し、再度、拡大することで、ソフトフォーカス効果が得られます。
 *	- ソフトフォーカスの度合いは、水平(x)、垂直(y)、独立に指定できるようにしました。
 *	  片方を1.0(効果無し)に固定したまま、もう一方を1.0⇔0.0に変化させると、面白い効果が得られます。
 *	  通常のソフトフォーカスを行う場合は、両方に同じ値を指定してください。
 *	- 度合いのパラメータ(x,y)をfixedとせず、doubleとした理由は、以下のとおりです。
 *	  ①clipfixやframfixモジュールが、無駄にリンクされるのを防ぐためです。
 *	    2007/11/05現在、clippceやclipren2等の必須モジュールは、clipfixやframfixを利用していません。
 *	    アプリケーションプログラム内で固定小数を使わず、かつ、clipren3等のモジュールも使わなければ、
 *	    clipfixやframfixモジュールをリンクせずに済みます。
 *	    もし、soft_focus()が固定小数を使ってしまうと、soft_focus()は必須モジュールであるclipren2に
 *	    含まれているので、clipfixやframfixモジュールも必ずリンクされてしまい、無駄です。
 *	    このような無駄を避けるために、固定小数の使用を避けました。
 *	    その代わりに、adddf3やmuldf3等の浮動小数モジュールが参照されますが、
 *	    これらは既に必須モジュールであるclipprntから参照されており、今回増加するわけではありません。
 *	  ②soft_focus()の実行時間が充分に長く、浮動小数演算のオーパーヘッドが無視できるからです。
 *	    soft_focus()の実行時間は、パラメータにもよりますが、おおよそ100～200ミリ秒程度と推測します。
 *	    これは、soft_focus()内で浮動小数演算が占める時間や、アプリケーションかsoft_focus()への
 *	    パラメータ計算のために浮動小数演算を要する時間よりも充分に長いです。
 *	    従って、パラメータが浮動小数演算であっても、オーパーヘッドは無視できると考えました。
 *	- <使用例>
 *		int i = UPDOWN_MOTION(now, 30);	// 0,1,2,...,27,28,29,28,27,...,2,1,0,1,2,...
 *		double t = i / 29.0;		// 0.0→1.0→0.0→1.0→...
 *		t = pow(t, 2.0);		// 効果かかり始め(1.0付近)の変化を早めます。(調整可)
 *		soft_focus(&surface, t, t);	// ソフトフォーカスをかけます。
 */
void soft_focus(SURFACE* surface, double x, double y);

/*****************************************************************************
 *	RENDER
 *****************************************************************************/

#define RENDER_CONTEXT_STACK_SIZE	16			/* コンテキストスタックサイズ */

/* _render_object()のASM版からオフセット固定で直接扱うため、全体をレイアウト固定とします。 (2007/09/27追記) */
typedef struct _RENDERCONTEXT {
	matrix matrix;						/* + 0,48: 変換行列              */
	TEXTURE* texture;					/* +48, 4: テクスチャ(NULL:なし) */
} RENDERCONTEXT;						/* +52 */

/* _render_object()のASM版からオフセット固定で直接扱うため、全体をレイアウト固定とします。 (2007/09/27追記) */
typedef struct _RENDER {
	SURFACE* surface;					/* + 0, 4: 描画サーフェイス                 */
	short left;						/* + 4, 2: ビューポート矩形(グリッド座標系) */
	short top;						/* + 6, 2:                                  */
	short right;						/* + 8, 2:                                  */
	short bottom;						/* +10, 2:                                  */
	/* ↑ここより上↑はrender_line()アセンブラ版から直接扱うため、レイアウト固定です。 (2004/12/20現在) */
	/* ↑render_font()のASM版からも、オフセット固定で参照するようになりました。        (2007/09/19追記) */
	/* ↓ここより下↓を直接扱うアセンブラ版関数はまだ無いので、レイアウト変更可能です。(2004/12/20現在) → _render_object()のASM版から、オフセット固定で参照するようになりました。(2007/09/27追記) */
	fixed front;						/* +12, 4: クリッピング距離(3D描画専用)     */
	fixed back;						/* +16, 4:                                  */
	RENDERCONTEXT* context;					/* +20, 4: コンテキストスタックトップ       */
	/* ↑ここより上↑は_render_object()のASM版から直接扱うため、レイアウト固定です。   (2007/09/27追記) */
	RENDERCONTEXT context_stack[RENDER_CONTEXT_STACK_SIZE];	/* +24, ?: コンテキストスタック             */
} RENDER;

/* フレームを初期化します。
 * [in]
 *	render		レンダラーへのポインタ。
 *	surface		描画サーフェイス。
 *	x,y		ビューポート原点。
 *	width,height	ビューポートサイズ。
 *	front,back	クリッピング距離。
 *	fovy		垂直視野角度。
 * [note]
 *	* width,heightに0を指定すると、サーフェイスの幅、高さと同じと見なします。
 *	  従って、サーフェイス全体をビューポート領域として指定するには、
 *	  x,y,width,heightを0,0,0,0と指定するのが簡単です。
 *	* 3D描画を行わない場合は、front,back,fovyに全て0を指定してください。
 *	  front,back,fovyに全て0を指定した場合、変換行列は初期化されません。
 *	* この関数は、サーフェイスのクリアを行いません。
 *	  カラーバッファおよびＺバッファのクリアは、呼び出し側で行ってください。
 *	* 2003/09/14: 2D用と3D用に初期化関数を分けました。
 *	  2D用として初期化する場合は、もうfront/back/fovyに0を指定する必要はありません。
 */
void render_init_2d(RENDER* render, SURFACE* surface, int x, int y, int width, int height);
void render_init_3d(RENDER* render, SURFACE* surface, int x, int y, int width, int height, fixed front, fixed back, fixed fovy);

/* コンテキストを退避します。
 * [in]
 *	render		レンダラーへのポインタ。
 */
void render_save(RENDER* render);

/* コンテキストを復元します。
 * [in]
 *	render		レンダラーへのポインタ。
 */
void render_restore(RENDER* render);

/* 点を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		点の座標。
 *	color		カラー。
 * [note]
 *	* この関数は、surface_point()と対を成します。
 */
void render_point(RENDER* render, int x, int y, int color);

/* 同じ色の範囲を塗りつぶします。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x0,y0		塗りつぶし開始点。
 *	color		カラー。
 * [out]
 *	戻り値		塗ったピクセルの数。
 * [note]
 *	* (x0,y0)の色が続く範囲を、colorで塗りつぶします。
 *	  (x0,y0)の色が既にcolorと同じなら、何もしません。
 *	* (x0,y0)がビューポート外なら、何もしません。
 */
int render_paint(RENDER* render, int x0, int y0, int color);

/* 線分を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x0,y0		始点座標。
 *	x1,y1		終点座標。
 *	color		カラー。
 * [note]
 *	* 多角形を描くために、連続して呼び出されることを想定しています。
 *	  よって、終点ピクセル(x1,y1)は描きません。
 *	* ただし実装の都合上、クリッピングされた側の終点も描かないので、
 *	  画面内から画面外への線分を描こうとすると、画面端に1ピクセルの
 *	  すき間ができてしまいます。要修正。
 *	* Fri Mar  8 07:00:00 JST 2002 Naoyuki Sawa
 *	  修正しました。
 */
void render_line(RENDER* render, int x0, int y0, int x1, int y1, int color);

/* 破線を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x0,y0		始点座標。
 *	x1,y1		終点座標。
 *	i_pat		破線パターンの開始インデックス。
 *	pat		//破線パターン。(カラー値の配列。値4以上は透明)
 *			//↓* Tue May 16 17:10:00 JST 2006 Naoyuki Sawa
 *			//↓- render_dashes()を16階調モードでも利用できるよう、透明色の定義を変更しました。
 *			//↓  これまでは4以上を透明色として扱っていましたが、今後は16以上を透明色とします。
 *			破線パターン。(カラー値の配列。値16以上は透明)
 *	n_pat		破線パターンの要素数。(1以上)
 * [out]
 *	戻り値		破線パターンの終了インデックス＋１。
 *			連続した線分を描くときは、この戻り値を次のrender_dashes()呼び出しのi_patに渡せば、
 *			破線パターンがうまくつながります。
 * [note]
 *	* n_patに0を指定すると、ゼロ除算エラーが発生します。
 *	* i_pat>=n_patでも構いません。適切な繰り返し位置から開始します。
 */
int render_dashes(RENDER* render, int x0, int y0, int x1, int y1, unsigned i_pat, const unsigned char* pat, unsigned n_pat);

/* 矩形を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		左上原点座標。
 *	w,h		矩形のサイズ。
 *	color		カラー。
 * [note]
 *	* 座標とサイズはグリッド座標系で指定してください。(Windows GDIと同様です)
 */
void render_rectangle(RENDER* render, int x, int y, int w, int h, int color);

/* 矩形座標の正規化とクリッピングを行います。
 * [in]
 *	(px,py,pw,ph)		変更前の座標値へのポインタ。
 * [out]
 *	戻り値			0 = 完全に画面外。
 *				    描画を行う必要はありません。
 *				    (*px,*py,*pw,*ph)は変更しません。
 *				1 = 少なくとも一部が画面内。
 *				    描画を行う必要があります。
 *				    (*px,*py,*pw,*ph)は変更されます。
 *	(*px,*py,*pw,*ph)	変更後の座標値を格納します。
 *				戻り値が0の場合は、格納しません。
 */
int render_rectangle_clip(RENDER* render, int* px, int* py, int* pw, int* ph);

/* 矩形を塗りつぶします。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		左上原点座標。
 *	w,h		矩形のサイズ。
 *	color		カラー。
 * [note]
 *	* 座標とサイズはグリッド座標系で指定してください。(Windows GDIと同様です)
 */
void render_rectangle_fill(RENDER* render, int x, int y, int w, int h, int color);

/* 矩形領域のピクセル値を増減します。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		左上原点座標。
 *	w,h		矩形のサイズ。
 *	adjust		ピクセル値増加量、または、ピクセル値減少量。
 *			(adjust<0)の場合、ピクセル値を減少します。
 *			(adjust>0)の場合、ピクセル値を増加します。
 *			(adjust=0)の場合、何もしません。
 *	limit		ピクセル値上限、または、ピクセル値下限。
 *			(adjust<0)の場合、(limit=ピクセル値下限)と見なします。
 *			  ピクセル値を減少した結果、limitを下回ったら、limitに補正します。
 *			  通常は、0を指定してください。
 *			  0以外の値を指定することも可能です。
 *			(adjust>0)の場合、(limit=ピクセル値上限)と見なします。
 *			  ピクセル値を増加した結果、limitを上回ったら、limitに補正します。
 *			  通常は、3(4階調表示)、または、15(16階調表示)を指定してください。
 *			  3、または、15以外の値を指定することも可能です。
 *			(adjust=0)の場合、limitは意味を持ちません。
 * [note]
 *	* 座標とサイズはグリッド座標系で指定してください。(Windows GDIと同様です)
 */
void render_rectangle_shadow(RENDER* render, int x, int y, int w, int h, int adjust, int limit);

/* 楕円を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		楕円に外接する矩形の左上原点座標。
 *	w,h		楕円に外接する矩形のサイズ。
 *	color		カラー。
 * [note]
 *	* 座標とサイズはグリッド座標系で指定してください。(Windows GDIと同様です)
 */
void render_ellipse(RENDER* render, int x, int y, int w, int h, int color);

/* 楕円を塗りつぶします。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		楕円に外接する矩形の左上原点座標。
 *	w,h		楕円に外接する矩形のサイズ。
 *	color		カラー。
 * [note]
 *	* 座標とサイズはグリッド座標系で指定してください。(Windows GDIと同様です)
 */
void render_ellipse_fill(RENDER* render, int x, int y, int w, int h, int color);

/* ポリゴンを描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	vertices	頂点リスト。
 *	n_vertices	頂点の数。
 *	color		カラー。
 */
void render_polygon(RENDER* render, const VERTEX* vertices, int n_vertices, int color);

/* メッシュを描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	mesh		描画されるメッシュ。
 */
void render_mesh(RENDER* render, const MESH* mesh);

/* メッシュファイルをロードします。
 * [in]
 *	filename	メッシュファイル名。
 * [out]
 *	戻り値		メッシュ構造体のメモリブロック。
 *			不要になったら、free()を呼び出して解放してください。
 * [note]
 *	* ファイルが見つからなかったり、読み込みエラーが発生した場合は、DIE()によって停止します。
 *	  本関数が失敗時にNULLを返すことは無いので、呼び出し側にて戻り値を検査する必要はありません。
 *	* メッシュファイル形式については、tool/ExportPieceClipを参照してください。
 *	  独自定義のXML形式メッシュ情報を出力する、Metasequoia用の自作プラグインです。
 */
MESH* mesh_load(const char* filename); /* → clipobj3.c */

#endif /*__CLIP_REND_H__*/
