/* Copyright 1996 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/****************************************************************************
 * This source file was written by Acorn Computers Limited. It is part of   *
 * the RISCOS library for writing applications in C for RISC OS. It may be  *
 * used freely in the creation of programs for Archimedes. It should be     *
 * used with Acorn's C Compiler Release 3 or later.                         *
 *                                                                          *
 ***************************************************************************/

/*
 * Title  : sprite.h
 * Purpose: provide access to RISC OS sprite facilities
 *
 */

# ifndef __sprite_h
# define __sprite_h

# ifndef __os_h
# include "os.h"
# endif

/*
 * This file contains functions for performing operations on sprites.
 * For brevity only a brief description is given for each call. More details
 * can be found in the Programmer's Reference manual under the section on
 * Sprite SWIs.
 *
 */



/******** Simple operations, use no sprite area, no name/sprite pointer ***/

typedef enum
{
  sprite_nopalette  = 0,
  sprite_haspalette = 1
} sprite_palflag;

typedef struct
{
  int xmag,ymag,xdiv,ydiv;
} sprite_factors;

typedef char sprite_pixtrans;




/* ----------------------------- sprite_screensave -------------------------
 * Save the current graphics window as a sprite file, with optional palette.
 * Equivalent to *ScreenSave.
 *
 */
extern os_error * sprite_screensave(const char *filename, sprite_palflag);

/* ---------------------------- sprite_screenload --------------------------
 * Load a sprite file onto the screen. Equivalent to *ScreenLoad.
 *
 */
extern os_error * sprite_screenload(const char *filename);



/****** Operations on either system/user area, no name/sprite pointer *****/

typedef struct /* Format of a sprite area control block */
{
  int size;
  int number;
  int sproff;
  int freeoff;
} sprite_area;

typedef struct /* Format of a sprite header */
{
  int  next;      /*  Offset to next sprite                */
  char name[12];  /*  Sprite name                          */
  int  width;     /*  Width in words-1      (0..639)       */
  int  height;    /*  Height in scanlines-1 (0..255/511)   */
  int  lbit;      /*  First bit used (left end of row)     */
  int  rbit;      /*  Last bit used (right end of row)     */
  int  image;     /*  Offset to sprite image               */
  int  mask;      /*  Offset to transparency mask          */
  int  mode;      /*  Mode sprite was defined in           */
                  /*  Palette data optionally follows here */
                  /*  in memory                            */
} sprite_header;

#define sprite_mainarea ((sprite_area *) 0)

typedef void * sprite_ptr;


/* ------------------------ sprite_area_initialise -------------------------
 * Initialise an area of memory as a sprite area
 *
 */
void sprite_area_initialise(sprite_area *, int size);

/* ----------------------- sprite_area_readinfo ----------------------------
 * Read information from a sprite area control block
 *
 */
extern os_error * sprite_area_readinfo(sprite_area *, sprite_area *resultarea);

/* --------------------------- sprite_area_reinit --------------------------
 * Reinitialise a sprite area.
 * If system area, then equivalent to *SNew
 *
 */
extern os_error * sprite_area_reinit(sprite_area *);

/* --------------------------- sprite_area_load ----------------------------
 * Load a sprite file into a sprite area.
 * If system area, then equivalent to *SLoad
 *
 */
extern os_error * sprite_area_load(sprite_area *, const char *filename);

/* ---------------------------- sprite_area_merge --------------------------
 * Merge a sprite file with a sprite area.
 * If system area, then equivalent to *SMerge
 *
 */
extern os_error * sprite_area_merge(sprite_area *, const char *filename);

/* ---------------------------- sprite_area_save ---------------------------
 * Saves a sprite area as a sprite file.
 * If system area, then equivalent to *SSave
 *
 */
extern os_error * sprite_area_save(sprite_area *, const char *filename);

/* ---------------------------- sprite_getname -----------------------------
 * Return the name and length of name of the n'th sprite in a sprite area into
 * a buffer.
 *
 */
extern os_error * sprite_getname(sprite_area *, void *buffer, int *length, int index);

