/*
 *			GPAC - MPEG-4 Systems C Development Kit
 *
 *			Copyright (c) Jean Le Feuvre 2000-2005
 *					All rights reserved
 *
 *  This file is part of GPAC / software 2D rasterizer plugin
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  GPAC 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.  See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 *
 *	Most of this module is a C code rewrite of the charcoal lib (mupdf)
 *	written by Tor Andersson <tor.andersson@dsek.lth.se> published under the GPL license
 *		
 */


#ifndef _M4_REND_H_
#define _M4_REND_H_

#include <gpac/m4_raster2d.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _m4_surface M4Surface;

/*base stencil stack*/
#define M4BASESTENCIL	\
	u32 type;	\
	void (*fill_run)(struct _m4_base_stencil *p, M4Surface *surf, s32 x, s32 y, u32 count);	\
	M4Matrix2D pmat;					\
	M4Matrix2D smat;					\
	M4Rect frame;					\

typedef struct _m4_base_stencil
{
	M4BASESTENCIL
} M4Stencil;


/*16 k of pool buffer for FreeType raster - min is 4k*/
#define M4_FT_POOL_SIZE		16318


/*FreeType redefined*/
typedef struct
{
	s32 x;
	s32 y;
} M4_Vector;

typedef struct 
{
	s32 xMin, yMin;
	s32 xMax, yMax;
} M4_BBox;


typedef struct
{
	s16 n_contours;
	s16 n_points;
	M4_Vector *points;
	u8 *tags;
	s16 *contours;
	s32 flags; /*same as path flags*/
} M4_Outline;

typedef struct TRaster_ *M4_Raster;

typedef struct M4_Span_
{
	short           x;
	unsigned short  len;
	unsigned char   coverage;
} M4_Span;

typedef void (*M4_SpanFunc)(int y, int count, M4_Span *spans, void *user);
#define M4_Raster_Span_Func  M4_SpanFunc

typedef struct M4_Raster_Params_
{
	M4_Outline *source;
	M4_SpanFunc gray_spans;
	M4_BBox clip_box;
	void *user;
} M4_Raster_Params;


int m4_gray_raster_new(void *memory, M4_Raster *out_new_raster);
void m4_gray_raster_done(M4_Raster raster);
void m4_gray_raster_reset(M4_Raster raster, const char *pool_base, long pool_size);
int m4_gray_raster_render(M4_Raster raster, M4_Raster_Params *params);


/*the surface object - currently only ARGB/RGB32, RGB/BGR and RGB555/RGB565 supported*/
struct _m4_surface
{
	/*surface info*/
	char *pixels;
	u32 pixelFormat, BPP;
	u32 width, height, stride;
	Bool center_coords;

	/*color buffer for variable stencils - size of width*/
	u32 *stencil_pix_run;

	/*aliasing flag (on/off only)*/
	u8 AALevel;
	/*default texture filter level*/
	u32 texture_filter;

	u32 useClipper;
	M4IRect clipper;

	M4Rect path_bounds;

	/*complete path transform (including page flipping/recenter)*/
	M4Matrix2D mat;

	/*stencil currently used*/
	M4Stencil *sten;

	void *raster_cbk;
	/*fills line pixels without any blending operation*/
	void (*raster_fill_run_no_alpha)(void *cbk, u32 x, u32 y, u32 run_h_len, M4Color color);
	/*fills line pixels without blending operation - alpha combines both fill color and anti-aliasing blending*/
	void (*raster_fill_run_alpha)(void *cbk, u32 x, u32 y, u32 run_h_len, M4Color color, u32 alpha);


	/*in solid color mode to speed things*/
	u32 fill_col;
	u32 fill_565;
	u32 fill_555;

	/*FreeType outline (path converted to ft)*/
	M4_Outline ftoutline;
	M4_Raster_Params ftparams;
	u32 pointlen;
	u32 contourlen;
	M4_Vector *points;
	s8 *tags;
	s16 *contours;

	/*FreeType raster and pool size*/
	char raster_pool[M4_FT_POOL_SIZE];
	void *ftrast_mem;
	M4_Raster ftraster;
};

/*solid color brush*/
typedef struct
{
	M4BASESTENCIL
	M4Color color;
} M4Brush;

/*max number of interpolation points*/
#define M4GRADIENTSLOTS		12

/*(2^M4GRADIENTBITS)-1 colors in gradient. Below 6 bits the gradient is crappy */
#define M4GRADIENTBITS		10

/*scale factor for linear - MUST BE greater than M4GRADIENTBITS. 12 should be enough for decent results in both fixed point and float versions*/
#define M4GRADIENTSCALEBITS		12

/*base gradient stencil*/
#define M4GRADIENT	\
		s32	mod;	\
		u32	pre[(1<<M4GRADIENTBITS)];	\
		u32	col[M4GRADIENTSLOTS];		\
		Fixed pos[M4GRADIENTSLOTS];	\

typedef struct
{
	M4BASESTENCIL
	M4GRADIENT
} M4BaseGradient;

/*linear gradient*/
typedef struct
{
	M4BASESTENCIL
	M4GRADIENT
	
	M4Point2D start, end;
	M4Matrix2D vecmat;
	s32	curp;
	Fixed pos_ft;
} M4LinearGradient;

/*radial gradient*/
typedef struct
{
	M4BASESTENCIL
	M4GRADIENT
	
	M4Point2D center, focus, radius;
	/*drawing state vars*/
	M4Point2D cur_p, d_f, d_i;
	Fixed rad;
} M4RadialGradient;

