b56e5a1998-04-24Mirar (Pontus Hagland) /* $Id: font.c,v 1.35 1998/04/24 13:50:21 mirar Exp $ */
fec6251998-03-25Fredrik Hübinette (Hubbe) #include "global.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include <config.h>
7abac31997-09-01Per Hedbor #define SPACE_CHAR 'i'
e3cb4b1997-04-03Mirar (Pontus Hagland) /* **! module Image
4ce7411997-05-29Mirar (Pontus Hagland) **! note
b56e5a1998-04-24Mirar (Pontus Hagland) **! $Id: font.c,v 1.35 1998/04/24 13:50:21 mirar Exp $
e3cb4b1997-04-03Mirar (Pontus Hagland) **! class font
b9284c1997-04-09Mirar (Pontus Hagland) **!
4ce7411997-05-29Mirar (Pontus Hagland) **! note **! Short technical documentation on a font file:
a827cd1997-04-19Mirar (Pontus Hagland) **! This object adds the text-drawing and -creation **! capabilities of the <ref>Image</ref> module. **! **! For simple usage, see **! <ref>write</ref> and <ref>load</ref>. **! **! other methods: <ref>baseline</ref>, **! <ref>height</ref>, **! <ref>set_xspacing_scale</ref>, **! <ref>set_yspacing_scale</ref>, **! <ref>text_extents</ref> **!
f311411997-04-18Mirar (Pontus Hagland) **! <pre>
b9284c1997-04-09Mirar (Pontus Hagland) **! struct file_head **! { **! unsigned INT32 cookie; - 0x464f4e54 **! unsigned INT32 version; - 1 **! unsigned INT32 chars; - number of chars **! unsigned INT32 height; - height of font **! unsigned INT32 baseline; - font baseline **! unsigned INT32 o[1]; - position of char_head's **! } *fh; **! struct char_head **! { **! unsigned INT32 width; - width of this character **! unsigned INT32 spacing; - spacing to next character **! unsigned char data[1]; - pixmap data (1byte/pixel) **! } *ch;
558db11998-02-24Per Hedbor **! **! version 2: **! **! **! On-disk syntax (everything in N.B.O), int is 4 bytes, a byte is 8 bits: **! **! pos **! 0 int cookie = 'FONT'; or 0x464f4e54 **! 4 int version = 2; 1 was the old version without the last four chars **! 8 int numchars; Always 256 in this version of the dump program **! 12 int height; in (whole) pixels **! 16 int baseline; in (whole) pixels **! 20 char direction; 1==right to left, 0 is left to right **! 21 char format; Font format **! 22 char colortablep; Colortable format **! 23 char kerningtablep; Kerning table format **! **! 24 int offsets[numchars]; pointers into the data, realative to &cookie. **! [colortable] **! [kerningtable] **! **! At each offset: **! **! **! 0 int width; in pixels **! 4 int spacing; in 1/1000:th of a pixels **! 8 char data[]; Enough data to plot width * font->height pixels **! Please note that if width is 0, there is no data. **! **! Font formats: **! id type **! 0 Raw 8bit data **! 1 RLE encoded data, char length, char data, 70% more compact than raw data **! 2 ZLib compressed data 60% more compact than RLE **! **! Colortable types: **! 0 No colortable (the data is an alpha channel) **! 1 24bit RGB with alpha (index->color, 256*4 bytes, rgba) **! 2 8bit Greyscale with alpha (index->color, 256*2 bytes) **! **! Kerningtable types: **! 0 No kerning table **! 1 numchars*numchars entries, each a signed char with the kerning value **! 2 numchar entries, each with a list of kerning pairs, like this: **! int len **! len * (short char, short value) **! **! </pre>
b9284c1997-04-09Mirar (Pontus Hagland) **!
a827cd1997-04-19Mirar (Pontus Hagland) **! see also: Image, Image.image
e3cb4b1997-04-03Mirar (Pontus Hagland) */
15dfec1997-05-28Mirar (Pontus Hagland) /* Dump a font into a Roxen Font file (format version 2) On-disk syntax (everything in N.B.O), int is 4 bytes, a byte is 8 bits: pos 0 int cookie = 'FONT'; or 0x464f4e54 4 int version = 2; 1 was the old version without the last four chars 8 int numchars; Always 256 in this version of the dump program 12 int height; in (whole) pixels 16 int baseline; in (whole) pixels 20 char direction; 1==right to left, 0 is left to right 21 char format; Font format 22 char colortablep; Colortable format 23 char kerningtablep; Kerning table format 24 int offsets[numchars]; pointers into the data, realative to &cookie. [colortable] [kerningtable] At each offset: 0 int width; in pixels 4 int spacing; in 1/1000:th of a pixels 8 char data[]; Enough data to plot width * font->height pixels Please note that if width is 0, there is no data. Font formats: id type efficiency with lucida 128 0 Raw 8bit data not really.. :-) 1 RLE encoded data, char length, char data, 70% more compact than raw data 2 ZLib compressed RLE encoded data 60% more compact than RLE Colortable types: 0 No colortable 1 24bit RGB (index->color, 256*3 bytes) 2 24bit Greyscale (index->color, 256*3 bytes) Kerningtable types: 0 No kerning table 1 numchars*numchars entries, each a signed char with the kerning value 2 numchar entries, each with a list of kerning pairs, like this: int len len * (short char, short value) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e42eaf1998-01-02Fredrik Hübinette (Hubbe) #include "fdlib.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include <sys/types.h> #include <sys/stat.h> #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif #ifdef HAVE_SYS_FCNTL_H #include <sys/fcntl.h> #endif
7210191997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_NETINET_IN_H
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include <netinet/in.h>
7210191997-12-22Fredrik Hübinette (Hubbe) #endif
32434a1998-02-10Fredrik Hübinette (Hubbe) #ifdef HAVE_WINSOCK_H #include <winsock.h>
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include <errno.h> #include "config.h" #include "stralloc.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "object.h" #include "constants.h" #include "interpret.h" #include "svalue.h" #include "array.h" #include "threads.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "builtin_functions.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include "image.h" #ifdef HAVE_MMAP #include <sys/mman.h> #endif
3c0c281998-01-26Fredrik Hübinette (Hubbe) #include "dmalloc.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  static struct program *font_program; extern struct program *image_program;
75920f1997-12-28Fredrik Hübinette (Hubbe) #undef THIS
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #define THIS (*(struct font **)(fp->current_storage)) #define THISOBJ (fp->current_object) struct font { unsigned long height; /* height of character rectangles */ unsigned long baseline; /* baseline of characters */ #ifdef HAVE_MMAP unsigned long mmaped_size; /* if 0 - not mmaped: just free() mem */ #endif void *mem; /* pointer to mmaped/malloced memory */ unsigned long chars; /* number of characters */ float xspacing_scale; /* Fraction of spacing to use */ float yspacing_scale; /* Fraction of spacing to use */ enum { J_LEFT, J_RIGHT, J_CENTER } justification; struct _char { unsigned long width; /* character rectangle has this width in pixels */ unsigned long spacing; /* pixels to next character */ unsigned char *pixels; /* character rectangle */ } charinfo [1]; /* many!! */ }; /***************** init & exit *********************************/
9037d01998-02-18Per Hedbor static INLINE void free_font_struct(struct font *font)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { if (font) { if (font->mem) { #ifdef HAVE_MMAP munmap(font->mem,font->mmaped_size); #else free(font->mem); #endif } free(font); } } static void init_font_struct(struct object *o) { THIS=NULL; } static void exit_font_struct(struct object *obj) { free_font_struct(THIS); THIS=NULL; } /***************** internals ***********************************/
d4f2441997-09-06Per Hedbor static INLINE int char_space(struct font *this, unsigned char c) { if(c==0x20) return (int)((float)(this->height*this->xspacing_scale)/4.5); else if(c==0x20+128) return (this->height*this->xspacing_scale)/18; return this->charinfo[c].spacing*this->xspacing_scale; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
d4f2441997-09-06Per Hedbor static INLINE int char_width(struct font *this, unsigned char c) { if(c==0x20 || c==0x20+128) return 0; return this->charinfo[c].width; }
87b4cb1997-11-11Mirar (Pontus Hagland) #ifndef HAVE_MMAP
e42eaf1998-01-02Fredrik Hübinette (Hubbe) static INLINE int my_read(int from, void *t, int towrite)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { int res;
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  while((res = fd_read(from, t, towrite)) < 0)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { switch(errno) { case EAGAIN: case EINTR: continue; default: res = 0; return 0; } } return res; }
87b4cb1997-11-11Mirar (Pontus Hagland) #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
d4f2441997-09-06Per Hedbor static INLINE long file_size(int fd)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { struct stat tmp; int res;
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  if((!fd_fstat(fd, &tmp)) &&
b56e5a1998-04-24Mirar (Pontus Hagland)  (tmp.st_mode & S_IFREG)) return res = tmp.st_size;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  return -1; }
d4f2441997-09-06Per Hedbor static INLINE void write_char(struct _char *ci,
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  rgb_group *pos, INT32 xsize, INT32 height)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { rgb_group *nl; INT32 x,y; unsigned char *p; p=ci->pixels; for (y=height; y>0; y--) { nl=pos+xsize; for (x=(INT32)ci->width; x>0; x--) {
1f94161997-09-03Per Hedbor  int r,c;
b56e5a1998-04-24Mirar (Pontus Hagland)  if((c=255-*p))
1f94161997-09-03Per Hedbor  if ((r=pos->r+c)>255) pos->r=pos->g=pos->b=255; else pos->r=pos->g=pos->b=r;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pos++; p++; } pos=nl; } } /***************** methods *************************************/
b9284c1997-04-09Mirar (Pontus Hagland) /* **! method object|int load(string filename) **! Loads a font file to this font object. **! returns zero upon failure, font object upon success **! arg string filename **! Font file **! see also: write */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  void font_load(INT32 args) { int fd; if (args<1 || sp[-args].type!=T_STRING) error("font->read: illegal or wrong number of arguments\n"); if (THIS) { free_font_struct(THIS); THIS=NULL; } do { #ifdef FONT_DEBUG fprintf(stderr,"FONT open '%s'\n",sp[-args].u.string->str); #endif
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  fd = fd_open(sp[-args].u.string->str,fd_RDONLY,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } while(fd < 0 && errno == EINTR); if (fd >= 0) { long size;
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  struct font *new_font;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  size = file_size(fd); if (size > 0) {
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font=THIS=(struct font *)xalloc(sizeof(struct font));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_ALLOW(); #ifdef HAVE_MMAP
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font->mem =
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  mmap(0,size,PROT_READ,MAP_SHARED,fd,0);
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font->mmaped_size=size;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #else
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font->mem = malloc(size); #ifdef FONT_DEBUG fprintf(stderr,"FONT Malloced %p (%d)\n",new_font->mem,size); #endif
b56e5a1998-04-24Mirar (Pontus Hagland)  if ((new_font->mem) && (!my_read(fd,new_font->mem,size))) {
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  free(new_font->mem); new_font->mem = NULL;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } #endif THREADS_DISALLOW(); if (THIS->mem) { struct file_head { unsigned INT32 cookie; unsigned INT32 version; unsigned INT32 chars; unsigned INT32 height; unsigned INT32 baseline; unsigned INT32 o[1]; } *fh; struct char_head { unsigned INT32 width; unsigned INT32 spacing; unsigned char data[1]; } *ch; #ifdef FONT_DEBUG fprintf(stderr,"FONT mapped ok\n"); #endif fh=(struct file_head*)THIS->mem; if (ntohl(fh->cookie)==0x464f4e54) /* "FONT" */ { #ifdef FONT_DEBUG fprintf(stderr,"FONT cookie ok\n"); #endif if (ntohl(fh->version)==1) { unsigned long i; #ifdef FONT_DEBUG fprintf(stderr,"FONT version 1\n"); #endif THIS->chars=ntohl(fh->chars);
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font=malloc(sizeof(struct font)+
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  sizeof(struct _char)*(THIS->chars-1));
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font->mem=THIS->mem;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #ifdef HAVE_MMAP
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font->mmaped_size=THIS->mmaped_size;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #endif
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  new_font->chars=THIS->chars; new_font->xspacing_scale = 1.0; new_font->yspacing_scale = 1.0; new_font->justification = J_LEFT;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  free(THIS);
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  THIS=new_font;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THIS->height=ntohl(fh->height); THIS->baseline=ntohl(fh->baseline); for (i=0; i<THIS->chars; i++) { if (i*sizeof(INT32)<(unsigned long)size && ntohl(fh->o[i])<(unsigned long)size && ! ( ntohl(fh->o[i]) % 4) ) /* must be aligned */ { ch=(struct char_head*) ((char *)(THIS->mem)+ntohl(fh->o[i])); THIS->charinfo[i].width = ntohl(ch->width); THIS->charinfo[i].spacing = ntohl(ch->spacing); THIS->charinfo[i].pixels = ch->data; } else /* illegal <tm> offset or illegal align */ { #ifdef FONT_DEBUG fprintf(stderr,"FONT failed on char %02xh %d '%c'\n", i,i,i); #endif
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  free_font_struct(new_font);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THIS=NULL; pop_n_elems(args); push_int(0); return; } }
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  fd_close(fd);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ); /* success */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #ifdef FONT_DEBUG fprintf(stderr,"FONT successfully loaded\n"); #endif return; } /* wrong version */ #ifdef FONT_DEBUG else fprintf(stderr,"FONT unknown version\n"); #endif } /* wrong cookie */ #ifdef FONT_DEBUG else fprintf(stderr,"FONT wrong cookie\n"); #endif } /* mem failure */ #ifdef FONT_DEBUG else fprintf(stderr,"FONT mem failure\n"); #endif free_font_struct(THIS); THIS=NULL; } /* size failure */ #ifdef FONT_DEBUG else fprintf(stderr,"FONT size failure\n"); #endif
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  fd_close(fd);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } /* fd failure */ #ifdef FONT_DEBUG else fprintf(stderr,"FONT fd failure\n"); #endif pop_n_elems(args); push_int(0); return; }
b9284c1997-04-09Mirar (Pontus Hagland) /* **! method object write(string text,...) **! Writes some text; thus creating an image object **! that can be used as mask or as a complete picture.
6335331997-11-05Mirar (Pontus Hagland) **! returns an <ref>Image.image</ref> object
b9284c1997-04-09Mirar (Pontus Hagland) **! arg string text, ... **! One or more lines of text.
6335331997-11-05Mirar (Pontus Hagland) **! see also: text_extents, load, Image.image->paste_mask, Image.image->paste_alpha_color
b9284c1997-04-09Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void font_write(INT32 args) { struct object *o; struct image *img;
d4f2441997-09-06Per Hedbor  INT32 xsize=0,i,maxwidth2,j;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  int *width_of;
1f94161997-09-03Per Hedbor  unsigned char *to_write; int to_write_len;
d4f2441997-09-06Per Hedbor  int c;
7abac31997-09-01Per Hedbor  struct font *this = (*(struct font **)(fp->current_storage)); if (!this)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  error("font->write: no font loaded\n");
5cb0011998-02-10Mirar (Pontus Hagland)  maxwidth2=1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  width_of=(int *)malloc((args+1)*sizeof(int));
1f94161997-09-03Per Hedbor  if(!width_of) error("Out of memory\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (j=0; j<args; j++) { if (sp[j-args].type!=T_STRING) error("font->write: illegal argument(s)\n"); xsize = 0;
1f94161997-09-03Per Hedbor  to_write = (unsigned char*)sp[j-args].u.string->str; to_write_len = sp[j-args].u.string->len; for (i = 0; i < to_write_len; i++) xsize += char_space(this,to_write[i]); xsize += char_width(this,to_write[to_write_len-1])-char_space(this,to_write[to_write_len-1]); width_of[j]=xsize; if (xsize>maxwidth2) maxwidth2=xsize;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
e709751997-03-12Fredrik Hübinette (Hubbe)  o = clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img = ((struct image*)o->storage); img->xsize = maxwidth2; if(args>1)
7abac31997-09-01Per Hedbor  img->ysize = this->height+((double)this->height*(double)(args-1)*(double)this->yspacing_scale)+1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
7a65d61998-02-07Mirar (Pontus Hagland)  img->ysize = this->height;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img->rgb.r=img->rgb.g=img->rgb.b=255;
7a65d61998-02-07Mirar (Pontus Hagland)  img->img=malloc(img->xsize*img->ysize*sizeof(rgb_group)+1);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!img) { free_object(o); free(width_of); error("Out of memory\n"); } MEMSET(img->img,0,img->xsize*img->ysize*sizeof(rgb_group)); for (j=0; j<args; j++) {
f23c571997-09-10Henrik Grubbström (Grubba)  to_write = (unsigned char *)sp[j-args].u.string->str;
1f94161997-09-03Per Hedbor  to_write_len = sp[j-args].u.string->len;
7abac31997-09-01Per Hedbor  switch(this->justification)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
1f94161997-09-03Per Hedbor  case J_LEFT: xsize = 0; break; case J_RIGHT: xsize = img->xsize-width_of[j]-1; break;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  case J_CENTER: xsize = img->xsize/2-width_of[j]/2-1; break; } if(xsize<0) xsize=0;
1f94161997-09-03Per Hedbor  THREADS_ALLOW(); for (i = 0; i < to_write_len; i++)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
d4f2441997-09-06Per Hedbor  c=*(to_write++); /* if(c<0) fatal("IDI compiler\n");*/
1f94161997-09-03Per Hedbor  if (c < (INT32)this->chars)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
d4f2441997-09-06Per Hedbor  if(char_width(this,c)) write_char(this->charinfo+c, (img->img+xsize)+ (img->xsize*(int)(j*this->height*this->yspacing_scale)), img->xsize, this->height);
1f94161997-09-03Per Hedbor  xsize += char_space(this, c);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } }
7abac31997-09-01Per Hedbor  THREADS_DISALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } free(width_of);
7abac31997-09-01Per Hedbor 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_object(o); }
b9284c1997-04-09Mirar (Pontus Hagland) /* **! method int height() **! returns font height **! see also: baseline, text_extents */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void font_height(INT32 args) { pop_n_elems(args); if (THIS) push_int(THIS->height); else push_int(0); }
b9284c1997-04-09Mirar (Pontus Hagland) /*
f311411997-04-18Mirar (Pontus Hagland) **! method array(int) text_extents(string text,...)
b9284c1997-04-09Mirar (Pontus Hagland) **! Calculate extents of a text-image, **! that would be created by calling <ref>write</ref> **! with the same arguments. **! returns an array of width and height **! arg string text, ... **! One or more lines of text. **! see also: write, height, baseline */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void font_text_extents(INT32 args) {
87b4cb1997-11-11Mirar (Pontus Hagland)  INT32 xsize,i,maxwidth2,j;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
1f94161997-09-03Per Hedbor  if (!THIS) error("font->text_extents: no font loaded\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  maxwidth2=0;
1f94161997-09-03Per Hedbor  for (j=0; j<args; j++)
d4f2441997-09-06Per Hedbor  {
1f94161997-09-03Per Hedbor  if (sp[j-args].type!=T_STRING) error("font->text_extents: illegal argument(s)\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  xsize = 0; for (i = 0; i < sp[j-args].u.string->len; i++)
1f94161997-09-03Per Hedbor  xsize += char_space(THIS, (unsigned char)sp[j-args].u.string->str[i]); xsize +=char_width(THIS,(unsigned char)sp[j-args].u.string->str[i-1]) -char_space(THIS,(unsigned char)sp[j-args].u.string->str[i-1]); if (xsize>maxwidth2) maxwidth2=xsize;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
b9284c1997-04-09Mirar (Pontus Hagland)  pop_n_elems(args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  push_int(maxwidth2); push_int(args * THIS->height * THIS->yspacing_scale);
b9284c1997-04-09Mirar (Pontus Hagland)  f_aggregate(2);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
b9284c1997-04-09Mirar (Pontus Hagland)  /* **! method void set_xspacing_scale(float scale) **! method void set_yspacing_scale(float scale) **! Set spacing scale to write characters closer **! or more far away. This does not change scale **! of character, only the space between them. **! arg float scale **! what scale to use */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void font_set_xspacing_scale(INT32 args) { if(!THIS) error("font->set_xspacing_scale(FLOAT): No font loaded.\n"); if(!args) error("font->set_xspacing_scale(FLOAT): No argument!\n"); if(sp[-args].type!=T_FLOAT) error("font->set_xspacing_scale(FLOAT): Wrong type of argument!\n"); THIS->xspacing_scale = (double)sp[-args].u.float_number; /*fprintf(stderr, "Setting xspacing to %f\n", THIS->xspacing_scale);*/ if(THIS->xspacing_scale < 0.0) THIS->xspacing_scale=0.1; pop_stack(); } void font_set_yspacing_scale(INT32 args) { if(!THIS) error("font->set_yspacing_scale(FLOAT): No font loaded.\n"); if(!args) error("font->set_yspacing_scale(FLOAT): No argument!\n"); if(sp[-args].type!=T_FLOAT) error("font->set_yspacing_scale(FLOAT): Wrong type of argument!\n"); THIS->yspacing_scale = (double)sp[-args].u.float_number; /*fprintf(stderr, "Setting yspacing to %f\n", THIS->yspacing_scale);*/ if(THIS->yspacing_scale <= 0.0) THIS->yspacing_scale=0.1; pop_stack(); }
b9284c1997-04-09Mirar (Pontus Hagland)  /* **! method int baseline() **! returns font baseline (pixels from top) **! see also: height, text_extents */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void font_baseline(INT32 args) { pop_n_elems(args); if (THIS) push_int(THIS->baseline); else push_int(0); } void font_set_center(INT32 args) { pop_n_elems(args); if(THIS) THIS->justification=J_CENTER; } void font_set_right(INT32 args) { pop_n_elems(args); if(THIS) THIS->justification=J_RIGHT; } void font_set_left(INT32 args) { pop_n_elems(args); if(THIS) THIS->justification=J_LEFT; } /***************** global init etc *****************************/ /* int load(string filename); // load font file, true is success object write(string text); // new image object int height(); // font heigth int baseline(); // font baseline */ void init_font_programs(void) { start_new_program(); add_storage(sizeof(struct font*)); add_function("load",font_load,
50a0d11997-03-09Henrik Grubbström (Grubba)  "function(string:object|int)",0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  add_function("write",font_write, "function(string:object)",0); add_function("height",font_height, "function(:int)",0); add_function("baseline",font_baseline, "function(:int)",0); add_function("extents",font_text_extents, "function(string ...:array(int))",0);
1f94161997-09-03Per Hedbor  add_function("text_extents",font_text_extents, "function(string ...:array(int))",0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  add_function("set_x_spacing",font_set_xspacing_scale, "function(float:void)",0); add_function("set_y_spacing",font_set_yspacing_scale, "function(float:void)",0); add_function("center", font_set_center, "function(void:void)", 0); add_function("left", font_set_left, "function(void:void)", 0); add_function("right", font_set_right, "function(void:void)", 0); set_init_callback(init_font_struct); set_exit_callback(exit_font_struct); font_program=end_program(); add_program_constant("font",font_program, 0); } void exit_font(void) { if(font_program) { free_program(font_program); font_program=0; } }