/* ---------------------------- sprite_get ---------------------------------
 * Copy a rectangle of screen delimited by the last pair of graphics cursor
 * positions as a named sprite in a sprite area, optionally storing the
 * palette with the sprite.
 *
 */
extern os_error * sprite_get(sprite_area *, char *name, sprite_palflag);

/* ---------------------------- sprite_get_rp ------------------------------
 * Copy a rectangle of screen delimited by the last pair of graphics cursor
 * positions as a named sprite in a sprite area, optionally storing the
 * palette with the sprite. Address of sprite returned in resultaddress.
 *
 */
extern os_error * sprite_get_rp(sprite_area *, char *name, sprite_palflag,
                         sprite_ptr *resultaddress);

/* ---------------------------- sprite_get_given ---------------------------
 * Copy a rectangle of screen delimited by the given pair of graphics
 * coordinates as a named sprite in a sprite area, optionally storing the
 * palette with the sprite.
 *
 */
extern os_error * sprite_get_given(sprite_area *, char *name, sprite_palflag,
                            int x0, int y0, int x1, int y1);

/* --------------------------- sprite_get_given_rp -------------------------
 * Copy a rectangle of screen delimited by the given pair of graphics
 * coordinates as a named sprite in a sprite area, optionally storing the
 * palette with the sprite. Address of sprite returned in resultaddress.
 *
 */
extern os_error * sprite_get_given_rp(sprite_area *, char *name, sprite_palflag,
                               int x0, int y0, int x1, int y1,
                               sprite_ptr *resultaddress);

/* ------------------------------ sprite_create ----------------------------
 * Create a named sprite in a sprite area of specified size and screen mode,
 * optionally reserving space for palette data with the sprite.
 *
 */
extern os_error * sprite_create(sprite_area *, char *name, sprite_palflag,
                         int width, int height, int mode);

/* ------------------------------ sprite_create_rp -------------------------
 * Create a named sprite in a sprite area of specified size and screen mode,
 * optionally reserving space for palette data with the sprite.Address of
 * sprite returned in resultaddress.
 *
 */
extern os_error * sprite_create_rp(sprite_area *, char *name, sprite_palflag,
                            int width, int height, int mode,
                            sprite_ptr *resultaddress);


/*********** Operations on system/user area, name/sprite pointer **********/

typedef enum
{
  sprite_id_name = 0,
  sprite_id_addr = 0x74527053 /* 'Magic' number ("SpRt") to test against */
} sprite_type;

typedef struct
{
  union
  {
    char *     name; /* Can use either name of sprite or address (faster) */
    sprite_ptr addr;
  } s;
  sprite_type tag;   /* User must tag the use of this structure manually */
} sprite_id;


/* ----------------------------- sprite_select -----------------------------
 * Select the specified sprite for plotting using plot(0xed,x,y).
 *
 */
extern os_error * sprite_select(sprite_area *, sprite_id *);

/* ----------------------------- sprite_select_rp --------------------------
 * Select the specified sprite for plotting using plot(0xed,x,y). Address of
 * sprite returned in resultaddress.
 *
 */
extern os_error * sprite_select_rp(sprite_area *, sprite_id *,
                            sprite_ptr *resultaddress);

/* ----------------------------- sprite_delete -----------------------------
 * Delete the specified sprite.
 *
 */
extern os_error * sprite_delete(sprite_area *, sprite_id *);

/* ----------------------------- sprite_rename -----------------------------
 * Rename the specified sprite within the same sprite area.
 *
 */
extern os_error * sprite_rename(sprite_area *, sprite_id *, char *newname);

/* ----------------------------- sprite_copy -------------------------------
 * Copy the specified sprite as another named sprite in the same sprite area.
 *
 */
extern os_error * sprite_copy(sprite_area *, sprite_id *, char *copyname);

/* ----------------------------- sprite_put --------------------------------
 * Plot the specified sprite using the given GCOL action.
 *
 */
extern os_error * sprite_put(sprite_area *, sprite_id *, int gcol);

/* ----------------------------- sprite_put_given --------------------------
 * Plot the specified sprite at (x,y) using the given GCOL action.
 *
 */
