/* GnarlPlot sprite header V0.38 22/2/08
   Copyright 2008 Jeffrey Lee
   This file is part of GnarlPlot.
   GnarlPlot 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 3 of the License, or
   (at your option) any later version.
   GnarlPlot 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 GnarlPlot.  If not, see <http://www.gnu.org/licenses/>. */

#ifndef _GP_SPR_H
#define _GP_SPR_H

#include <stdio.h>

#include "screen.h"
#include "/WoumInclude:lib/fixmath.h"

/*
				SPR.C
*/

struct _gp_sprfmt;

/* Sprite structure
   A sprite is a pointer to its format information, and a pointer to its data
   block
*/
typedef struct {
	struct _gp_sprfmt *f;
	void *d;
} gp_spr;

/* Sprite format information structure
   Contains a list of functions for each of the operations possible on a sprite
*/
typedef struct _gp_sprfmt {
	gp_spr *(*create)(struct _gp_sprfmt *f,int w,int h,int ox,int oy); /* Create new sprite */
	gp_spr *(*fromscreen)(struct _gp_sprfmt *f,gp_screen *s,int x,int y,int w,int h,int ox,int oy); /* Create new sprite from a screen */
	gp_spr *(*fromspr)(struct _gp_sprfmt *f,gp_spr *s,int x,int y,int w,int h,int ox,int oy); /* Make a new sprite as a copy of 's' */
	void (*delete)(gp_spr *s); /* Delete sprite */
	int (*getsize)(gp_spr *s); /* Return size of s->d, in bytes */
	int (*getps)(gp_spr *s); /* Return internal/best match pixel size */
	int (*getmt)(gp_spr *s); /* Return internal/best match mask type */
	int (*getw)(gp_spr *s); /* Return width of sprite, in pixels */
	int (*geth)(gp_spr *s); /* Return height of sprite, in pixels */
	int (*getox)(gp_spr *s); /* Return X coordinate of sprite origin, in pixels */
	int (*getoy)(gp_spr *s); /* Return Y coordinate of sprite origin, in pixels */
	int (*getpix)(gp_spr *s,int x,int y,int ps); /* Return a sprite pixel, in a specified format. 0,0 is top left. */
	int (*getmask)(gp_spr *s,int x,int y,int mt,int ps); /* Return the mask of a pixel, in a specified format. 0,0 is top left. */
	int (*setw)(gp_spr *s,int w); /* Set width of sprite to w pixels. !0 on failure */
	int (*seth)(gp_spr *s,int h); /* Set height of sprite to h pixels. !0 on failure */
	int (*setox)(gp_spr *s,int ox); /* Set origin X coordinate to ox pixels. !0 on failure */
	int (*setoy)(gp_spr *s,int oy); /* Set origin Y coordinate to oy pixels. !0 on failure */
	int (*setpix)(gp_spr *s,int x,int y,int ps,int c); /* Set pixel at x,y to colour c (format ps). 0,0 is top left. !0 on failure. */
	int (*setmask)(gp_spr *s,int x,int y,int mt,int ps,int c); /* Set pixel mask at x,y, to value c (format ps). 0,0 is top left. !0 on failure. */
	int (*plot)(gp_spr *s,int x,int y,gp_screen *scr); /* Plot sprite to screen at coordinates x,y. Sprite will be plotted relative to the sprite origin. !0 on failure */
	gp_screen *(*toscreen)(gp_spr *s,gp_screen *scr); /* Convert to a screen, if possible. Uses 'scr' if given, else allocates a new gp_screen using malloc. */
	int (*tplot)(gp_spr *s,int x,int y,gp_screen *scr,int l,f1616 sx,f1616 sy,f1616 xd,f1616 yd); /* Plot transformed row onto the screen, taken from an arbitrary line through a sprite. !0 on failure */
} gp_sprfmt;

/* Handy sprite op macro */
#define _GP_SPROP(Op,Spr,Args...) ((Spr)->f->Op)(Spr,##Args)
#define GP_SPROP(Op,Args...) _GP_SPROP(Op,Args)

/* Generic sprite functions */
extern gp_spr *gp_spr_gen_fromscreen(gp_sprfmt *f,gp_screen *s,int x,int y,int w,int h,int ox,int oy); /* Create a sprite from a screen. First creates a blank sprite then copies the pixels one by one */
extern gp_spr *gp_spr_gen_fromspr(gp_sprfmt *f,gp_spr *s,int x,int y,int w,int h,int ox,int oy); /* Create a sprite from a sprite. First creates a blank sprite then copies the pixels one by one */
extern void gp_spr_gen_delete(gp_spr *s); /* Deletes a sprite; free()'s s->d (if it exists), then s itself */

extern int gp_spr_gen_setw(gp_spr *s,int w); /* These functions are wrappers */
extern int gp_spr_gen_seth(gp_spr *s,int h); /* to s->f->fromspr, which create*/
extern int gp_spr_gen_setox(gp_spr *s,int ox); /* a new sprite from s but with*/
extern int gp_spr_gen_setoy(gp_spr *s,int oy); /* modified values, and then */
						/* modify s to point to it */

