/*	
 *	nuklear_piece.c
 *
 *	NuklearのP/ECE用レンダリングバックエンド
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2016-2017 Naoyuki Sawa
 *
 *	* Sat Nov 12 09:40:37 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	  まだオリジナル版のNuklearの変化が早くて、当モジュールも頻繁に変更すると思うので、まだ当モジュールはライブラリに含めない事にしました。		⇒{{2016/11/15コメント追記:当モジュールもライブラリに含めました。}}
 *	  いずれ、オリジナル版のNuklearが安定した頃に、当モジュールもライブラリに含める予定です。
 *	  それまでの間は、Nuklearを利用するアプリケーションのフォルダに当ファイルをコピーして、直接、アプリケーションと一緒にビルドして下さい。
 *	* Sun Nov 13 21:39:44 JST 2016 Naoyuki Sawa
 *	- nk_piece_new()の中でカーソルをロードする処理を追加したので、カーソルが表示されるようになりました。
 *	- デフォルトスタイルを、P/ECEの解像度に合わせて調整しました。
 *	* Tue Nov 15 09:07:00 JST 2016 Naoyuki Sawa
 *	- P/ECE開発環境のgcc33.exeで警告が出るのを抑制するために、'/clip/nuklear/nuklear.h'を新たに二か所直接修正しました。(移動元一か所＋移動先一か所です)
 *	  修正箇所は、'/clip/nuklear/nuklear.h'内の「{{2016/11/15移動:〜」のコメント(二か所)を参照して下さい。
 *	  修正後の内容で、パッチ('/clip/nuklear/nuklear.h.patch')を更新しました。
 *	  パッチの適用方法については、'/clip/nuklear/nuklear_dxlib.cpp'の、'Fri Oct 21 22:24:40 JST 2016 Naoyuki Sawa'のコメントを参照して下さい。
 *	  今回の修正は、P/ECE開発環境のgcc33.exeのために行った修正ですが、Windows環境でVC++でコンパイルする場合にも害は有りません。
 *	  引き続き、'/clip/nuklear/nuklear.h'は、P/ECE用とWindows用で共通としておきます。
 *	- 当モジュールもライブラリに含めました。
 *	  ただし、ライブラリ本体(clip1.lib,clip2.lib,fram.lib)に直接含めるのではなく、既存のliblua/liblua.lib等と同様に、独立したライブラリ(nuklear/nuklear_piece.lib)としてビルドしました。
 *	  そうした理由は、Nuklearのコードはまだ完全に理解出来ていない部分が多いので、もしCLiPライブラリに直接含めてしまうと、管理し切れなくなる恐れが有ると思ったからです。
 *	  また、もし今後のNuklearの変化によって、P/ECEでは使用出来なくなった場合に、ライブラリから外し易いようにしておくためにも、独立したライブラリとしました。
 *	* Thu Nov 17 21:56:29 JST 2016 Naoyuki Sawa
 *	- nk_piece_new()に、ポップアップの枠が表示されない問題を暫定的に回避する処理を追加しました。
 *	  2016/11/17時点のNuklear(リビジョン8e60328)では、nk_style_from_table()にて、win->popup_border_colorとwin->popup_borderの初期化が欠けている問題が有ります。
 *	  2016/11/16にプルリクエスト(https://github.com/vurtun/nuklear/pull/286)を提出しましたが、まだ採用されていないので、それまでここで明示的に初期化しておく事にします。
 *	  プルリクエストが採用されたら、この処理は不要になるので、削除して下さい。	⇒{{2016/11/21コメント追記:オリジナル版のNuklearでもポップアップの枠が表示されない問題が修正されたので、当モジュール内で行っていた暫定的に回避する処理はもう不要になったので削除しました。}}
 *	* Thu Mar 16 22:31:07 JST 2017 Naoyuki Sawa
 *	- リビジョン2e4db87にて、内部関数nk_strtoi(),nk_strtof(),nk_strtod()の引数endptrの型が(char**)⇒(const char**)に変更された事に伴い、C標準関数のstrtod()をそのまま使うと警告が出るようになった問題を回避しました。
 *	  僕的には、リビジョン2e4db87の上記の変更は改悪だと思うので、いつか元に戻って欲しいです…
 *	* Wed May 10 22:17:50 JST 2017 Naoyuki Sawa
 *	- nk_vsnprintf()の警告抑制を削除しました。
 *	  オリジナル版のnuklear.hのリビジョン70d9de1にて、NK_INCLUDE_STANDARD_IOが定義されていればnk_vsnprintf()は定義されない対応がなされたので、自前でnk_vsnprintf()の警告抑制を行う必要は無くなったからです。
 */
#include "clip.h"
/****************************************************************************
 *	
 ****************************************************************************/
#include "nuklear_piece.h"	//宣言用
//{{使われていない関数で「warning: `...' defined but not used」という警告が出るのを抑制します。本当はメモリ節約のために実体を削除すべきなのですが、オリジナル版のnuklear.hに対して多くの変更を行いたくないので、警告抑制だけで妥協する事にしました。
static float nk_sqrt(float x) __attribute__((unused));
static float nk_sin(float x) __attribute__((unused));
static float nk_cos(float x) __attribute__((unused));
static int nk_to_upper(int c) __attribute__((unused));
static void* nk_memcopy(void* dst0, const void* src0, nk_size length) __attribute__((unused));
static void nk_memset(void* ptr, int c0, nk_size size) __attribute__((unused));
static int nk_ifloorf(float x) __attribute__((unused));
//static int nk_vsnprintf(char* buf, int buf_size, const char* fmt, va_list args) __attribute__((unused));	//{{2017/05/10削除:nk_vsnprintf()の警告抑制を削除しました。オリジナル版のnuklear.hのリビジョン70d9de1にて、NK_INCLUDE_STANDARD_IOが定義されていればnk_vsnprintf()は定義されない対応がなされたので、自前でnk_vsnprintf()の警告抑制を行う必要は無くなったからです。}}
static char* nk_file_load(const char* path, nk_size* siz, struct nk_allocator* alloc) __attribute__((unused));
//}}使われていない関数で「warning: `...' defined but not used」という警告が出るのを抑制します。本当はメモリ節約のために実体を削除すべきなのですが、オリジナル版のnuklear.hに対して多くの変更を行いたくないので、警告抑制だけで妥協する事にしました。
#undef  __NUKLEAR_PIECE_H__
#define NK_IMPLEMENTATION
#include "nuklear_piece.h"	//実装用
#undef  NK_IMPLEMENTATION
/****************************************************************************
 *	ローカル関数宣言
 ****************************************************************************/
