38d0972000-09-04Per Hedbor #include <config.h> #include <stat.h>
fad0b72000-09-16Martin Nilsson constant cvs_version = "$Id: imagedir.pike,v 1.5 2000/09/16 20:43:31 nilsson Exp $";
38d0972000-09-04Per Hedbor  constant name = "Image directory fonts"; constant doc = ("Handles a directory with images (in almost any format), each "
e892262000-09-04Per Hedbor  "named after the character they will represent. Characters " "with codes larger than 127 or less than 48 are encoded like "
0bd4d92000-09-04Per Hedbor  "0xHEX where HEX is the code in hexadecimal. There must be a " "file named 'fontname' in the directory, the first line of " "that file is used as the name of the font");
38d0972000-09-04Per Hedbor  inherit FontHandler;
e892262000-09-04Per Hedbor #ifdef THREADS Thread.Mutex lock = Thread.Mutex(); #endif
b5aa9c2000-09-04Per Hedbor static mapping nullchar = ([ "image":Image.Image(1,1), "alpha":Image.Image(1,1) ]); static mapping spacechar = ([ "image":Image.Image(10,1), "alpha":Image.Image(10,1) ]); static mapping smallspacechar = ([ "image":Image.Image(2,1), "alpha":Image.Image(2,1) ]);
38d0972000-09-04Per Hedbor class myFont { inherit Font; static string path; static int size, rsize; static array files; static string _sprintf() { return sprintf( "FontDir(%O,%d)", path, height() ); } static string encode_char( string c ) {
e892262000-09-04Per Hedbor  int cc = c[0]; if( (cc < 48) || (cc > 127) ) return sprintf( "0x%x", cc ); return c;
38d0972000-09-04Per Hedbor  } static mapping(string:Image.Image) load_char( string c ) {
b5aa9c2000-09-04Per Hedbor  if( c[0] == 0x120 ) return smallspacechar;
38d0972000-09-04Per Hedbor  if(!files) files = get_dir( path ) - ({ "fontname" });
e892262000-09-04Per Hedbor  array possible = ({ encode_char(c) })+ glob(encode_char( c )+".*", files); sort( map(possible,strlen), possible );
38d0972000-09-04Per Hedbor  foreach( possible, string pf ) if( mapping r = Image._load( path+pf ) ) return r;
b5aa9c2000-09-04Per Hedbor  if( c == " " ) return spacechar;
38d0972000-09-04Per Hedbor  return nullchar; } mapping(string:mapping(string:Image.Image)) char_cache = ([]); static mapping(string:Image.Image) write_char( string c ) { if( char_cache[ c ] ) return char_cache[ c ]; return char_cache[ c ] = load_char( c ); } static Image.Image write_row( string text ) { array(mapping(string:Image.Image)) res = map( text/"", write_char ); Image.Image rr=Image.Image((int)abs(`+(0,@res->image->xsize())*x_spacing), max(0,@res->image->ysize())); float start; if( x_spacing < 0 ) start = (float)rr->xsize()-res[0]->image->xsize(); foreach( res, mapping(string:Image.Image) r ) { if( !r->image ) continue; if( r->alpha ) rr->paste_mask(r->image,r->alpha, (int)start,rr->ysize()-r->image->ysize() ); else rr->paste(r->image,(int)start,rr->ysize()-r->image->ysize()); start += r->image->xsize()*x_spacing; } return rr; } int height() { return rsize ? rsize : (rsize = text_extents("0WjI|9")[1] ); } Image.Image write( string ... what ) { array(Image.Image) res = map( what, write_row ); Image.Image rr = Image.Image( max(0,@res->xsize()), (int)abs(`+(0,@res->ysize())*y_spacing) ); float start; if( y_spacing < 0 ) start = (float)rr->ysize()-res[0]->ysize(); foreach( res, object r ) { if( j_right ) rr->paste(r,rr->xsize()-r->xsize(),(int)start); else if( j_center ) rr->paste(r,(rr->xsize()-r->xsize())/2,(int)start); else rr->paste( r, 0, (int)start ); start += r->ysize()*y_spacing; } return rr; } array text_extents( string what ) { Image.Image o = write( what ); return ({ o->xsize(), o->ysize() }); } void create( string _path, int _size ) { path = _path; size = _size; } } mapping font_list;
fad0b72000-09-16Martin Nilsson mapping meta_data;
38d0972000-09-04Per Hedbor static string font_name( string what ) {
fad0b72000-09-16Martin Nilsson  if(!meta_data) meta_data=([]); mapping _meta_data=([]); Parser.HTML()-> add_containers( ([ "name":lambda(string t, mapping m, string c) { what=c; return ""; }, "meta":lambda(string t, mapping m, string c) { _meta_data[m->name]=c; }, ]) )->finish(what); what=(lower_case( replace(what," ","_") )/"\n")[0]-"\r"; if(sizeof(_meta_data)) meta_data[what]=_meta_data; return what;
38d0972000-09-04Per Hedbor } void update_font_list() { font_list = ([]); foreach(roxen->query("font_dirs"), string dir) foreach( (get_dir( dir )||({})), string d ) if( file_stat( dir+d )[ ST_SIZE ] == -2 ) // isdir if( file_stat( dir+d+"/fontname" ) ) font_list[font_name(Stdio.read_bytes(dir+d+"/fontname"))]=dir+d+"/"; } array available_fonts() {
e892262000-09-04Per Hedbor #ifdef THREADS object key = lock->lock(); #endif
38d0972000-09-04Per Hedbor  array res = ({}); if( !font_list ) update_font_list(); return indices( font_list ); } array(mapping) font_information( string fnt ) {
e892262000-09-04Per Hedbor #ifdef THREADS object key = lock->lock(); #endif
38d0972000-09-04Per Hedbor  if( !font_list ) update_font_list(); if( font_list[ fnt ] )
fad0b72000-09-16Martin Nilsson  return ({ (meta_data[fnt] || ([])) | ([
38d0972000-09-04Per Hedbor  "name":fnt, "family":fnt, "path":font_list[fnt], "format":"imagedir", ]) }); return ({}); } array has_font( string name, int size ) {
e892262000-09-04Per Hedbor #ifdef THREADS object key = lock->lock(); #endif
38d0972000-09-04Per Hedbor  if( !font_list ) update_font_list(); if( font_list[ name ] ) return ({ "nn" }); } Font open( string name, int size, int bold, int italic ) {
e892262000-09-04Per Hedbor #ifdef THREADS object key = lock->lock(); #endif
38d0972000-09-04Per Hedbor  if( !font_list ) update_font_list(); if( font_list[ name ] ) return myFont( font_list[name], size ); } void create() { roxen.getvar( "font_dirs" ) ->add_changed_callback( lambda(Variable.Variable v){ font_list = 0; } ); }