extern int gp_spr_gen_plot(gp_spr *s,int x,int y,gp_screen *scr); /* Plots the sprite to the screen pixel by pixel. The sprite will be plotted relative to its origin. */
extern int gp_spr_gen_tplot(gp_spr *s,int x,int y,gp_screen *scr,int l,f1616 sx,f1616 sy,f1616 dx,f1616 dy); /* Plots part of the sprite to a row of the screen pixel by pixel */

extern int gp_spr_save(gp_spr *s,FILE *f); /* Save the sprite's data block to a certain file. Returns !0 on failure, file ptr may be corrupt */
extern gp_spr *gp_spr_load(gp_sprfmt *fmt,FILE *f); /* Load a sprite's data block from a file, and create a new sprite based around it. Returns 0 on failure, file ptr status may be corrupt */

/* Array functions */
extern void gp_spr_ar_delete(gp_spr **s,int n); /* Delete all 'n' sprites in array 's', and then s itself. Null entries are ignored. */
extern gp_spr **gp_spr_ar_convert(gp_spr **s,int n,gp_sprfmt *f,gp_spr **d); /* Convert an array of 'n' sprites 's' to format 'f', storing them in array 'd'. If d is null, an array will be allocated for you. If d is s, the source sprites will be deleted as they are converted and array s overwritten. Returns 0 on failure, else the new sprite array. If an individual sprite fails to convert, a null pointer will be placed in its array entry. Null entries are left as nulls in the new array. */

/* Rot/scale plotter */
extern int gp_spr_plot_rotscale(gp_spr *s,int x,int y,gp_screen *scr,f1616 dx,f1616 dy); /* Plot a rotated/scaled sprite to the screen. The sprite's centre will be at x,y, and will be drawn with the sprite-per-screen-x delta (dx,dy). This means that the sprite-per-screen-y delta is (-dy,dx). This allows the sprites which are rotated or scaled (with equal X and Y scale factors) to be plotted. Returns !0 on failure */

extern char *gp_spr_mouseptr(gp_spr *s,int cols[3]); /* Convert 's' to a pointer definition suitable for supplying to OS_Word 21. The data returned contains the R1 parameter block and pointer definition, in the one malloc block. The user can then set byte 1 to the shape number and pass the block to OS_Word 21. cols[] contains the three (24bpp) colours to extract from the sprite and use in the pointer definition. Any other colours, and all transparent pixels, will be set to the transparent colour. The active point is taken from the sprite origin. Returns 0 on failure. */

/*
				SIMPSPR.C
*/

/* Standard sprite formats */
/* Number codes are <pixel size><mask format> */
extern gp_sprfmt gp_spr_00, gp_spr_10, gp_spr_20;
extern gp_sprfmt gp_spr_01, gp_spr_11, gp_spr_21;
extern gp_sprfmt gp_spr_02, gp_spr_12, gp_spr_22;
extern gp_sprfmt gp_spr_03, gp_spr_13, gp_spr_23;

/* Preshifted sprite formats */
/* Number codes are <pixel size><mask format>
   Currently, they can only be created in widths which are multiples of 4 bytes, and cannot be toscreen()'d */
extern gp_sprfmt gp_spr_pre00, gp_spr_pre01, gp_spr_pre10, gp_spr_pre11;

/*
				PAINTSPR.C
*/

/* OS Sprite format
   Can't be used to create blank sprites (Only from screen or other sprites),
   isn't very fast */
extern gp_sprfmt gp_spr_paint;

extern int gp_spr_paint_size(gp_spr *s); /* Returns the size of the OS Sprite that gp_spr represents (Must be of format gp_spr_paint). Returns 0 on failure */
extern char *gp_spr_paint_getname(gp_spr *s,char *name); /* Fills 'name' with the name of the gp_spr_paint 's', and returns 'name' on success. If name is 0 then a pointer to the internal name buffer is returned, which may not be null terminated. Returns 0 on failure, and 'name' (if supplied) should be at least 13 characters long to allow for a null terminator */
extern void gp_spr_paint_setname(gp_spr *s,char *name); /* Sets the name of gp_spr_paint 's' to 'name', returning !0 on failure. Only up to 12 characters of 'name' are copied. */
extern int gp_spr_paint_find(gp_spr **s,int n,char *name); /* Search an array of paint sprites for one with name 'name', returning its index or -1 on failure. Only up to the first 12 characters are compared, and null/non-gp_spr_paint sprites are ignored */
extern int gp_spr_paint_save(gp_spr *s,FILE *f); /* Saves the gp_spr_paint 's' to disc (in OS Sprite format), returning !0 on failure */
extern gp_spr *gp_spr_paint_load(FILE *f); /* Loads an OS Sprite from disc, and returns it as a gp_spr. May not work with all sprites, e.g. ones which aren't 8/16/24bpp. Returns 0 on failure, and if successful 'f' should point to the next sprite in the sprite file */
extern gp_spr **gp_spr_paint_loadfile(char *fname,int *n); /* Loads a Sprite file from disc, and returns it as an array of gp_spr pointers. n gets filled with the number of sprites loaded. Returns 0 on failure */
extern int gp_spr_paint_savefile(char *fname,int n,gp_spr **s); /* Saves a Sprite file to disc under name 'fname'. Any sprites which aren't of gp_spr_paint format will be temporarily converted before being saved. Returns !0 on failure */

#endif