/*texture stencil - should be reworked, is very slow*/
typedef struct
{
	M4BASESTENCIL
	u32 width, height, stride;
	u32 pixel_format, Bpp;
	char *pixels;

	M4Point2D cur_pt;
	Fixed cur_y, inc_x, inc_y;

	u32 mod, filter;
	M4ColorMatrix cmat;
	u32 replace_col;
	Bool cmat_is_replace;

	u8 alpha;

	/*YUV->RGB local buffer*/
	unsigned char *conv_buf;
	u32 conv_size;
	unsigned char *orig_buf;
	u32 orig_stride, orig_format;
	Bool is_converted;

	Bool owns_texture;

	u32 (*tx_get_pixel)(char *pix);
} M4Texture;

#define M4_TEXTURE_FILTER_DEFAULT	M4_TEXTURE_FILTER_HIGH_SPEED


void m4_radial_init(M4RadialGradient *_this) ;
void bmp_init(M4Stencil *p);
void m4_set_texture_active(M4Stencil *st);


LPM4STENCIL m4_stencil_new(Raster2D *, M4StencilType type);
void m4_stencil_delete(LPM4STENCIL st);
M4Err m4_stencil_set_matrix(LPM4STENCIL st, M4Matrix2D *mx);
M4Err m4_stencil_set_brush_color(LPM4STENCIL st, M4Color c);
M4Err m4_stencil_set_linear_gradient(LPM4STENCIL st, Fixed start_x, Fixed start_y, Fixed end_x, Fixed end_y, M4Color start_col, M4Color end_col);
M4Err m4_stencil_set_radial_gradient(LPM4STENCIL st, Fixed cx, Fixed cy, Fixed fx, Fixed fy, Fixed x_radius, Fixed y_radius);
M4Err m4_stencil_set_gradient_interpolation(LPM4STENCIL p, Fixed *pos, M4Color *col, u32 count);
M4Err m4_stencil_set_gradient_mode(LPM4STENCIL p, M4GradientMode mode);

/*texture only*/
M4Err m4_stencil_set_texture(LPM4STENCIL st, unsigned char *pixels, u32 width, u32 height, u32 stride, M4PixelFormat pixelFormat, M4PixelFormat destination_format_hint, Bool no_copy);
M4Err m4_stencil_set_tiling(LPM4STENCIL st, M4TextureTiling mode);
M4Err m4_stencil_set_filter(LPM4STENCIL st, M4TextureFilter filter_mode);
M4Err m4_stencil_set_color_matrix(LPM4STENCIL st, M4ColorMatrix *cmat);
M4Err m4_stencil_reset_color_matrix(LPM4STENCIL st);
M4Err m4_stencil_set_texture_alpha(LPM4STENCIL st, u8 alpha);
M4Err m4_stencil_create_texture(LPM4STENCIL st, u32 width, u32 height, M4PixelFormat pixelFormat);



LPM4SURFACE m4_surface_new(Raster2D *, Bool center_coords);
void m4_surface_delete(LPM4SURFACE _this);
void m4_surface_detach(LPM4SURFACE _this);
M4Err m4_surface_attach_to_buffer(LPM4SURFACE _this, unsigned char *pixels, u32 width, u32 height, u32 stride, M4PixelFormat pixelFormat);
M4Err m4_surface_attach_to_texture(LPM4SURFACE _this, LPM4STENCIL sten);
M4Err m4_surface_attach_to_callbacks(LPM4SURFACE _this, M4RasterCallback *callbacks, u32 width, u32 height);

M4Err m4_surface_set_matrix(LPM4SURFACE surf, M4Matrix2D *mat);
M4Err m4_surface_set_raster_level(LPM4SURFACE surf , M4RasterLevel RasterSetting);
M4Err m4_surface_set_clipper(LPM4SURFACE surf, M4IRect *rc);
M4Err m4_surface_set_path(LPM4SURFACE surf, M4Path *gp);
M4Err m4_surface_fill(LPM4SURFACE surf, LPM4STENCIL stencil);
M4Err m4_surface_clear(LPM4SURFACE surf, M4IRect *rc, u32 color);


/*FT raster callbacks - it's better to have a bit bigger code than using extra 
get/set pixels routines on the surface*/
void m4_argb_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_argb_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_argb_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_argb(LPM4SURFACE surf, M4IRect rc, M4Color col);

void m4_rgb32_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_rgb32_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_rgb32_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_rgb32(LPM4SURFACE surf, M4IRect rc, M4Color col);

void m4_rgb_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_rgb_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_rgb_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_rgb(LPM4SURFACE surf, M4IRect rc, M4Color col);

void m4_bgr_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_bgr_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_bgr_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_bgr(LPM4SURFACE surf, M4IRect rc, M4Color col);

void m4_565_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_565_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_565_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_565(LPM4SURFACE _this, M4IRect rc, M4Color col);

void m4_555_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_555_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_555_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_555(LPM4SURFACE surf, M4IRect rc, M4Color col);

void m4_user_fill_const(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_user_fill_const_a(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
void m4_user_fill_var(s32 y, s32 count, M4_Span *spans, M4Surface *surf);
M4Err m4_surface_clear_user(LPM4SURFACE surf, M4IRect rc, M4Color col);




#ifdef __cplusplus
}
#endif

#endif 