extern os_error * sprite_put_given(sprite_area *, sprite_id *, int gcol,
                            int x, int y);

/* --------------------------- sprite_put_scaled ---------------------------
 * Plot the specified sprite at (x,y) using the given GCOL action, and scaled
 * using the given scale factors.
 *
 */
extern os_error * sprite_put_scaled(sprite_area *, sprite_id *, int gcol,
                            int x, int y,
                            sprite_factors *factors,
                            sprite_pixtrans pixtrans[]);

/* ---------------------------- sprite_put_greyscaled ----------------------
 * Plot the specified sprite at (x,y) using the given GCOL action, and
 * greyscaled using the given scale factors.
 *
 */
extern os_error * sprite_put_greyscaled(sprite_area *, sprite_id *,
                            int x, int y,
                            sprite_factors *factors,
                            sprite_pixtrans pixtrans[]);

/* ----------------------------- sprite_put_mask ---------------------------
 * Plot the specified sprite mask in the background colour.
 *
 */
extern os_error * sprite_put_mask(sprite_area *, sprite_id *);

/* ----------------------------- sprite_put_mask_given ---------------------
 * Plot the specified sprite mask at (x,y) in the background colour.
 *
 */
extern os_error * sprite_put_mask_given(sprite_area *, sprite_id *, int x, int y);

/* --------------------------- sprite_put_mask_scaled ----------------------
 * Plot the sprite mask at (x,y) scaled, using the background colour/action
 *
 */
extern os_error * sprite_put_mask_scaled(sprite_area *, sprite_id *,
                            int x, int y,
                            sprite_factors *factors);

/* ----------------------------- sprite_put_char_scaled --------------------
 * Paint char scaled at (x,y)
 *
 */
extern os_error * sprite_put_char_scaled(char ch,
                                  int x, int y,
                                  sprite_factors *factors);

/* ---------------------------- sprite_create_mask -------------------------
 * Create a mask definition for the specified sprite.
 *
 */
extern os_error * sprite_create_mask(sprite_area *, sprite_id *);

/* ---------------------------- sprite_remove_mask -------------------------
 * Remove the mask definition from the specified sprite.
 *
 */
extern os_error * sprite_remove_mask(sprite_area *, sprite_id *);

/* ---------------------------- sprite_insert_row --------------------------
 * Insert a row into the specified sprite at the given row.
 *
 */
extern os_error * sprite_insert_row(sprite_area *, sprite_id *, int row);

/* ---------------------------- sprite_delete_row --------------------------
 * Delete the given row from the specified sprite.
 *
 */
extern os_error * sprite_delete_row(sprite_area *, sprite_id *, int row);

/* ---------------------------- sprite_insert_column -----------------------
 * Insert a column into the specified sprite at the given column.
 *
 */
extern os_error * sprite_insert_column(sprite_area *, sprite_id *, int column);

/* ---------------------------- sprite_delete_column -----------------------
 * Delete the given column from the specified sprite.
 *
 */
extern os_error * sprite_delete_column(sprite_area *, sprite_id *, int column);

/* ----------------------------- sprite_flip_x -----------------------------
 * Flip the specified sprite about the x axis
 *
 */
extern os_error * sprite_flip_x(sprite_area *, sprite_id *);

/* ----------------------------- sprite_flip_y -----------------------------
 * Flip the specified sprite about the y axis
 *
 */
extern os_error * sprite_flip_y(sprite_area *, sprite_id *);


typedef struct
{
 int width;
 int height;
 int mask;
 int mode;
} sprite_info;

/* -------------------------------- sprite_readsize ------------------------
 * Read the size information for the specified sprite_id
 *
 */
extern os_error * sprite_readsize(sprite_area *, sprite_id *,
                           sprite_info *resultinfo);


typedef struct
{
  int colour;
  int tint;
} sprite_colour;

/* ----------------------------- sprite_readpixel --------------------------
 * Read the colour of a given pixel in the specified sprite_id
 *
 */
extern os_error * sprite_readpixel(sprite_area *, sprite_id *,
                            int x, int y, sprite_colour *resultcolour);

