/*$
apdtool
Copyright (c) 2020 Azel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
$*/

/*****************************
 * 各定義
 *****************************/

#define IS_PROC_BLEND   (g_work.proctype == PROCTYPE_BLEND)
#define IS_PROC_LAYER   (g_work.proctype == PROCTYPE_LAYER)
#define IS_PROC_INFO    (g_work.proctype == PROCTYPE_INFO)
#define ISNOT_PROC_INFO  (g_work.proctype != PROCTYPE_INFO)

typedef struct _TexItem TexItem;


/* 作業用データ */

typedef struct
{
	mBuf bufName;		//レイヤ名・テクスチャ名格納バッファ
	mList listTexture,	//テクスチャイメージリスト
		listTexPath;	//テクスチャパスリスト (レイヤテクスチャ色変換用)

	mStr strInputFile,	//入力ファイル名
		strOutput,		//出力ファイル名 or ディレクトリ (空でカレントディレクトリ)
		strLayerPrefix,	//レイヤ抽出の出力ファイル名接頭語 (空で元ファイル名)
		strLayerTex,	//レイヤテクスチャのテキストファイル名
		strTexPathSys,	//テクスチャパス (システム)
		strTexPathUser;	//テクスチャパス (ユーザー)

	int format,			//画像出力フォーマット
		proctype,		//処理タイプ
		src_dpi;		//元ファイルのDPI (0 でなし)
	uint32_t flags;

	uint8_t *layerno_flags;	//抽出レイヤ番号のフラグ (NULL で指定なし)
	int layerno_num;		//抽出レイヤ番号の数
}WorkData;

/* レイヤデータ */

typedef struct
{
	const char *name,	//レイヤ名 (NULL で空文字列)
		*texpath;		//レイヤテクスチャパス名 (NULL でなし)
	TexItem *texitem;	//テクスチャイメージアイテム
	
	off_t fpos;			//イメージのファイル位置
	int32_t offx,offy;
	uint32_t imgparam,	//全体の圧縮サイズ,タイル数
		imgparam2,
		col;
	uint16_t parent,	//親のレイヤ番号 (0xffff でルート)
		tilew,tileh;
	uint8_t coltype,
		blendmode,
		opacity,
		flags;
}LayerData;

/*---------------*/

enum
{
	FORMAT_PNG,
	FORMAT_BMP,
	FORMAT_PSD,
};

enum
{
	FLAGS_IMAGE_TO_GRAY = 1<<0,		//合成画像をグレイスケールで出力
	FLAGS_IMAGE_TO_MONO = 1<<1,		//合成画像を1bitモノクロで出力
	FLAGS_LAYERTEX_LIST = 1<<2,		//レイヤテクスチャパスをテキストに出力 (INFO 時)
	FLAGS_LAYERTEX_TO_COL = 1<<3,	//A16/A1 のレイヤテクスチャをグレイスケール変換
	FLAGS_LAYER_NO_TEXTURE = 1<<4,	//レイヤ出力時、テクスチャを適用しない
	FLAGS_HAVE_LAYER_PREFIX = 1<<5,	//レイヤ出力接頭語あり

	FLAGS_OUTPUT_DIR = 1<<16	//--output が既存のディレクトリなら ON
};

/* 処理タイプ */

enum
{
	PROCTYPE_BLEND,		//合成絵を出力
	PROCTYPE_LAYER,		//レイヤを出力
	PROCTYPE_INFO		//情報表示
};

/* レイヤフラグ */

enum
{
	LAYER_FLAGS_HIDE = 1<<0,	//非表示
	LAYER_FLAGS_FOLDER = 1<<1	//フォルダ
};

/* 合成モード */

enum
{
	BLENDMODE_NORMAL,
	BLENDMODE_MUL,
	BLENDMODE_ADD,
	BLENDMODE_SUB,
	BLENDMODE_SCREEN,
	BLENDMODE_OVERLAY,
	BLENDMODE_HARD_LIGHT,
	BLENDMODE_SOFT_LIGHT,
	BLENDMODE_DODGE,
	BLENDMODE_BURN,
	BLENDMODE_LINEAR_BURN,
	BLENDMODE_VIVID_LIGHT,
	BLENDMODE_LINEAR_LIGHT,
	BLENDMODE_PIN_LIGHT,
	BLENDMODE_DARKER,
	BLENDMODE_LIGHTEN,
	BLENDMODE_DIFF,
	BLENDMODE_LUM_ADD,
	BLENDMODE_LUM_DODGE,