static void nk_piece_init_style1(struct nk_context* ctx);
static void nk_piece_init_style2(struct nk_context* ctx);
static void nk_piece_load_cursor(struct nk_context* ctx);
static void nk_piece_scissor(RENDER* render, int x, int y, int w, int h);
static void nk_piece_draw_line(RENDER* render, int x1, int y1, int x2, int y2, int line_thickness, struct nk_color col);
static void nk_piece_draw_curve(RENDER* render, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int line_thickness, struct nk_color col);
static void nk_piece_draw_rect(RENDER* render, int x, int y, int w, int h, int rounding, int line_thickness, struct nk_color col);
static void nk_piece_draw_rect_filled(RENDER* render, int x, int y, int w, int h, int rounding, struct nk_color col);
static void nk_piece_draw_rect_multi_color(RENDER* render, int x, int y, int w, int h, struct nk_color col1, struct nk_color col2, struct nk_color col3, struct nk_color col4);
static void nk_piece_draw_circle(RENDER* render, int x, int y, int w, int h, int line_thickness, struct nk_color col);
static void nk_piece_draw_circle_filled(RENDER* render, int x, int y, int w, int h, struct nk_color col);
static void nk_piece_draw_arc(RENDER* render, int cx, int cy, int r, float a1, float a2, int line_thickness, struct nk_color col);
static void nk_piece_draw_arc_filled(RENDER* render, int cx, int cy, int r, float a1, float a2, struct nk_color col);
static void nk_piece_draw_triangle(RENDER* render, int x1, int y1, int x2, int y2, int x3, int y3, int line_thickness, struct nk_color col);
static void nk_piece_draw_triangle_filled(RENDER* render, int x1, int y1, int x2, int y2, int x3, int y3, struct nk_color col);
static void nk_piece_draw_polygon(RENDER* render, const struct nk_vec2i* points, int point_count, int line_thickness, struct nk_color col);
static void nk_piece_draw_polygon_filled(RENDER* render, const struct nk_vec2i* points, int point_count, struct nk_color col);
static void nk_piece_draw_polyline(RENDER* render, const struct nk_vec2i* points, int point_count, int line_thickness, struct nk_color col);
static void nk_piece_draw_text(RENDER* render, int x, int y, int w, int h, const char* string, int len, const struct nk_user_font* font, struct nk_color bg, struct nk_color fg);
static void nk_piece_draw_image(RENDER* render, int x, int y, int w, int h, const struct nk_image* img, struct nk_color col);
static float nk_piecefont_get_text_width(nk_handle handle, float height, const char* text, int len);
/****************************************************************************
 *	構造体
 ****************************************************************************/
struct nk_piece {
	struct nk_context	ctx;		//コンテキスト
	int			t0;		//前回nk_piece_render()が呼び出された時刻
	int			scrkbd;
	int			mouse_button;
	double			mouse_pos_x;
	double			mouse_pos_y;
	double			mouse_speed;
};
/****************************************************************************
 *	グローバル定数
 ****************************************************************************/
const struct nk_user_font nk_piece_font[4] = {
	{ { .id = 0 }, 10, nk_piecefont_get_text_width },	//[0]=半角5x10/全角10x10
	{ { .id = 1 }, 16, nk_piecefont_get_text_width },	//[1]=半角8x16
	{ { .id = 2 },  6, nk_piecefont_get_text_width },	//[2]=半角4x6
	{ { .id = 3 },  5, nk_piecefont_get_text_width },	//[3]=半角4x5
};
/****************************************************************************
 *	グローバル関数
 ****************************************************************************/
