Roxen.git
/
server
/
font_handlers
/
compactimgfile.pike
version
»
Context lines:
10
20
40
80
file
none
3
Roxen.git/server/font_handlers/compactimgfile.pike:1:
+
#include <config.h>
+
inherit "imagetar";
+
constant name = "Compact image file font";
+
constant doc =
+
#"A compact image file.
+
The format is very simple:
+
<pre>
+
'CIF1' (4 bytes magic)
+
'fontname' (64 bytes name, \\0 terminated)
+
for each char:
+
char (4 bytes charcode)
+
len (4 bytes image length)
+
len bytes data
+
</pre>
+
All integers are NBO<p>
+
There is a small program included in bin (createcif.pike) that
+
creates a cif font from an imagedir or imagetar font</p>";
-
+
class StringFile
+
{
+
string data;
+
int offset;
+
+
string _sprintf()
+
{
+
return "StringFile("+strlen(data)+","+offset+")";
+
}
+
+
string read(int nbytes)
+
{
+
if(!nbytes)
+
{
+
offset = strlen(data);
+
return data;
+
}
+
string d = data[offset..offset+nbytes-1];
+
offset += strlen(d);
+
return d;
+
}
+
+
void write(mixed ... args)
+
{
+
throw( ({ "File not open for write\n", backtrace() }) );
+
}
+
+
void seek(int to)
+
{
+
offset = to;
+
}
+
+
void create(string d)
+
{
+
data = d;
+
}
+
}
+
+
class CIF
+
{
+
Stdio.File fd;
+
array filelist ;
+
mapping offsets;
+
array get_dir( string f )
+
{
+
// #ifdef THREADS
+
// object lock = lock->trylock();
+
// #endif
+
if(!filelist)
+
{
+
offsets = ([]);
+
filelist = ({ "/fontname" });
+
+
fd->seek( 64 + 4 ); // header.
+
int c;
+
while( c = getint() )
+
{
+
offsets[c] = fd->tell();
+
if( c < 48 || c > 127 )
+
if( c == 0xffffffff )
+
filelist += ({ "/fontinfo" });
+
else
+
filelist += ({ sprintf( "/0x%x", c ) });
+
else
+
filelist += ({ sprintf( "/%c", c ) });
+
fd->read( getint() ); // skip data.
+
}
+
}
+
return filelist;
+
}
+
+
int getint( )
+
{
+
int c;
+
sscanf( fd->read( 4 ), "%4c", c );
+
return c;
+
}
+
+
object open( string fname, string mode )
+
{
+
// #ifdef THREADS
+
// object lock = lock->trylock();
+
// #endif
+
if(!offsets) get_dir( "foo" );
+
fname -= "/";
+
if( fname == "fontname" )
+
{
+
fd->seek( 4 );
+
return StringFile( fd->read( 64 )-"\0" );
+
}
+
// werror("open "+fname+"\n");
+
int wc;
+
sscanf( fname, "%s.", fname );
+
if( strlen(fname) > 2 ) sscanf( fname, "0x%x", wc ); else wc=fname[0];
+
int c;
+
+
if( fname == "fontinfo" ) wc = 0xffffffff;
+
+
if( offsets[ wc ] )
+
{
+
fd->seek( offsets[ wc ] );
+
return StringFile( fd->read( getint() ) );
+
}
+
return 0;
+
}
+
+
void create( string fname )
+
{
+
fd = Stdio.File( );
+
if( !fd->open( fname, "r" ) ) error( "Illegal CIF\n");
+
if( fd->read( 4 ) != "CIF1" ) error( "Illegal CIF\n");
+
}
+
}
+
+
mapping(string:CIF) cif_cache = ([]);
+
CIF open_tar( string path )
+
{
+
CIF res;
+
if( cif_cache[ path ] )
+
return cif_cache[ path ];
+
if( !catch { res= CIF( path ); } )
+
cif_cache[ path ] = res;
+
while( sizeof( cif_cache ) > 10 )
+
{
+
array q = indices( cif_cache );
+
string w = q[ random( sizeof(q) ) ];
+
if( w != path )
+
m_delete( cif_cache, w );
+
}
+
return open_tar( path );
+
}
+
+
array(mapping) font_information( string fnt )
+
{
+
array res = ::font_information( fnt );
+
if( sizeof( res ) ) res[0]->format = "cif";
+
return res;
+
}
+
+
void update_font_list()
+
{
+
font_list = ([]);
+
void rec_find_in_dir( string dir )
+
{
+
foreach( get_dir( dir )||({}), string pd )
+
{
+
if( file_stat( dir+pd )[ ST_SIZE ] == -2 ) // isdir
+
rec_find_in_dir( dir+pd+"/" );
+
else if( glob( "*.cif", pd ) )
+
{
+
CIF t = open_tar( dir+pd );
+
if( Stdio.File f = t->open( "fontname", "r" ) )
+
font_list[font_name( f->read() )] = dir+pd;
+
else
+
destruct( t );
+
}
+
}
+
};
+
+
foreach(roxen->query("font_dirs"), string dir)
+
rec_find_in_dir( dir );
+
}
Newline at end of file added.