/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

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


#ifndef ___R64_TYPES_H___
#define ___R64_TYPES_H___

#define ENT_UNIT	64
#define ENT_LEN_DEFAULT	(2048/ENT_UNIT*10)
#define ENT_LEN		ent_len
#define LEVEL_OFS_LEN	32

#define CR_TH		32
#define CR_LIMIT	300

typedef struct r64_header {
	char		preamble[3];
	char		type;
	short		width;
	short		height;
} R64_HEADER;

typedef struct r64_cache_ent {
	struct r64_cache_ent * next;
	struct r64_cache_ent * prev;
	int		flags;
#define EF_DIRTY	0x00000001
	char *		buf;
	int		w_ofs;
	int		h_ofs;
	char		w_len;
	char		h_len;
	char		level;
} R64_CACHE_ENT;

typedef struct r64_file {
	int		fd;
	int		fctl;
	R64_HEADER	header;
	struct r64_cache_ent *free_list;
	R64_CACHE_ENT	cache[ENT_LEN_DEFAULT];
	unsigned int	level_ofs[LEVEL_OFS_LEN];
	int		level_w[LEVEL_OFS_LEN];
	int		level_h[LEVEL_OFS_LEN];
	char		background[3];
	char		rc_type;
} R64_FILE;


typedef struct cr_header {
	R64_HEADER	h;
	unsigned short	rect_size;
		/* rect_size = 64 128 256 */
	unsigned char	dummy[2];
	unsigned int	cr_tbl_nos;
} CR_HEADER;

typedef struct cr_tbl {
	unsigned int	ofs;
	char		type;
	/*
		'n'	: non compress
		'j'	: jpeg
		'g'	: gif
	*/
	unsigned char	cal[3];
		/* calibration */
	unsigned int	size;
} CR_TBL;

typedef struct cr_mem_tbl {
	unsigned char *	buf;
	char		type;
	unsigned char	cal[3];
	unsigned int	size;
} CR_MEM_TBL;


typedef struct cr_ent {
	struct cr_ent *	next;
	struct cr_ent * prev;
	CR_MEM_TBL	b;
	int		w_ofs;
	int		h_ofs;
	char		w_len;
	char		h_len;
	char		level;
} CR_ENT;

typedef struct cr_file {
	int		fd;
	int		fctl;
	CR_HEADER	header;
	struct cr_ent *	free_list;
	CR_ENT		cache[ENT_LEN_DEFAULT];
	int		level_entry[LEVEL_OFS_LEN];
	int		level_w[LEVEL_OFS_LEN];
	int		level_h[LEVEL_OFS_LEN];
	unsigned int	write_ofs;
} CR_FILE;

extern int r64_error;
extern int ent_len;

#define UNIT_VOL(f) \
	( (f)->header.type == 'B' ?	ENT_UNIT*ENT_UNIT/8 : \
	( (f)->header.type == 'G' ?	ENT_UNIT*ENT_UNIT : \
	( (f)->header.type == 'P' ?	ENT_UNIT*ENT_UNIT*3 : 0 )))
#define EUP(x) ( ((x)%8) ? ((x)-((x)%8))/8+1 : (x)/8 )
#define ENT_VOL(f,ce) \
	( (f)->header.type == 'B' ?	EUP(ce->w_len)*ce->h_len : \
	( (f)->header.type == 'G' ?	(ce)->w_len*(ce)->h_len : \
	( (f)->header.type == 'P' ?	(ce)->w_len*(ce)->h_len*3 : 0 )))
#define ENT_VOL2(f,ce) \
	( (f)->header.type == 'B' ?	EUP(ENT_UNIT)*ce->h_len : \
	( (f)->header.type == 'G' ?	ENT_UNIT*(ce)->h_len : \
	( (f)->header.type == 'P' ?	ENT_UNIT*(ce)->h_len*3 : 0 )))
#define ENT_UNIT_VOL(f) \
	( (f)->header.type == 'B' ?	1 : \
	( (f)->header.type == 'G' ?	1 : \
	( (f)->header.type == 'P' ?	3 : 0 )))
#define FILE_LINES(f,ce) \
	( (f)->header.type == 'B' ?		\
		(((f)->header.width%8) ? 	\
			((f)->level_w[ce->level]>>3)+1 :	\
			((f)->level_w[ce->level]>>3))* \
			(ce)->h_ofs : \
	( (f)->header.type == 'G' ?	\
		(ce)->h_ofs * (f)->level_w[ce->level] : \
	( (f)->header.type == 'P' ?	\
		(ce)->h_ofs * (f)->level_w[ce->level]*3 : \
		0 )))
#define CH_OFS2_FILE_IN_LEVEL(f,ce) \
	(FILE_LINES(f,ce) + \
	(ce)->w_ofs/ENT_UNIT*ENT_VOL2(f,ce))
#define CH_OFS2_FILE(f,ce) \
	((f)->level_ofs[ce->level] + CH_OFS2_FILE_IN_LEVEL(f,ce))
#define BIT_OFS_IN_CH(f,ce,w,h) \
	((((h) - (ce)->h_ofs)*(ce)->w_len + \
	(w) - (ce)->w_ofs)*ENT_UNIT_VOL(f))

#endif