//ライブラリを初期化する。
NK_API struct nk_context* nk_piece_new() {
	//構造体のメモリを確保する。
	struct nk_piece* piece = (struct nk_piece*)calloc(1, sizeof(struct nk_piece));
	if(!piece) { DIE(); }
	//コンテキストを初期化する。
	nk_init_default(&piece->ctx, &nk_piece_font[3]/*半角4x5*/);
	//デフォルトスタイルを設定する。
	nk_piece_init_style1(&piece->ctx);	//色の設定
	nk_piece_init_style2(&piece->ctx);	//サイズの設定
	//カーソルをロードする。
	nk_piece_load_cursor(&piece->ctx);
	//前回nk_piece_render()が呼び出された時刻の初期値を、現在時刻とする。
	piece->t0 = pceTimerGetCount();
	//カーソルの初期位置を画面中央とする。
	piece->mouse_pos_x = DISP_X / 2;
	piece->mouse_pos_y = DISP_Y / 2;
	nk_input_motion(&piece->ctx, piece->mouse_pos_x, piece->mouse_pos_y);
//{{2016/11/21削除:オリジナル版のNuklearでもポップアップの枠が表示されない問題が修正されたので、当モジュール内で行っていた暫定的に回避する処理はもう不要になったので削除しました。
////{{2016/11/17追加:nk_piece_new()に、ポップアップの枠が表示されない問題を暫定的に回避する処理を追加しました。
//	// * Thu Nov 17 21:56:29 JST 2016 Naoyuki Sawa
//	// - nk_piece_new()に、ポップアップの枠が表示されない問題を暫定的に回避する処理を追加しました。
//	//   2016/11/17時点のNuklear(リビジョン8e60328)では、nk_style_from_table()にて、win->popup_border_colorとwin->popup_borderの初期化が欠けている問題が有ります。
//	//   2016/11/16にプルリクエスト(https://github.com/vurtun/nuklear/pull/286)を提出しましたが、まだ採用されていないので、それまでここで明示的に初期化しておく事にします。
//	//   プルリクエストが採用されたら、この処理は不要になるので、削除して下さい。
//	piece->ctx.style.window.popup_border_color = piece->ctx.style.window.border_color;
//	piece->ctx.style.window.popup_border       = piece->ctx.style.window.border;
////}}2016/11/17追加:nk_piece_new()に、ポップアップの枠が表示されない問題を暫定的に回避する処理を追加しました。
//}}2016/11/21削除:オリジナル版のNuklearでもポップアップの枠が表示されない問題が修正されたので、当モジュール内で行っていた暫定的に回避する処理はもう不要になったので削除しました。
	return &piece->ctx;
}
/*--------------------------------------------------------------------------*/
//ライブラリを終了する。
NK_API void nk_piece_free(struct nk_context* ctx) {
	struct nk_piece* piece = CONTAINING_RECORD(ctx, struct nk_piece, ctx);
	//コンテキストを終了する。
	nk_free(&piece->ctx);
	//構造体のメモリを解放する。
	free(piece);
}
/*--------------------------------------------------------------------------*/
//イベントを処理する。
NK_API void nk_piece_handle_event(struct nk_context* ctx, int joy) {
	struct nk_piece* piece = CONTAINING_RECORD(ctx, struct nk_piece, ctx);
	//スクリーンキーボードの表示を切り替える。
	if(joy & TRG_B) {
		piece->scrkbd = !piece->scrkbd;
		//スクリーンキーボードが表示中になったら…
		if(piece->scrkbd) {
			//スクリーンキーボードを初期化する。
			// - スクリーンキーボードが非表示から表示に切り替わる度に、スクリーンキーボードを初期化する事にしました。
			//   アプリケーションが別の用途でスクリーンキーボードを使用していたかも知れないので、Nuklear用として使用を開始する直前に毎回初期化する方が安全だと思ったからです。
			ScrKbd_Init();
		}
	}
	//スクリーンキーボードが表示中ならば…
	if(piece->scrkbd) {
		int x = 0, y = 0, KeySym, state, ctrl;
		if(piece->mouse_pos_x < (DISP_X / 2)) { x = DISP_X - 43/*ScrKbd_W*/; }
		if(piece->mouse_pos_y < (DISP_Y / 2)) { y = DISP_Y - 19/*ScrKbd_H*/; }
		ScrKbd_SetPos(x, y);
		KeySym = ScrKbd_Exec(joy, &state);
		ctrl = !!(state & (1<<1)/*Control*/);
		if((KeySym >= 0x20) && (KeySym <= 0x7F)) {
			nk_input_char(&piece->ctx, KeySym);
		} else {
			static const int TBL_KeyMap[][3/*vk,(ctrl==0),(ctrl==1)*/]={
			{XK_Shift_L	,NK_KEY_SHIFT		,NK_KEY_SHIFT		},
			{XK_Shift_R	,NK_KEY_SHIFT		,NK_KEY_SHIFT		},
			{XK_Control_L	,NK_KEY_CTRL		,NK_KEY_CTRL		},
			{XK_Control_R	,NK_KEY_CTRL		,NK_KEY_CTRL		},
			{XK_Delete	,NK_KEY_DEL		,NK_KEY_DEL		},
			{XK_Return	,NK_KEY_ENTER		,NK_KEY_ENTER		},
			{XK_Tab		,NK_KEY_TAB		,NK_KEY_TAB		},
			{XK_BackSpace	,NK_KEY_BACKSPACE	,NK_KEY_BACKSPACE	},
			{XK_Up		,NK_KEY_UP		,NK_KEY_UP		},
			{XK_Down	,NK_KEY_DOWN		,NK_KEY_DOWN		},
			{XK_Left	,NK_KEY_LEFT		,NK_KEY_TEXT_WORD_LEFT	},
			{XK_Right	,NK_KEY_RIGHT		,NK_KEY_TEXT_WORD_RIGHT	},
			{XK_Home	,NK_KEY_SCROLL_START	,NK_KEY_SCROLL_START	},	//追加:NK_KEY_TEXT_START
			{XK_End		,NK_KEY_SCROLL_END	,NK_KEY_SCROLL_END	},	//追加:NK_KEY_TEXT_END
			{XK_Next	,NK_KEY_SCROLL_DOWN	,NK_KEY_SCROLL_DOWN	},
			{XK_Prior	,NK_KEY_SCROLL_UP	,NK_KEY_SCROLL_UP	}};
			int i;
			for(i = 0; i < ARRAY_SIZE(TBL_KeyMap); i++) {
				if(TBL_KeyMap[i][0/*vk*/] == KeySym) {
					int key = TBL_KeyMap[i][1 + ctrl];
					//スクリーンキーボードではキーアップの瞬間が検出出来ないので、キーダウンの直後に…
					if(key != -1) { nk_input_key(&piece->ctx, (enum nk_keys)key, 1/*down*/); }
					if(KeySym == XK_Home) { nk_input_key(&piece->ctx, NK_KEY_TEXT_START, 1/*down*/); }	//追加
					if(KeySym == XK_End)  { nk_input_key(&piece->ctx, NK_KEY_TEXT_END,   1/*down*/); }	//追加
					//…キーアップされたものとして処理する事にしました。
					if(key != -1) { nk_input_key(&piece->ctx, (enum nk_keys)key, 0/*up*/); }
					if(KeySym == XK_Home) { nk_input_key(&piece->ctx, NK_KEY_TEXT_START, 0/*up*/); }	//追加
					if(KeySym == XK_End)  { nk_input_key(&piece->ctx, NK_KEY_TEXT_END,   0/*up*/); }	//追加
				}
			}
		}
	//スクリーンキーボードが表示中でなければ…
	} else {
		int trg = piece->mouse_button ^ joy;
		          piece->mouse_button = joy;
		if(trg & PAD_A) {
			nk_input_button(&piece->ctx, NK_BUTTON_LEFT, piece->mouse_pos_x, piece->mouse_pos_y, !!(joy & PAD_A));
		}
		if(joy & PAD_LRUD) {
			piece->mouse_speed += piece->ctx.delta_time_seconds * 2.0/*調整可*/;	//加速
			piece->mouse_speed = clamp(piece->mouse_speed, 1.0, 3.0/*調整可*/);
			if(joy & PAD_LF) { piece->mouse_pos_x -= piece->mouse_speed; }
			if(joy & PAD_RI) { piece->mouse_pos_x += piece->mouse_speed; }
			if(joy & PAD_UP) { piece->mouse_pos_y -= piece->mouse_speed; }
			if(joy & PAD_DN) { piece->mouse_pos_y += piece->mouse_speed; }
			piece->mouse_pos_x = clamp(piece->mouse_pos_x, 0.0, DISP_X - 1.0);
			piece->mouse_pos_y = clamp(piece->mouse_pos_y, 0.0, DISP_Y - 1.0);
			nk_input_motion(&piece->ctx, piece->mouse_pos_x, piece->mouse_pos_y);
		} else {
			piece->mouse_speed = 0.0;	//速度をリセットする。
		}
	}
}
/*--------------------------------------------------------------------------*/
//現在のコンテキストを描画する。
NK_API void nk_piece_render(struct nk_context* ctx, struct _RENDER* render) {
	struct nk_piece* piece = CONTAINING_RECORD(ctx, struct nk_piece, ctx);
	//前回nk_piece_render()が呼び出された時刻からの、経過時間を格納する。
	{
		int t1 = pceTimerGetCount();
		piece->ctx.delta_time_seconds = (t1 - piece->t0) / 1000.0f;
		piece->t0 = t1;
	}
	{
		const struct nk_command* cmd;
		//クリッピング領域を退避する。
		int save_left   = render->left;
		int save_top    = render->top;
		int save_right  = render->right;
		int save_bottom = render->bottom;
		//現在のコンテキストの、各コマンドを描画する。
		nk_foreach(cmd, &piece->ctx) {
			switch(cmd->type) {
			default:
				{
					syslog(LOG_NOTICE, "nk_piece_render: unknown nk_command_type(%d)", cmd->type);
				}
				break;
			case NK_COMMAND_NOP:
				{
					/** no job **/
				}
				break;
			case NK_COMMAND_SCISSOR:
				{
					const struct nk_command_scissor* p = (const struct nk_command_scissor*)cmd;
					nk_piece_scissor(render,
						p->x,
						p->y,
						p->w,
						p->h);
				}
				break;
			case NK_COMMAND_LINE:
				{
					const struct nk_command_line* p = (const struct nk_command_line*)cmd;
					nk_piece_draw_line(render,
						p->begin.x,
						p->begin.y,
						p->end.x,
						p->end.y,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_CURVE:
				{
					const struct nk_command_curve* p = (const struct nk_command_curve*)cmd;
					nk_piece_draw_curve(render,
						p->begin.x,
						p->begin.y,
						p->ctrl[0].x,
						p->ctrl[0].y,
						p->ctrl[1].x,
						p->ctrl[1].y,
						p->end.x,
						p->end.y,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_RECT:
				{
					const struct nk_command_rect* p = (const struct nk_command_rect*)cmd;
					nk_piece_draw_rect(render,
						p->x,
						p->y,
						p->w,
						p->h,
						p->rounding,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_RECT_FILLED:
				{
					const struct nk_command_rect_filled* p = (const struct nk_command_rect_filled*)cmd;
					nk_piece_draw_rect_filled(render,
						p->x,
						p->y,
						p->w,
						p->h,
						p->rounding,
						p->color);
				}
				break;
			case NK_COMMAND_RECT_MULTI_COLOR:
				{
					const struct nk_command_rect_multi_color* p = (const struct nk_command_rect_multi_color*)cmd;
					nk_piece_draw_rect_multi_color(render,
						p->x,
						p->y,
						p->w,
						p->h,
						p->left,
						p->top,
						p->bottom,
						p->right);
				}
				break;
			case NK_COMMAND_CIRCLE:
				{
					const struct nk_command_circle* p = (const struct nk_command_circle*)cmd;
					nk_piece_draw_circle(render,
						p->x,
						p->y,
						p->w,
						p->h,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_CIRCLE_FILLED:
				{
					const struct nk_command_circle_filled* p = (const struct nk_command_circle_filled*)cmd;
					nk_piece_draw_circle_filled(render,
						p->x,
						p->y,
						p->w,
						p->h,
						p->color);
				}
				break;
			case NK_COMMAND_ARC:
				{
					const struct nk_command_arc* p = (const struct nk_command_arc*)cmd;
					nk_piece_draw_arc(render,
						p->cx,
						p->cy,
						p->r,
						p->a[0],
						p->a[1],
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_ARC_FILLED:
				{
					const struct nk_command_arc_filled* p = (const struct nk_command_arc_filled*)cmd;
					nk_piece_draw_arc_filled(render,
						p->cx,
						p->cy,
						p->r,
						p->a[0],
						p->a[1],
						p->color);
				}
				break;
			case NK_COMMAND_TRIANGLE:
				{
					const struct nk_command_triangle* p = (const struct nk_command_triangle*)cmd;
					nk_piece_draw_triangle(render,
						p->a.x,
						p->a.y,
						p->b.x,
						p->b.y,
						p->c.x,
						p->c.y,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_TRIANGLE_FILLED:
				{
					const struct nk_command_triangle_filled* p = (const struct nk_command_triangle_filled*)cmd;
					nk_piece_draw_triangle_filled(render,
						p->a.x,
						p->a.y,
						p->b.x,
						p->b.y,
						p->c.x,
						p->c.y,
						p->color);
				}
				break;
			case NK_COMMAND_POLYGON:
				{
					const struct nk_command_polygon* p = (const struct nk_command_polygon*)cmd;
					nk_piece_draw_polygon(render,
						p->points,
						p->point_count,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_POLYGON_FILLED:
				{
					const struct nk_command_polygon_filled* p = (const struct nk_command_polygon_filled*)cmd;
					nk_piece_draw_polygon_filled(render,
						p->points,
						p->point_count,
						p->color);
				}
				break;
			case NK_COMMAND_POLYLINE:
				{
					const struct nk_command_polyline* p = (const struct nk_command_polyline*)cmd;
					nk_piece_draw_polyline(render,
						p->points,
						p->point_count,
						p->line_thickness,
						p->color);
				}
				break;
			case NK_COMMAND_TEXT:
				{
					const struct nk_command_text* p = (const struct nk_command_text*)cmd;
					nk_piece_draw_text(render,
						p->x,
						p->y,
						p->w,
						p->h,
						p->string,
						p->length,
						p->font,
						p->background,
						p->foreground);
				}
				break;
			case NK_COMMAND_IMAGE:
				{
					const struct nk_command_image* p = (const struct nk_command_image*)cmd;
					nk_piece_draw_image(render,
						p->x,
						p->y,
						p->w,
						p->h,
						&p->img,
						p->col);
				}
				break;
			}
		}
		//クリッピング領域を復帰する。
		render->left   = save_left;
		render->top    = save_top;
		render->right  = save_right;
		render->bottom = save_bottom;
	}
	//現在のコンテキストの、コマンドをクリアする。
	nk_clear(&piece->ctx);
	//スクリーンキーボードが表示中ならば…
	if(piece->scrkbd) {
		//スクリーンキーボードを描画する。
		ScrKbd_Draw(render);
	}
}
/****************************************************************************
 *	ローカル関数
 ****************************************************************************/
//デフォルトスタイルを設定する。(色の設定)
static void nk_piece_init_style1(struct nk_context* ctx) {
	static const unsigned char TBL_ColTbl[NK_COLOR_COUNT]={
		3,	//NK_COLOR_TEXT				//文字の色								全てのウインドウやウィジットに共通です。
		0,	//NK_COLOR_WINDOW			//ウインドウの背景色
		1,	//NK_COLOR_HEADER			//タイトルバーの色
		2,	//NK_COLOR_BORDER			//ボーダーの色								全てのウインドウやウィジットに共通です。
		1,	//NK_COLOR_BUTTON			//ボタンの背景色		マウスカーソルが上に無い時
		0,	//NK_COLOR_BUTTON_HOVER			//ボタンの背景色		マウスカーソルが上に有る時
		2,	//NK_COLOR_BUTTON_ACTIVE		//ボタンの背景色		マウスボタンを押し下げている間
		1,	//NK_COLOR_TOGGLE			//四角の部分の色		マウスカーソルが上に無い時		ラベルの部分の背景色には関係有りません。
		1,	//NK_COLOR_TOGGLE_HOVER			//四角の部分の色		マウスカーソルが上に有る時		ラベルの部分の背景色には関係有りません。
		2,	//NK_COLOR_TOGGLE_CURSOR		//四角の部分の色		オンにした時の四角の中心部分の色
		1,	//NK_COLOR_SELECT			//選択ボタンの背景色
		2,	//NK_COLOR_SELECT_ACTIVE		//選択ボタンの背景色
		1,	//NK_COLOR_SLIDER			//つまみよりも右側のバーの色						プログレスバーの色一式もスライダの色一式が参照される。
		2,	//NK_COLOR_SLIDER_CURSOR		//つまみの色			マウスカーソルが上に無い時		つまみよりも左側のバーの色もこの色です。
		2,	//NK_COLOR_SLIDER_CURSOR_HOVER		//つまみの色			マウスカーソルが上に有る時
		2,	//NK_COLOR_SLIDER_CURSOR_ACTIVE		//つまみの色			マウスボタンを押し下げている間		※と思ったのだが実際にはNK_COLOR_SLIDER_CURSOR_HOVERの色のままになる(?)
		1,	//NK_COLOR_PROPERTY			//プロパティの背景色
		1,	//NK_COLOR_EDIT				//エディットの背景色
		2,	//NK_COLOR_EDIT_CURSOR			//									※参照されていない(?)カーソルの色はNK_COLOR_TEXTが使われるようです。
		1,	//NK_COLOR_COMBO			//閉じた部分の背景色							開いた部分の背景色はNK_COLOR_WINDOWが使われるようです。
		0,	//NK_COLOR_CHART			//チャートの背景色
		2,	//NK_COLOR_CHART_COLOR			//棒グラフや折れ線グラフの色	マウスカーソルが上に無い時
		2,	//NK_COLOR_CHART_COLOR_HIGHLIGHT	//棒グラフや折れ線グラフの色	マウスカーソルが上に有る時
		1,	//NK_COLOR_SCROLLBAR			//バーの背景色
		2,	//NK_COLOR_SCROLLBAR_CURSOR		//つまみの色			マウスカーソルが上に無い時
		2,	//NK_COLOR_SCROLLBAR_CURSOR_HOVER	//つまみの色			マウスカーソルが上に有る時
		2,	//NK_COLOR_SCROLLBAR_CURSOR_ACTIVE	//つまみの色			マウスボタンを押し下げている間
		1,	//NK_COLOR_TAB_HEADER			//ツリーのタブの色
	};
	struct nk_color table[NK_COLOR_COUNT];
	int i;
	for(i = 0; i < NK_COLOR_COUNT; i++) {
		table[i] = nk_rgb(TBL_ColTbl[i],
		                  TBL_ColTbl[i],
		                  TBL_ColTbl[i]);
	}
	nk_style_from_table(ctx, table);
}
/*--------------------------------------------------------------------------*/
//デフォルトスタイルを設定する。(サイズの設定)
static void nk_piece_init_style2(struct nk_context* ctx) {
	static const struct nk_vec2 v0 = { 0, 0 };
	static const struct nk_vec2 v1 = { 1, 1 };
	static const struct nk_vec2 v5 = { 5, 5 };
	struct nk_style* style = &ctx->style;
	//default text
	style->text.padding					= v0;					//ラベルは色々な所で使用するのでそれ自体にパディングは設定しない。
	//default button
	style->button.border					= 1;					//1にすべし(?)
	style->button.rounding					= 0;
	style->button.padding					= v1;					//ボタンのラベルはセンタリングされるのでパディングは関係無いが、一応パディングを設定しておく事にした。
	style->button.image_padding				= v0;
	style->button.touch_padding				= v0;
	//contextual button
	style->contextual_button.border				= 1;
	style->contextual_button.rounding			= 0;
	style->contextual_button.padding			= v1;
	style->contextual_button.image_padding			= v0;
	style->contextual_button.touch_padding			= v0;
	//menu button
	style->menu_button.border				= 0;					//Nuklearのメニューはフラットデザインなので、ボーダーもパディングも0にするのが正しい。
	style->menu_button.rounding				= 0;
	style->menu_button.padding				= v0;
	style->menu_button.image_padding			= v0;
	style->menu_button.touch_padding			= v0;
	//option toggle
	style->option.padding					= v1;					//外側の四角から内側の四角へのパディング
	style->option.touch_padding				= v0;
	style->option.spacing					= 1;					//外側の四角と右側のラベルの間のスペーシング
	style->option.border					= 0;					//0にすべし(?)
	//checkbox toggle
	style->checkbox.padding					= v1;					//外側の丸から内側の丸へのパディング
	style->checkbox.touch_padding				= v0;
	style->checkbox.spacing					= 1;					//外側の丸と右側のラベルの間のスペーシング
	style->checkbox.border					= 0;					//0にすべし(?)
	//selectable
	style->selectable.rounding				= 0;
	style->selectable.padding				= v1;					//外側の四角と内側のラベルの間のパディング。選択ボタンは左揃えなのでパディングが必要。
	style->selectable.touch_padding				= v0;
	style->selectable.image_padding				= v0;
	//slider
	style->slider.border					= 0;					//※参照されていない(?)
	style->slider.rounding					= 0;
	style->slider.bar_height				= 0;					//※参照されていない(?)
	style->slider.padding					= v0;					//0にすべし(?)。バーは上下センタリングされるから不要だし、パディングが大きいとバーのサイズが残らなくて消えてしまう事も有るから。
	style->slider.spacing					= v0;
	style->slider.cursor_size				= nk_vec2(5,5);
	style->slider.show_buttons				= nk_false;
	//progressbar
	style->progress.rounding				= 0;
	style->progress.border					= 0;					//0にすべし(?)
	style->progress.cursor_border				= 0;
	style->progress.cursor_rounding				= 0;
	style->progress.padding					= v1;					//外側の四角から内側の四角へのパディング
	//property
	style->property.border					= 0;					//0にすべし(?)
	style->property.rounding				= 0;
	style->property.padding					= v1;					//左側のボタンからラベル,及び,右側のボタンからエディットの間のパディング
	//property edit
	style->property.edit.border				= 0;					//0にすべし(?)
	style->property.edit.rounding				= 0;
	style->property.edit.cursor_size			= 2;					//※効果が良く判らない(?)
	style->property.edit.scrollbar_size			= v5;					//※効果が良く判らない(?)
	style->property.edit.padding				= v0;
	style->property.edit.row_padding			= 0;
	//property buttons
	style->property.inc_button.border			= 0;					//0にすべし(?)
	style->property.inc_button.rounding			= 0;
	style->property.inc_button.padding			= v0;
	style->property.inc_button.image_padding		= v0;
	style->property.inc_button.touch_padding		= v0;
	style->property.dec_button				= style->property.inc_button;		//コピー
	//edit
	style->edit.border					= 0;					//0にすべし(?)
	style->edit.rounding					= 0;
	style->edit.cursor_size					= 2;					//※効果が良く判らない(?)
	style->edit.scrollbar_size				= v5;
	style->edit.padding					= v1;					//エディット領域の外側から内側のテキストへのパディング。必要です。
	style->edit.row_padding					= 0;
	//edit scrollbar
	style->edit.scrollbar.border				= 0;					//0にすべし(?)
	style->edit.scrollbar.rounding				= 0;
	style->edit.scrollbar.border_cursor			= 0;
	style->edit.scrollbar.rounding_cursor			= 0;
	style->edit.scrollbar.padding				= v1;					//外側の四角から内側の四角へのパディング
	style->edit.scrollbar.show_buttons			= nk_false;				//上下のボタンは無くても困らないので表示しない事にした。
	//chart
	style->chart.border					= 1;					//1にすべし(?)
	style->chart.rounding					= 0;
	style->chart.padding					= v0;					//棒グラフの個々の棒の間のパディング。P/ECEは解像度が低いので(0,0)にするのが良い。(0,0)にしても1ピクセルぐらい間隔が空くみたい。もしかするとこのフィールドは棒の内側のパディングを示していて、棒と棒の間は常に1ピクセル空くのかもしれない。
	//scrollbars
	style->scrollh.border					= 0;					//0にすべし(?)
	style->scrollh.rounding					= 0;
	style->scrollh.border_cursor				= 0;
	style->scrollh.rounding_cursor				= 0;
	style->scrollh.padding					= v0;					//外側の四角から内側の四角へのパディング。0にすべし(?)。スクロールバーは、この行で指定するパディングを0にしても何故か暗黙のパディングが1ピクセル生じるようで、明示的なパディングも指定するとバーのサイズが残らなくて消えてしまう。(何故か横スクロールバーだけその問題が生じた)
	style->scrollh.show_buttons				= nk_false;				//上下のボタンは無くても困らないので表示しない事にした。
	style->scrollv						= style->scrollh;			//コピー
	//tab
	style->tab.border					= 1;					//1にすべし(?)
	style->tab.rounding					= 0;
	style->tab.indent					= 2;
	style->tab.padding					= v1;
	style->tab.spacing					= v0;
	//tab button
	style->tab.tab_minimize_button.border			= 0;					//0にすべし(?)
	style->tab.tab_minimize_button.rounding			= 0;
	style->tab.tab_minimize_button.padding			= v1;					//左端の三角ボタンのパディング。(0,0)にすると三角が大きすぎて見栄えが悪いので(1,1)が良い。
	style->tab.tab_minimize_button.image_padding		= v0;
	style->tab.tab_minimize_button.touch_padding		= v0;
	style->tab.tab_maximize_button				= style->tab.tab_minimize_button;	//コピー
	//node button
	style->tab.node_minimize_button.border			= 0;					//0にすべし(?)
	style->tab.node_minimize_button.rounding		= 0;
	style->tab.node_minimize_button.padding			= v1;					//左端の三角ボタンのパディング。(0,0)にすると三角が大きすぎて見栄えが悪いので(1,1)が良い。
	style->tab.node_minimize_button.image_padding		= v0;
	style->tab.node_minimize_button.touch_padding		= v0;
	style->tab.node_maximize_button				= style->tab.node_minimize_button;	//コピー
	//combo
	style->combo.border					= 1;					//1にすべし(?)
	style->combo.rounding					= 0;
	style->combo.content_padding				= v1;					//一行目のラベルのパディング。一行目のラベルは左揃えなのでパディングが必要。
	style->combo.button_padding				= v1;					//一行目の右端の三角ボタンのパディング。(0,0)にすると三角が大きすぎて見栄えが悪いので(1,1)が良い。	※style->combo.button_paddingとstyle->combo.button.paddingを両方設定しないと上手く表示されないみたい(?)
	style->combo.spacing					= v0;
	//combo button
	style->combo.button.border				= 0;
	style->combo.button.rounding				= 0;
	style->combo.button.padding				= v1;					//一行目の右端の三角ボタンのパディング。(0,0)にすると三角が大きすぎて見栄えが悪いので(1,1)が良い。	※style->combo.button_paddingとstyle->combo.button.paddingを両方設定しないと上手く表示されないみたい(?)
	style->combo.button.image_padding			= v0;
	style->combo.button.touch_padding			= v0;
	//window
	style->window.border					= 1;
	style->window.combo_border				= 1;
	style->window.contextual_border				= 1;
	style->window.menu_border				= 1;
	style->window.group_border				= 1;
	style->window.tooltip_border				= 1;
	style->window.popup_border				= 1;
	style->window.rounding					= 0;
	style->window.spacing					= v1;
	style->window.scrollbar_size				= v5;					//調整可
	style->window.min_size					= nk_vec2(16,16);			//調整可
	style->window.padding					= v1;
	style->window.group_padding				= v1;
	style->window.popup_padding				= v1;
	style->window.combo_padding				= v1;
	style->window.contextual_padding			= v1;
	style->window.menu_padding				= v1;
	style->window.tooltip_padding				= v1;
	//window header
	style->window.header.padding				= v1;
	style->window.header.label_padding			= v1;
	style->window.header.spacing				= v0;
	//window header close button
	style->window.header.close_button.border		= 0;					//最小化ボタンはテキストで表示されるのでボーダーやパディングはあまり関係ない。
	style->window.header.close_button.rounding		= 0;
	style->window.header.close_button.padding		= v0;
	style->window.header.close_button.image_padding		= v0;
	style->window.header.close_button.touch_padding		= v0;
	//window header minimize button
	style->window.header.minimize_button.border		= 0;					//最小化ボタンはテキストで表示されるのでボーダーやパディングはあまり関係ない。
	style->window.header.minimize_button.rounding		= 0;
	style->window.header.minimize_button.padding		= v0;
	style->window.header.minimize_button.image_padding	= v0;
	style->window.header.minimize_button.touch_padding	= v0;
}
/*--------------------------------------------------------------------------*/
//カーソルをロードする。
static void nk_piece_load_cursor(struct nk_context* ctx) {
	//'/clip/nuklear/keep/makefile'を使って'/clip/nuklear/keep/nk_custom_cursor_data-2m.bmp'を変換して生成しました。
	static const unsigned char NK_CUSTOM_CURSOR_DATA[] = {
	0x50,0x4d,0x42,0x50,0x4f,0x01,0x00,0x00,0x02,0x01,0x38,0x00,0x0f,0x00,0x00,0x00,0x3b,0x01,0x00,0x00,
	/*buf*/
	0x00,0x03,0xff,0x03,0x00,0x00,0x30,0x00,0x3f,0xf0,0x00,0x03,0xff,0x00,
	0x00,0x03,0x03,0x0c,0xc0,0x00,0xcc,0x00,0x30,0x30,0x00,0x03,0x03,0x00,
	0xc0,0x03,0xcf,0x30,0x30,0x03,0x03,0x00,0x30,0xc0,0x00,0x00,0xc3,0x00,
	0xf0,0x00,0xcc,0x3c,0xf0,0x03,0xcf,0x00,0x33,0x30,0x00,0x03,0x33,0x00,
	0xcc,0x00,0xcc,0x0c,0xc0,0x3c,0xcc,0xf0,0x3c,0xcc,0xf3,0xcc,0xcf,0x00,
	0xc3,0x00,0xcc,0x0c,0xc0,0xcf,0xcf,0xcc,0x00,0x33,0x33,0x33,0x00,0x00,
	0xc0,0xc3,0xcf,0x0c,0xc3,0x00,0x00,0x03,0x00,0x0c,0x33,0x0c,0x00,0x00,
	0xc0,0x33,0x03,0x0c,0xc0,0xcf,0xcf,0xcc,0x00,0x30,0x33,0x03,0x00,0x00,
	0xc0,0xf3,0xff,0x0c,0xc0,0x3c,0xcc,0xf0,0x00,0x3f,0xf3,0xff,0x00,0x00,
	0xcc,0xc0,0x00,0x3c,0xf0,0x03,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0xf3,0x30,0x00,0x30,0x30,0x03,0x03,0x00,0x03,0xc0,0x0f,0x00,0x00,0x00,
	0x03,0x30,0x00,0x0c,0xc0,0x00,0xcc,0x00,0x0c,0xff,0xfc,0xc0,0x00,0x00,
	0x00,0xc0,0x00,0x03,0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x30,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0xff,0xfc,0xc0,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xc0,0x0f,0x00,0x00,0x00,
	/*mask*/
	0x81,0xf1,0x00,0x40,0x7c,0x01,0xf0,
	0x01,0xf3,0x80,0xe0,0x7c,0x01,0xf0,
	0x81,0xf7,0xc1,0xf0,0x78,0x00,0xf0,
	0xc0,0xe7,0xc1,0xf0,0x7c,0x01,0xf0,
	0xe0,0xe3,0x86,0xec,0x6e,0xdb,0xb0,
	0xf0,0xe3,0x8f,0xfe,0x07,0xdf,0x00,
	0xf9,0xf3,0x9f,0xff,0x03,0xde,0x00,
	0xfd,0xf3,0x8f,0xfe,0x07,0xdf,0x00,
	0xfd,0xf3,0x86,0xec,0x07,0xdf,0x00,
	0xf8,0x07,0xc1,0xf0,0x00,0x00,0x00,
	0xdc,0x07,0xc1,0xf0,0x18,0x30,0x00,
	0x1c,0x03,0x80,0xe0,0x3f,0xf8,0x00,
	0x08,0x01,0x00,0x40,0x7f,0xfc,0x00,
	0x00,0x00,0x00,0x00,0x3f,0xf8,0x00,
	0x00,0x00,0x00,0x00,0x18,0x30,0x00,
	};
	//nuklear.hのnk_font_atlas_bake()を元にして作成しました。
	static const unsigned char nk_cursor_data[/*NK_CURSOR_COUNT*/][3/*Pos,Size,Offset*/][2/*x,y*/]={
	{{ 0, 2},{ 6,11},{ 0, 0}},	//NK_CURSOR_ARROW
	{{ 7, 0},{ 5, 9},{ 2, 4}},	//NK_CURSOR_TEXT
	{{19, 0},{13,13},{ 6, 6}},	//NK_CURSOR_MOVE
	{{13, 0},{ 5,13},{ 2, 6}},	//NK_CURSOR_RESIZE_VERTICAL
	{{33,10},{13, 5},{ 6, 2}},	//NK_CURSOR_RESIZE_HORIZONTAL
	{{43, 0},{ 9, 9},{ 4, 4}},	//NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT
	{{33, 0},{ 9, 9},{ 4, 4}}};	//NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT
	static_assert(((sizeof nk_cursor_data)/(sizeof nk_cursor_data[0])) == NK_CURSOR_COUNT, "nk_cursor_data[]の要素数が不正です。");
	static struct nk_cursor cursors[NK_CURSOR_COUNT]; /* カーソル定義の配列、ＳＴＡＴＩＣです！ */	//Nuklearのコンテキストはカーソル定義の配列をコピーせずにポインタで参照するので、staticとする必要が有る。複数インスタンスを作成した場合も、全てのインスタンスで共用出来ます。
	static TEXTURE texture; /* テクスチャ定義、ＳＴＡＴＩＣです！ */
	texture_init(&texture, NK_CUSTOM_CURSOR_DATA);	//忘れないで!!
	//カーソル定義の配列を初期化する。
	// - 当関数が複数回呼び出された場合(複数インスタンスに対してカーソルをロードした場合など)、カーソル定義の配列は共用するので、カーソル定義の配列を初期化する処理は最初の一回だけでも構わないのですが、実装を簡単にするために毎回初期化する事にしました。
	//   何度初期化しても結果は同じになりますし、リソースリークも発生しないし、また、当関数は頻繁に呼び出されるものではないので、多少無駄な処理を行っても性能の低下も問題とならないからです。
	{
		int i;
		for(i = 0; i < NK_CURSOR_COUNT; ++i) {
			int PosX		= nk_cursor_data[i][0][0];
			int PosY		= nk_cursor_data[i][0][1];
			int SizeX		= nk_cursor_data[i][1][0];
			int SizeY		= nk_cursor_data[i][1][1];
			int OffsetX		= nk_cursor_data[i][2][0];
			int OffsetY		= nk_cursor_data[i][2][1];
			cursors[i].img		= nk_subimage_ptr(&texture, SizeX, SizeY, nk_rect(PosX, PosY, SizeX, SizeY));
			cursors[i].size		= nk_vec2(SizeX, SizeY);
			cursors[i].offset	= nk_vec2(OffsetX, OffsetY);
		}
		nk_style_load_all_cursors(ctx, cursors);	//nk_style_load_all_cursors()が、nk_style_show_cursor()の効果も含んでいます。
	}
}
/*--------------------------------------------------------------------------*/
static void nk_piece_scissor(RENDER* render, int x, int y, int w, int h) {
	SURFACE* surface = render->surface;
	render->left   = clamp(x,     0, (int)surface->w);
	render->top    = clamp(y,     0, (int)surface->h);
	render->right  = clamp(x + w, 0, (int)surface->w);
	render->bottom = clamp(y + h, 0, (int)surface->h);
}
/*--------------------------------------------------------------------------*/
//現在の実装では、line_thickness引数を無視しています。
static void nk_piece_draw_line(RENDER* render, int x1, int y1, int x2, int y2, int line_thickness, struct nk_color col) {
	render_line(render,
		x1,
		y1,
		x2,
		y2,
		col.r);
}
/*--------------------------------------------------------------------------*/
//本当はベジェ曲線を描く必要が有るのですが、現在の実装では、始点(x1,y1),制御点(x2,y2),制御点(x3,y3),終点(x4,y4)を直線で結んでいます。
static void nk_piece_draw_curve(RENDER* render, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int line_thickness, struct nk_color col) {
	render_line(render,
		x1,
		y1,
		x2,
		y2,
		col.r);
	render_line(render,
		x2,
		y2,
		x3,
		y3,
		col.r);
	render_line(render,
		x3,
		y3,
		x4,
		y4,
		col.r);
}
/*--------------------------------------------------------------------------*/
//現在の実装では、rounding引数とline_thickness引数を無視しています。
static void nk_piece_draw_rect(RENDER* render, int x, int y, int w, int h, int rounding, int line_thickness, struct nk_color col) {
	render_rectangle(render,
		x,
		y,
		w,
		h,
		col.r);
}
/*--------------------------------------------------------------------------*/
//現在の実装では、rounding引数を無視しています。
static void nk_piece_draw_rect_filled(RENDER* render, int x, int y, int w, int h, int rounding, struct nk_color col) {
	render_rectangle_fill(render,
		x,
		y,
		w,
		h,
		col.r);
}
/*--------------------------------------------------------------------------*/
//本当はグラデーションで塗り潰した矩形を描く必要が有るのですが、現在の実装では、単色で塗り潰した矩形を描いています。
static void nk_piece_draw_rect_multi_color(RENDER* render, int x, int y, int w, int h, struct nk_color col1, struct nk_color col2, struct nk_color col3, struct nk_color col4) {
	nk_piece_draw_rect_filled(render,
		x,
		y,
		w,
		h,
		0,
		col1);
}
/*--------------------------------------------------------------------------*/
//現在の実装では、line_thickness引数を無視しています。
static void nk_piece_draw_circle(RENDER* render, int x, int y, int w, int h, int line_thickness, struct nk_color col) {
	render_ellipse(render,
		x,
		y,
		w,
		h,
		col.r);
}
/*--------------------------------------------------------------------------*/
static void nk_piece_draw_circle_filled(RENDER* render, int x, int y, int w, int h, struct nk_color col) {
	render_ellipse_fill(render,
		x,
		y,
		w,
		h,
		col.r);
}
/*--------------------------------------------------------------------------*/
//本当は円弧を描く必要が有るのですが、現在の実装では、全円を描いています。
static void nk_piece_draw_arc(RENDER* render, int cx, int cy, int r, float a1, float a2, int line_thickness, struct nk_color col) {
	nk_piece_draw_circle(render,
		cx - r,
		cy - r,
		r << 1,
		r << 1,
		line_thickness,
		col);
}
/*--------------------------------------------------------------------------*/
//本当は円弧を描く必要が有るのですが、現在の実装では、全円を描いています。
static void nk_piece_draw_arc_filled(RENDER* render, int cx, int cy, int r, float a1, float a2, struct nk_color col) {
	nk_piece_draw_circle_filled(render,
		cx - r,
		cy - r,
		r << 1,
		r << 1,
		col);
}
/*--------------------------------------------------------------------------*/
static void nk_piece_draw_triangle(RENDER* render, int x1, int y1, int x2, int y2, int x3, int y3, int line_thickness, struct nk_color col) {
	struct nk_vec2i points[3] = {
		{ x1, y1 },
		{ x2, y2 },
		{ x3, y3 }
	};
	nk_piece_draw_polygon(render,
		points,
		3,
		line_thickness,
		col);
}
/*--------------------------------------------------------------------------*/
static void nk_piece_draw_triangle_filled(RENDER* render, int x1, int y1, int x2, int y2, int x3, int y3, struct nk_color col) {
	struct nk_vec2i points[3] = {
		{ x1, y1 },
		{ x2, y2 },
		{ x3, y3 }
	};
	nk_piece_draw_polygon_filled(render,
		points,
		3,
		col);
}
/*--------------------------------------------------------------------------*/
//現在の実装では、line_thickness引数を無視しています。
static void nk_piece_draw_polygon(RENDER* render, const struct nk_vec2i* points, int point_count, int line_thickness, struct nk_color col) {
	vec2i v[16/*調整可*/];
	int i;
	if((unsigned)point_count > (unsigned)ARRAY_SIZE(v)) { DIE(); }
	for(i = 0; i < point_count; i++) {
		v[i].x = points[i].x;
		v[i].y = points[i].y;
	}
	render_vec2i_polygon(render,
		v,
		point_count,
		col.r);
}
/*--------------------------------------------------------------------------*/
static void nk_piece_draw_polygon_filled(RENDER* render, const struct nk_vec2i* points, int point_count, struct nk_color col) {
	vec2i v[16/*調整可*/];
	int i;
	if((unsigned)point_count > (unsigned)ARRAY_SIZE(v)) { DIE(); }
	for(i = 0; i < point_count; i++) {
		v[i].x = points[i].x;
		v[i].y = points[i].y;
	}
	render_vec2i_polygon_fill(render,
		v,
		point_count,
		col.r);
}
/*--------------------------------------------------------------------------*/
//現在の実装では、line_thickness引数を無視しています。
static void nk_piece_draw_polyline(RENDER* render, const struct nk_vec2i* points, int point_count, int line_thickness, struct nk_color col) {
	int i;
	for(i = 0; i < (point_count - 1); i++) {
		render_line(render,
			points[i + 0].x,
			points[i + 0].y,
			points[i + 1].x,
			points[i + 1].y,
			col.r);
	}
}
/*--------------------------------------------------------------------------*/
static void nk_piece_draw_text(RENDER* render, int x, int y, int w, int h, const char* string, int len, const struct nk_user_font* font, struct nk_color bg, struct nk_color fg) {
	int type = font->userdata.id;
#if 0
	//'nuklear-master/demo/〜'の各レンダリングバックエンドのソースから推測するに、Nuklearの仕様上は常に文字列の背景を塗り潰すのが正しいようなのだが、
	//背景色が半透明の場合に背景色を塗り潰すと、ウインドウの背景と文字列の背景で半透明色が二重に塗られてしまい、見た目に不自然な描画結果になる。
	//実際の所、文字列の背景色は常にウインドウの背景色と同じであるようだから、文字列の背景を塗り潰す必要は無いと思う。
	//その上、当関数の引数w,hは、文字列の高さよりもかなり小さいサイズが指定されるようで、塗り潰す範囲が文字列と合っていない。
	//以上の理由により、引数w,h,及び,bgは無視して、文字列を塗り潰す処理は行わない事にした。
	render_rectangle_fill(render,
		x,
		y,
		w,
		h,
		bg.r);
#endif
	render_printf(render,
		x,
		y,
		type,
		fg.r,
		"%.*s", len, string);
}
/*--------------------------------------------------------------------------*/
//本当は描画するイメージのサイズとw,h引数で指定されたサイズが異なる場合は拡大縮小して描く必要が有るのですが、現在の実装ではw,h引数を無視して拡大縮小無しで描いています。
static void nk_piece_draw_image(RENDER* render, int x, int y, int w, int h, const struct nk_image* img, struct nk_color col) {
	int sx, sy, sw, sh;
	TEXTURE* texture = img->handle.ptr;
	TEXTURE* texture_save = render->context->texture;
	render->context->texture = texture;
	//サブイメージでなければ…
	if(!nk_image_is_subimage(img)) {
		sx = 0;
		sy = 0;
		sw = texture->header.w;
		sh = texture->header.h;
	//サブイメージならば…
	} else {
		sx = img->region[0/*x*/];
		sy = img->region[1/*y*/];
		sw = img->region[2/*w*/];
		sh = img->region[3/*h*/];
	}
	render_object(render, x, y, sx, sy, sw, sh, DRW_NOMAL);
	render->context->texture = texture_save;
}
/*--------------------------------------------------------------------------*/
static float nk_piecefont_get_text_width(nk_handle handle, float height, const char* text, int len) {
	int type = handle.id;
	return (short)render_printf(&null_render, 0, 0, type, 0, "%.*s", len, text);
}