/* ----------------------------- sprite_writepixel -------------------------
 * Write the colour of a given pixel in the specified sprite_id
 *
 */
extern os_error * sprite_writepixel(sprite_area *, sprite_id *,
                             int x, int y, sprite_colour *colour);


typedef enum
{
  sprite_masktransparent = 0,
  sprite_masksolid       = 1
} sprite_maskstate;

/* ------------------------------- sprite_readmask -------------------------
 * Read the state of a given pixel in the specified sprite mask
 *
 */
extern os_error * sprite_readmask(sprite_area *, sprite_id *,
                           int x, int y, sprite_maskstate *resultmaskstate);

/* ------------------------------- sprite_writemask ------------------------
 * Write the state of a given pixel in the specified sprite mask
 *
 */
extern os_error * sprite_writemask(sprite_area *, sprite_id *,
                            int x, int y, sprite_maskstate *maskstate);


typedef struct
        { int r[4];
        } sprite_state;

/* ----------------------------- sprite_restorestate -----------------------
 * Restores the old state after one of the sprite redirection calls
 *
 */
extern os_error *sprite_restorestate(sprite_state state);


/* ---------------------------- sprite_outputtosprite ----------------------
 * Redirect VDU output to a sprite, saving old state
 *
 */
extern os_error *sprite_outputtosprite(sprite_area *area, sprite_id *id,
                                int *save_area, sprite_state *state);

/* ----------------------- sprite_outputtomask -----------------------------
 * Redirects output to a sprite's transparency mask, saving old state
 *
 */
extern os_error *sprite_outputtomask(sprite_area *area, sprite_id *id,
                              int *save_area, sprite_state *state);

/* --------------------------- sprite_outputtoscreen -----------------------
 * Redirect output back to screen, saving old state
 *
 */
extern os_error *sprite_outputtoscreen(int *save_area, sprite_state *state);

/* --------------------------- sprite_sizeof_spritecontext -----------------
 * Get size of save area needed to save sprite context.
 *
 */
extern os_error *sprite_sizeof_spritecontext(sprite_area *area, sprite_id *id,
                                      int *size);

/* ------------------------- sprite_sizeof_screencontext -------------------
 * Get size of save area needed to save screen context.
 *
 */
extern os_error *sprite_sizeof_screencontext(int *size);

/* ------------------------ sprite_removewastage ---------------------------
 * Removes left hand wastage from a sprite
 *
 */
extern os_error *sprite_removewastage(sprite_area *area, sprite_id *id);

/* ------------------------ sprite_change_size -----------------------------
 * General insert/delete rows/columns operations
 *
 */
extern os_error
  *sprite_change_size
  (sprite_area *area, sprite_id *id, BOOL rows, int at, int number);

/* Typedefs and functions for rotating sprites. */

typedef struct {int p0 [2], p1 [2], p2 [2], p3 [2];} sprite_pgm;
typedef int sprite_transmat [6];
typedef struct {int x0, y0, x1, y1;} sprite_box;

/* ------------------------ sprite_put_mask_trans ---------------------
 * Put a box from the mask in background colours through a transformation matrix
 *
 */
extern os_error
  *sprite_put_mask_trans
  (sprite_area *, sprite_id *, sprite_box *, sprite_transmat *);

/* ------------------------ sprite_put_mask_pgm -----------------------
 * Put a box from the mask in background colours to a parallelogram
 *
 */
extern os_error
  *sprite_put_mask_pgm
  (sprite_area *, sprite_id *, sprite_box *, sprite_pgm *);

/* ------------------------ sprite_put_trans --------------------------
 * Put a box from the sprite through a transformation matrix
 *
 */
extern os_error
  *sprite_put_trans
  (sprite_area *, sprite_id *, int gcol_action, sprite_box *, sprite_transmat *, sprite_pixtrans *);

/* ------------------------ sprite_put_pgm ----------------------------
 * Put a box from the sprite to a parallelogram
 *
 */
extern os_error
  *sprite_put_pgm
  (sprite_area *, sprite_id *, int gcol_action, sprite_box *, sprite_pgm *, sprite_pixtrans *);

# endif

/* end of sprite.h */