/* Simple span buffer manager V3.44 10/9/04
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM 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.
   WOUM 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 WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _SPAN_H
#define _SPAN_H

#include "fixmath.h"

/* Values to limit depth of span buffer
   CLOSEST_Z musn't be less than 1
   Placing un Z-clipped objects with Z's between +1 and -1 isn't a good idea */
#define CLOSEST_Z f1616_FromInt(1)
#define FARTHEST_Z f1616_FromInt(30000)

/* Define this to perform extra safety checks during poly/span insertion */
#define PARANOID

/* Define this to a value to make span_do2/3 skip drawing spans of a certain
   id. This can be useful to mask out areas of the screen you don't want
   overwriting
*/
#define SKIPID -1

/* These variables should only be changed between calls to span_free and
   span_init, otherwise the internal data structures won't match with these
   values
*/
extern int span_lines; /* Number of lines (i.e. y height) of buffer */
extern int span_width; /* Width of buffer (pixels) */
extern void *span_buf; /* Buffer which gets drawn to */
extern int span_gap; /* Gap between lines in buffer, in bytes */
extern int span_ps; /* Pixel size of span buffer, such that 1 << ps == bytes per pixel */

/* This is the object id given to all spans as they are created by the drawing
   tools
*/
extern int span_id;

typedef void *spanset; /* A set of spans which have been stored */

/* Free all spans in 's', or the currently active set */
extern void span_free(spanset s);

/* Initialise the system
   The initial spans will be colour 'col', have an id of span_id, and Z value of
   FARTHEST_Z */
extern void span_init(int col);

/* Draw spans to buffer
   Define SAFE to enable lots of error checking */
extern void span_do();

/* Draw spans to buffer using custom routine
   void (*func)(int col,void *scr,int len)
   Where col=colour, scr=screen start ptr, len=length to draw (pixels)
   i.e. in the format for Gnarl Plot's hline drawers
*/
extern void span_do2(void (*func)(int,void *,int));

/* Draw only the spans which have changed from span set s
   If s is null, all spans will be redrawn
   Returns the span set describing the current screen
   The current span set will also have been set to s (Or cleared if s was null)
*/
extern spanset span_do3(void (*func)(int,void *,int),spanset s);

/* Swap a span set into use
   The span set indicated by s will be overwritten by the current span set
*/
extern void span_swapset(spanset s);

/* Save the current span set out, leaving no set loaded
*/
extern spanset span_saveset();

/* Various return codes for the span/poly adding code */
#define SPAN_OK 0 /* Span was on screen, and was at least partially visible */
#define SPAN_OCCLUDED 1 /* Span was on screen, but fully hidden by other spans */
#define SPAN_OFFSCREEN 2 /* Span was fully off screen */
#define SPAN_WRONGWAYROUND 3 /* The wrong side was facing the viewer */

/* Interrogate the span buffer or a saved span set to return certain information
   All functions return 0 if the input is out of range */
extern int span_readcol(spanset si,int x,int y); /* Return colour at point */
extern f1616 span_readdepth(spanset si,int x,int y); /* Return depth at point */
extern int span_readid(spanset si,int x,int y); /* Return object id at point */
extern int span_readstart(spanset si,int x,int y); /* Return X start of span */
extern int span_readlen(spanset si,int x,int y); /* Return length of span */

typedef int invz; /* Inverse Z value as used by the span buffer */

#define INVZ_ACCURACY ((float) 0x40000000) /* INVZ_ACCURACY/z = inverse z */
#define INVZ_ACC_LOG2 30 /* Log2 of INVZ_ACCURACY */
#define F16_TO_INVZ(x) gen_inverse(INVZ_ACC_LOG2+16,x) /* Conversion macros */
#define INVZ_TO_F16(x) gen_inverse(INVZ_ACC_LOG2+16,x)

extern invz f1616_to_invz(f1616 a); /* Return a as an invz */
extern f1616 invz_to_f1616(invz a); /* Return a as an f1616 */

/* Add a span, giving a return code:
   in_xs is the start point of the span (inclusive). 0 <= in_xs < span_width
   in_xe is the end point of the span (inclusive). in_xe < span_width
   in_izs is the Z value at in_xs
   in_izg is the Z increment per X
   col is the colour of the span
   y is the row the span appears on. 0 <= y < span_lines
   The span will be given an id of span_id
   Spans with in_xe < in_xs are ignored. */
extern int span_add(int in_xs,int in_xe,invz in_izs,invz in_izg,int col,int y);
 
#endif
