/* GDCHART 0.11.3dev GDC.C 11 Mar 2003 */
/* Copyright Bruce Verderaime 1998-2003 */
#define GDC_INCL
#define GDC_LIB
#include <math.h>
#include "gdc.h"
struct GDC_FONT_T GDC_fontc[GDC_numfonts] = { (gdFontPtr)NULL, 8, 5,
(gdFontPtr)NULL, 8, 5,
(gdFontPtr)NULL, 12, 6,
(gdFontPtr)NULL, 13, 7,
(gdFontPtr)NULL, 16, 8,
(gdFontPtr)NULL, 15, 9 };
/* ------------------------------------------------------------------- *\
* convert from enum GDC_font_size to gd fonts
* for now load them all
* #defines and #ifdefs might enable loading only needed fonts
* gd2.0 is to be built as a shared obj.
\* ------------------------------------------------------------------- */
void
load_font_conversions()
{
GDC_fontc[GDC_pad].f = gdFontTiny;
GDC_fontc[GDC_TINY].f = gdFontTiny;
GDC_fontc[GDC_SMALL].f = gdFontSmall;
GDC_fontc[GDC_MEDBOLD].f = gdFontMediumBold;
GDC_fontc[GDC_LARGE].f = gdFontLarge;
GDC_fontc[GDC_GIANT].f = gdFontGiant;
}
/* ------------------------------------------------------------------ *\
* count (natural) substrings (new line sep)
\* ------------------------------------------------------------------ */
short
cnt_nl( char *nstr,
int *len ) /* strlen - max seg */
{
short c = 1;
short max_seg_len = 0;
short tmplen = 0;
if( !nstr )
{
if( len )
*len = 0;
return 0;
}
while( *nstr )
{
if( *nstr == '\n' )
{
++c;
max_seg_len = MAX( tmplen, max_seg_len );
tmplen = 0;
}
else
++tmplen;
++nstr;
}
if( len )
*len = MAX( tmplen, max_seg_len ); /* don't forget last seg */
return c;
}
/* ------------------------------------------------------------------ *\
* gd out a string with '\n's
* handle FTs (TTFs) and gd fonts
* gdImageString() draws from the upper left;
* gdImageStringFT() draws from lower left (one font height, even with '\n's)! >:-|
\* ------------------------------------------------------------------ */
int
GDCImageStringNL( gdImagePtr im,
struct GDC_FONT_T *f,
char *ftfont,
double ftptsz,
double rad,
int x,
int y,
char *str,
int clr,
GDC_justify_t justify,
char **sts )
{
int retval = 0;
char *err = NULL;
#ifdef HAVE_LIBFREETYPE
/* TODO: honor justifies */
if( ftfont && ftptsz )
{
/* need one line height */
/* remember last one (will likely be the same) */
/* is this needed? */
/* gdImageStringFT() utilizes some caching */
/* saves a couple floating point trig calls */
static int f1hgt = 0;
static double xs,
ys;
static double lftptsz = 0.0;
static char *lftfont = (char*)-1;
if( !f1hgt ||
( lftfont != ftfont || lftptsz != ftptsz ) )
{
f1hgt = GDCfnt_sz( "Aj",
0,
ftfont,
ftptsz,
rad,
NULL ).h;
xs = (double)f1hgt * sin(rad);
ys = (double)(f1hgt-1) * cos(rad);
}
x += (int)xs;
y += (int)ys;
if( (err = gdImageStringFT( im,
(int*)NULL,
clr,
ftfont,
ftptsz,
rad,
x,
y,
str)) == NULL )
{
if( sts ) *sts = err;
return 0;
}
else
{
/* TTF failed */
retval = 1;
/* fall through - default to gdFonts */
/* reinstate upper left reference */
x -= (int)xs;
y -= (int)ys;
}
}
#endif
{
int i;
int len;
int max_len;
short strs_num = cnt_nl( str, &max_len );
CREATE_ARRAY1( sub_str, unsigned char, max_len+1 ); /* char sub_str[max_len+1]; */
len = -1;
strs_num = -1;
i = -1;
do
{
++i;
++len;
sub_str[len] = *(str+i);
if( *(str+i) == '\n' ||
*(str+i) == '\0' )
{
int xpos;
sub_str[len] = '\0';
++strs_num;
switch( justify )
{
case GDC_JUSTIFY_LEFT: xpos = 0; break;
case GDC_JUSTIFY_RIGHT: xpos = f->w*(max_len-len); break;
case GDC_JUSTIFY_CENTER:
default: xpos = f->w*(max_len-len)/2;
}
if( rad == 0.0 )
gdImageString( im,
f->f,
x + xpos,
y + (f->h-1)*strs_num,
sub_str,
clr );
else /* if( rad == M_PI/2.0 ) */
gdImageStringUp( im,
f->f,
x + (f->h-1)*strs_num,
y - xpos,
sub_str,
clr );
len = -1;
}
}
while( *(str+i) );
}
if( sts ) *sts = err;
return retval;
}
/* ------------------------------------------------------------------------ *\
* TODO: *
* really get a unique color from the color map *
\* ------------------------------------------------------------------------ */
long
get_uniq_color( gdImagePtr im )
{
return 0x123454;
}
/* ------------------------------------------------------------------------ */
struct fnt_sz_t
GDCfnt_sz( char *s,
enum GDC_font_size gdfontsz,
char *ftfont,
double ftfptsz,
double rad, /* w,h still relative to horiz. */
char **sts )
{
struct fnt_sz_t rtnval;
int len;
char *err = NULL;
#ifdef HAVE_LIBFREETYPE
if( ftfont && ftfptsz )
{
int brect[8];
/* obtain brect so that we can size the image */
if( (err = gdImageStringFT( (gdImagePtr)NULL,
&brect[0],
0,
ftfont,
ftfptsz,
0.0, /* rad, */ /* always match angled size??? */
0,
0,
s)) == NULL )
{
rtnval.h = brect[1] - brect[7];
rtnval.w = brect[2] - brect[0];
if( sts ) *sts = err;
return rtnval;
}
}
#endif
rtnval.h = cnt_nl(s,&len) * GDC_fontc[gdfontsz].h;
rtnval.w = len * GDC_fontc[gdfontsz].w;
if( sts ) *sts = err;
return rtnval;
}
/* ------------------------------------------------------------------------ */
void
GDC_destroy_image(void *im)
{
if( im )
gdImageDestroy( (gdImagePtr)im );
}
/* ------------------------------------------------------------------------ */
void
out_err( int IMGWIDTH,
int IMGHEIGHT,
FILE *fptr,
unsigned long BGColor,
unsigned long LineColor,
char *err_str )
{
gdImagePtr im;
int lineclr;
int bgclr;
if( (GDC_hold_img & GDC_REUSE_IMAGE) &&
GDC_image != (void*)NULL )
im = GDC_image;
else
im = gdImageCreate( IMGWIDTH, IMGHEIGHT );
bgclr = gdImageColorAllocate( im, l2gdcal(BGColor) );
lineclr = gdImageColorAllocate( im, l2gdcal(LineColor) );
gdImageString( im,
gdFontMediumBold,
IMGWIDTH/2 - GDC_fontc[GDC_MEDBOLD].w*strlen(err_str)/2,
IMGHEIGHT/3,
(unsigned char*)err_str,
lineclr );
/* usually GDC_generate_img is used in conjunction with hard or hold options */
if( GDC_generate_img )
{
fflush(fptr); /* clear anything buffered */
switch( GDC_image_type )
{
#ifdef HAVE_JPEG
case GDC_JPEG: gdImageJpeg( im, fptr, GDC_jpeg_quality ); break;
#endif
case GDC_WBMP: gdImageWBMP( im, lineclr, fptr ); break;
case GDC_GIF: gdImageGif( im, fptr); break;
case GDC_PNG:
default: gdImagePng( im, fptr );
}
}
if( GDC_hold_img & GDC_EXPOSE_IMAGE )
GDC_image = (void*)im;
else
gdImageDestroy(im);
return;
}