	BLENDMODE_LUM_SUB,

	BLENDMODE_HUE,
	BLENDMODE_SATURATION,
	BLENDMODE_COLOR,
	BLENDMODE_LUM,

	BLENDMODE_NUM,
	BLENDMODE_APDv3_LAST = BLENDMODE_LUM_DODGE
};

/*------------*/

extern WorkData g_work;

/*------------*/

typedef mlkerr (*func_read_layerimage)(LayerData *pl,void *ptr);
typedef mlkerr (*func_blend_layer)(mImageBuf2 *img,LayerData *pl,int opacity,void *ptr);
typedef void (*func_set_tileimage)(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,uint32_t col,TexItem *tex);
typedef void (*func_blendtile)(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,int mode,int opacity,uint32_t col,TexItem *tex);

/* main.c */

void exit_app(int ret);
void puterr_exit(const char *fmt,...);
void put_progress_char(void);
void put_layerinfo(LayerData *p,int layernum);
void put_layerinfo_texpath(LayerData *buf,int layernum);

const char *add_name_utf8(const char *name,int len);
const char *add_name_checkcode(void *buf,int len);
int get_layernum_dig(int num);

mlkerr output_layers(mImageBuf2 *img,LayerData *layer,int layernum,func_read_layerimage readimg,void *ptr);
mlkerr output_blendimage8(int width,int height,mImageBuf2 *imglayer,LayerData *layer,int layernum,
	func_read_layerimage readimage,void *ptr);
mlkerr output_blendimage_tile(int width,int height,LayerData *layer,int layernum,
	func_blend_layer blendimage,void *ptr,int imgbits);
void read_layertexture(LayerData *layer,int layernum);

/* image.c */

void image_fill_zero(mImageBuf2 *p);
void image_fill_white(mImageBuf2 *p);
void image_fill_white16(mImageBuf2 *p);
void image_convert_16to8(mImageBuf2 *p);

void set_tileimage_rgba16(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,uint32_t col,TexItem *tex);
void set_tileimage_graya16(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,uint32_t col,TexItem *tex);
void set_tileimage_a16(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,uint32_t col,TexItem *tex);
void set_tileimage_a1(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,uint32_t col,TexItem *tex);
void set_tileimage_rgba8(mImageBuf2 *p,uint8_t *tilebuf,int x,int y,uint32_t col,TexItem *tex);

void write_image_blend(mImageBuf2 *img);
void write_image_layer(mImageBuf2 *img,int no,int dig);

/* blend8.c */

void blendimage_8bit(mImageBuf2 *imgdst,mImageBuf2 *imgsrc,int mode,int alpha);
void blendtile_rgba8(mImageBuf2 *img,uint8_t *tilebuf,int x,int y,int mode,int opacity,uint32_t col,TexItem *tex);

/* blend16.c */

void blendtile_rgba16(mImageBuf2 *img,uint8_t *tilebuf,int x,int y,int mode,int opacity,uint32_t col,TexItem *tex);
void blendtile_graya16(mImageBuf2 *img,uint8_t *tilebuf,int x,int y,int mode,int opacity,uint32_t col,TexItem *tex);
void blendtile_a16(mImageBuf2 *img,uint8_t *tilebuf,int x,int y,int mode,int opacity,uint32_t col,TexItem *tex);
void blendtile_a1(mImageBuf2 *img,uint8_t *tilebuf,int x,int y,int mode,int opacity,uint32_t col,TexItem *tex);

/* texture.c */

void TextureList_init(mList *list);
TexItem *TextureList_load(mList *list,const char *path);
uint8_t TextureItem_getOpacity(TexItem *pi,int x,int y);

void TexturePathList_init(mList *list);
void TexturePathList_add(mList *list,const char *path,uint32_t col);
int TexturePathList_getColor(mList *list,const char *path);
void TexturePathList_output(mList *list,const char *filename);
void TexturePathList_readFile(mList *list,const char *filename);
