/*
 *  FILE: postext.c
 *  Support routines for writing text (or a number) in a rastport,
 *  with flexible text location specification (eg any corner, centre).
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


#define I_AM_POSTEXT
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/postext.h"


SHORT positionText( rp, myflags, s, num, x, y )
    register struct RastPort	*rp;
    register ULONG		myflags;
    UBYTE   *s;
    LONG    num;
    SHORT   x, y;
{
    register SHORT  i, j;
    SHORT	    len, rastlen, maxrastlen;
    SHORT	    maxbit, lowi;
    SHORT	    dest, temp;
    SHORT	    height, baseline;
    struct RastPort myrp;
    UBYTE	    buf[12];		/* big enough for max ULONG + '\0' */


#ifdef GIMME_WIMPY
    if( !rp ) {
	return( -1 );
    }
#endif
    if( s ) {
	len = strlen( s );
    } else {
	len = sprintf( buf, "%1ld", num );
	s = buf;
    }
    maxrastlen = len * (rp->TxWidth + rp->TxSpacing);
    rastlen = TextLength( rp, s, (long) len );

    if( myflags & (GPT_YUPWARDS | GPT_YDOWNWARDS) ) {
	myrp = *rp;			/* copy struct */
	myrp.BitMap = gimmeBitMap( rp->BitMap->Depth, rastlen, myrp.TxHeight );
	if( !myrp.BitMap ) {
	    return( -1 );
	}
	myrp.Layer = NULL;		/* make sure no layer else trouble */
	myrp.GelsInfo = NULL;
	Move( &myrp, 0L, (long) myrp.TxBaseline );
	Text( &myrp, s, (long) len );

	maxbit = rastlen - 1;
	switch( myflags & GPT_XFLAGS ) {
	  case GPT_XRIGHT:
	    if( myflags & GPT_YDOWNWARDS ) {
		y -= maxbit;
	    }
	    break;
	  case GPT_XCENTRE:
	    y -= rastlen >> 1;
	    break;
	  case GPT_XLEFT:
	  default:
	    if( myflags & GPT_YUPWARDS ) {
		y -= maxbit;
	    }
	    break;
	} /* switch */

	if( myflags & GPT_XTHICKEN ) {              /* if double thickness */
	    height = (myrp.TxHeight << 1) - 1;
	    baseline = (myrp.TxBaseline << 1);
	} else {
	    height = myrp.TxHeight - 1;
	    baseline = myrp.TxBaseline;
	}

	switch( myflags & GPT_YFLAGS ) {        /* make x top of char */
	  case GPT_YBOTTOM:
	    if( myflags & GPT_YUPWARDS ) {
		x -= height;
	    }
	    break;
	  case GPT_YCENTRE:			/* skew to top of char */
	    if( myflags & GPT_YDOWNWARDS ) {
		/* x += (height >> 1) - height; */
		x -= (height + 1) >> 1;
	    } else {
		x -= height >> 1;
	    }
	    break;
	  case GPT_YCENTREBASE: 		/* skew to bottom of char */
	    if( myflags & GPT_YDOWNWARDS ) {
		x += ((baseline + 1) >> 1) - height;
	    } else {
		x -= (baseline + 1) >> 1;
	    }
	    break;
	  case GPT_YTOP:
	    if( myflags & GPT_YDOWNWARDS ) {
		x -= height;
	    }
	    break;
	  case GPT_YBASELINE:
	  default:
	    if( myflags & GPT_YDOWNWARDS ) {
		x += baseline - height;
	    } else {
		x -= baseline;
	    }
	    break;
	} /* switch */

	if( y < 0 ) {
	    rastlen += y;
	    y = 0;
	}
	lowi = rastlen - rp->BitMap->Rows;
	if( lowi > 0 ) {
	    rastlen -= lowi;
	} else {
	    lowi = 0;
	}
	maxbit = rastlen - 1;
	if( myflags & GPT_YDOWNWARDS ) {
	    if( lowi ) {
		maxbit -= lowi;
		lowi = 0;
	    }
	    temp = x + height;
	    for( j = myrp.TxHeight - 1; j >= 0; --j ) {
		if( GPT_XTHICKEN ) {
		    dest = temp - (j << 1) - 1;
		} else {
		    dest = temp - j;
		}
		for( i = maxbit; i >= lowi; --i ) {
		    /* if no error and not background colour */
		    if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) {
			WritePixel( rp, (long) dest, (long) y + i );
			if( myflags & GPT_XTHICKEN ) {
			    WritePixel( rp, (long) dest + 1, (long) y + i );
			}
		    }
		} /* for */
	    } /* for */
	} else {		/* else upwards */
	    for( i = maxbit; i >= lowi; --i ) {
		dest = y + maxbit - i;
		for( j = myrp.TxHeight - 1; j >= 0; --j ) {
		    /* if no error and not background colour */
		    if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) {
			if( myflags & GPT_XTHICKEN ) {
			    temp = j << 1;
			    WritePixel( rp, (long) x + temp + 1, (long) dest );
			    WritePixel( rp, (long) x + temp, (long) dest );
			} else {
			    WritePixel( rp, (long) x + j, (long) dest );
			}
		    }
		} /* for */
	    } /* for */
	}
	getRidOfBitMap( myrp.BitMap );
    } else {
	switch( myflags & GPT_XFLAGS ) {
	  case GPT_XRIGHT:
	    x -= rastlen - 1;
	    break;
	  case GPT_XCENTRE:
	    x -= rastlen >> 1;
	    break;
	  case GPT_XLEFT:
	  default:
	    break;
	} /* switch */

	switch( myflags & GPT_YFLAGS ) {        /* make y top of char */
	  case GPT_YBOTTOM:
	    y -= rp->TxHeight - 1;
	    break;
	  case GPT_YCENTRE:
	    y -= (rp->TxHeight - 1) >> 1;       /* skew to top of char */
	    break;
	  case GPT_YCENTREBASE:
	    y -= (rp->TxBaseline + 1) >> 1;     /* skew to bottom of char */
	    break;
	  case GPT_YTOP:
	    break;
	  case GPT_YBASELINE:
	  default:
	    y -= rp->TxBaseline;
	    break;
	} /* switch */
	y += rp->TxBaseline;		/* adjust top to baseline for Text() */
	/* note rp's TxBaseline is offset from top pixel of character */

	Move( rp, (long) x, (long) y );
	Text( rp, s, (long) len );
    }
    return( maxrastlen );
} /* positionText */
