This commit is contained in:
Alexander Deynichenko
2013-02-25 07:23:44 +04:00
parent 35ff18a6a1
commit 03b62f3315
809 changed files with 211135 additions and 0 deletions

10
tools/src/Makefile.am Normal file
View File

@@ -0,0 +1,10 @@
SUBDIRS = af2rgb
bin_PROGRAMS = plibconvert
plibconvert_SOURCES = plibconvert.cxx
plibconvert_LDADD = -lplibssg -lplibsg -lplibul

View File

@@ -0,0 +1,8 @@
noinst_PROGRAMS = af2rgb
af2rgb_SOURCES = af2rgb.cxx
af2rgb_LDADD = -lplibssg -lplibsg -lplibul
EXTRA_DIST = af2rgb.dsp

206
tools/src/af2rgb/af2rgb.cxx Normal file
View File

@@ -0,0 +1,206 @@
// Convert textures made for MSFS to rgb textures.
// Written by Wolfram Kuss (w_kus@rz-online.de) in dec 2000 / jan 2001
// with some help by Marten Str<74>mberg.
//
// Published as part of Steve Baker's PLIB
// License is GPL
#include <stdlib.h>
#include <stdio.h>
#include <plib/ul.h>
#include <plib/ssgMSFSPalette.h>
// *.?af textures are always 256 x 256:
#define XSIZE 256
#define YSIZE 256
#define ZSIZE 4
static unsigned char texelsR [ XSIZE * YSIZE ];
static unsigned char texelsG [ XSIZE * YSIZE ];
static unsigned char texelsB [ XSIZE * YSIZE ];
static unsigned char texelsA [ XSIZE * YSIZE ];
static FILE *fd;
static size_t writeByte (unsigned char x )
{
return fwrite ( & x, sizeof(unsigned char), 1, fd ) ;
}
static size_t writeShort (unsigned short x )
{
if (ulIsLittleEndian) // this is the other way round compared to normally.
// obviously, this is because the .rgb format comes from SGI.
ulEndianSwap(&x);
return fwrite( & x, sizeof(unsigned short), 1, fd ) ;
}
static size_t writeInt (unsigned int x)
{
if (ulIsLittleEndian) // this is the other way round compared to normally.
// obviously, this is because the .rgb format comes from SGI.
ulEndianSwap(&x);
return fwrite( & x, sizeof(unsigned int), 1, fd ) ;
}
#define SGI_IMG_MAGIC 0x01DA
static int writeTexelsIntoSGI ( const char *fname )
{
fd = fopen ( fname, "wb" ) ;
size_t NoWritten = 0;
if ( fd == NULL )
{
ulSetError(UL_WARNING, "ssgLoadTexture: Failed to open '%s' for writing.", fname ) ;
return false;
}
// ******* write the header *****************
NoWritten += writeShort (SGI_IMG_MAGIC) ;
NoWritten += writeByte (0) ; // don't use RLE
NoWritten += writeByte (1) ; // bpp
NoWritten += writeShort (3) ; // dimension
NoWritten += writeShort ( XSIZE ) ;
NoWritten += writeShort ( YSIZE ) ;
NoWritten += writeShort ( ZSIZE ) ;
NoWritten += writeInt ( 0 ) ;
NoWritten += writeInt ( 255 ) ;
NoWritten += writeInt ( 0 ) ; /* Dummy field */
int i ;
for ( i = 0 ; i < 80 ; i++ )
NoWritten += writeByte ( 0 ) ; /* Name field */
NoWritten += writeInt ( 0 ) ; // colormap
for ( i = 0 ; i < 404 ; i++ )
NoWritten += writeByte ( 0 ) ; /* Dummy field */
// ************ write the body ****************
NoWritten += fwrite ( texelsR, XSIZE, YSIZE, fd ) ;
NoWritten += fwrite ( texelsG, XSIZE, YSIZE, fd ) ;
NoWritten += fwrite ( texelsB, XSIZE, YSIZE, fd ) ;
NoWritten += fwrite ( texelsA, XSIZE, YSIZE, fd ) ;
if(NoWritten!=91+404+4*YSIZE)
{ ulSetError(UL_WARNING, "Only %ld records written instead of %d. Proceed at your own risc\n",
(long)NoWritten, 91+404+4*YSIZE);
return false;
}
fclose ( fd ) ;
return true;
}
int loadMDLIntoTexels ( const char *fname )
// returns TRUE on success
{
FILE *tfile;
if ( (tfile = fopen(fname, "rb")) == NULL) {
ulSetError(UL_WARNING, "ssgLoadTexture: Failed to load '%s'.", fname );
return false;
}
fseek(tfile, 0, SEEK_END);
unsigned long file_length = ftell(tfile);
if (file_length != 65536) {
ulSetError(UL_WARNING, "ssgLoadTexture: Wrong size of '%s'.", fname );
return false;
} else {
fseek(tfile, 0, SEEK_SET);
int c = 0;
for (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
unsigned char b;
if ( fread(&b, 1, 1, tfile) != 1)
return false;
texelsR[c] = ssgFsTexPalette[b*4 ];
texelsG[c] = ssgFsTexPalette[b*4 + 1];
texelsB[c] = ssgFsTexPalette[b*4 + 2];
texelsA[c] = ssgFsTexPalette[b*4 + 3];
c++;
}
}
fclose(tfile);
}
return true;
}
void DoAllFiles( char *sDirectoryP )
{ char newname [ 1024 ], sDirectory[1024], sFullPath[1024]; // todo fixme
strcpy( sDirectory, sDirectoryP);
if ( ( sDirectoryP[ strlen(sDirectoryP)-1 ] != '\\') &&
( sDirectoryP[ strlen(sDirectoryP)-1 ] != '/') )
strcat( sDirectory, "/");
// ************** For all *.?af files in the current dir ************
ulDir* dirp = ulOpenDir(".");
if ( dirp != NULL )
{
ulDirEnt* dp;
while ( (dp = ulReadDir(dirp)) != NULL )
{
if ( !dp->d_isdir )
{ size_t len = strlen(dp->d_name );
if ( len >4 )
if ((dp->d_name[len-1] == 'f') || (dp->d_name[len-1] == 'F'))
if ((dp->d_name[len-2] == 'a') || (dp->d_name[len-2] == 'A'))
if ((dp->d_name[len-4] == '.') || (dp->d_name[len-4] == '.'))
{ strcpy( newname, dp->d_name );
unsigned int i;
for (i=0; i<len; i++)
newname [i] = tolower ( newname [i] );
newname[len-4] = newname[len-3];
newname[len-3] = '.';
newname[len-2] = 'r';
newname[len-1] = 'g';
newname[len] = 'b';
newname[len+1] = 0;
ulSetError(UL_DEBUG, "%s %s\n",dp->d_name, newname);
// ********** convert it **************
if ( loadMDLIntoTexels ( dp->d_name ))
{ strcpy(sFullPath, sDirectory);
strcat(sFullPath, newname);
writeTexelsIntoSGI ( sFullPath ); //lint !e534
}
}
}
}
ulCloseDir(dirp);
}
}
// converts all *.?af files from the current dir to *.rgb in the dir givven in the argument
int main(int argc, char* argv[])
{
if ( argc > 2 )
ulSetError(UL_WARNING, "All arguments after the first are ignored!" );
if ( argc >= 2 )
DoAllFiles( argv[1] );
else
DoAllFiles(".");
return 0;
}

102
tools/src/af2rgb/af2rgb.dsp Normal file
View File

@@ -0,0 +1,102 @@
# Microsoft Developer Studio Project File - Name="af2rgb" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=af2rgb - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "af2rgb.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "af2rgb.mak" CFG="af2rgb - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "af2rgb - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "af2rgb - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "af2rgb - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x407 /d "NDEBUG"
# ADD RSC /l 0x407 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg.lib ssg.lib ul.lib opengl32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\\"
!ELSEIF "$(CFG)" == "af2rgb - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x407 /d "_DEBUG"
# ADD RSC /l 0x407 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sg_d.lib ssg_d.lib ul_d.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\\"
!ENDIF
# Begin Target
# Name "af2rgb - Win32 Release"
# Name "af2rgb - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\af2rgb.cxx
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

18
tools/src/afm2txf/README Normal file
View File

@@ -0,0 +1,18 @@
It's definitely a tool of the "duct tape and fishing line" variety. :)
It expects to find a ghostscript interpreter and ImageMagick's "mogrify"
program on the command line, takes a .afm font metrics file as its sole
argument, and expects that the font therein is accessible to ghostscript.
Basically, it should work out of the box on most linux distributions,
and nowhere else without a lot of work.
If you have a TrueType font that you want to generate:
export GS_FONTPATH=<wherever the font is>
ttf2afm yourfont.ttf > whatever.afm
font.pl whatever.afm
Wait for a while (at 16x downsampling, this takes 1-2 minutes on my
Athlon 1800+), and the .txf file will appear in the current directory.
It will have the Postscript language name of the font.
Andy

283
tools/src/afm2txf/afm2txf.pl Executable file
View File

@@ -0,0 +1,283 @@
#!/usr/bin/perl -w
# afm2txf.pl 0.2
#
# Generates .txf font textures from Type 1 fonts
# Requirements: Ghostscript, ImageMagick
#
# Usage:
# afm2txf.pl whatever.afm
#
# Changelog:
# 0.2 (06/28/2002): Generate fonts with proper padding
# 0.1 (06/28/2002): Initial version
#
# Copyright (C) 2002 Andrew James Ross
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
use strict;
my $METRICS = shift or die; # AFM file
# Texture size
my $TEXSIZ = 256;
# Padding around each character, for mipmap separation
my $PADDING = 4;
# Antialiasing multiplier. Should be 16 for production work. As low
# as 4 works well for testing.
my $DOWNSAMPLE = 16;
# The 94 printable ASCII characters (and the space) and their
# postscript glyph names. We use names because not all postscript
# fonts are encoded using ASCII. AFM metrics generated by ttf2afm, in
# fact, don't have any numerical character IDs at all. In principle,
# this mechanism will work for any 8 bit font encoding, you just have
# to do the legwork of figuring out the name to ID mapping.
my %CHARS = ('space'=>32, 'exclam'=>33, 'quotedbl'=>34,
'numbersign'=>35, 'dollar'=>36, 'percent'=>37,
'ampersand'=>38, 'quotesingle'=>39, 'parenleft'=>40,
'parenright'=>41, 'asterisk'=>42, 'plus'=>43,
'comma'=>44, 'hyphen'=>45, 'period'=>46, 'slash'=>47,
'zero'=>48, 'one'=>49, 'two'=>50, 'three'=>51,
'four'=>52, 'five'=>53, 'six'=>54, 'seven'=>55,
'eight'=>56, 'nine'=>57, 'colon'=>58, 'semicolon'=>59,
'less'=>60, 'equal'=>61, 'greater'=>62, 'question'=>63,
'at'=>64, 'A'=>65, 'B'=>66, 'C'=>67, 'D'=>68, 'E'=>69,
'F'=>70, 'G'=>71, 'H'=>72, 'I'=>73, 'J'=>74, 'K'=>75,
'L'=>76, 'M'=>77, 'N'=>78, 'O'=>79, 'P'=>80, 'Q'=>81,
'R'=>82, 'S'=>83, 'T'=>84, 'U'=>85, 'V'=>86, 'W'=>87,
'X'=>88, 'Y'=>89, 'Z'=>90, 'bracketleft'=>91,
'backslash'=>92, 'bracketright'=>93, 'asciicircum'=>94,
'underscore'=>95, 'grave'=>96, 'a'=>97, 'b'=>98, 'c'=>99,
'd'=>100, 'e'=>101, 'f'=>102, 'g'=>103, 'h'=>104,
'i'=>105, 'j'=>106, 'k'=>107, 'l'=>108, 'm'=>109,
'n'=>110, 'o'=>111, 'p'=>112, 'q'=>113, 'r'=>114,
's'=>115, 't'=>116, 'u'=>117, 'v'=>118, 'w'=>119,
'x'=>120, 'y'=>121, 'z'=>122, 'braceleft'=>123,
'bar'=>124, 'braceright'=>125, 'asciitilde'=>126);
my %metrics = ();
my %positions = ();
#
# Parse the font metrics. This is a 5 element array. All numbers are
# expressed as a fraction of the line spacing.
# 0: nominal width (distance to the next character)
# 1, 2: Coordinates of the lower left corner of the bounding box,
# relative to the nominal position.
# 3, 4: Size of the bounding box
#
print STDERR "Reading font metrics...\n";
my $FONT;
my @lines = `cat $METRICS`
or die "Couldn't read metrics";
foreach my $m (grep {/^(C|FontName) /} @lines) {
chomp $m;
if($m =~ /^FontName ([^\s]*)/) { $FONT = $1; next; }
die "No name: $m" if $m !~ /N\s+([^\s]+)\s+;/;
my $name = $1;
die "No box: $m"
if $m !~ /B\s+([-0-9]+)\s+([-0-9]+)\s+([-0-9]+)\s+([-0-9]+)\s+;/;
my ($left, $bottom, $right, $top) = ($1/1000, $2/1000, $3/1000, $4/1000);
die "No width: $m" if $m !~ /WX\s+([-0-9]+)/;
my $nomwid = $1/1000; # nominal, not physical width!
# The coordinates of the corner relative to the character
# "position"
my ($x, $y) = (-$left, -$bottom);
my ($w, $h) = ($right-$left, $top-$bottom);
$metrics{$name} = [$nomwid, $x, $y, $w, $h];
}
die "No FontName found in metrics" if not defined $FONT;
#
# Find the height of the tallest character, and print some warnings
#
my $maxhgt = 0;
foreach my $c (keys %CHARS) {
if(!defined $metrics{$c}) {
print STDERR "% WARNING: no metrics for char $c. Skipping.\n";
next;
}
if($metrics{$c}->[4] > $maxhgt) { $maxhgt = $metrics{$c}->[4]; }
}
if($maxhgt == 0) {
print STDERR "No usable characters found. Bailing out.\n";
exit 1;
}
#
# Do the layout. Keep increasing the row count until the characters
# just fit. This isn't terribly elegant, but it's simple.
#
print STDERR "Laying out";
my $rows = 1;
my $PS;
my $LINEHGT;
while(!defined ($PS = genPostscript($rows))) { $rows++; }
print STDERR " ($rows rows)\n";
#
# Call ghostscript to render
#
print STDERR "Rendering Postscript...\n";
my $res = $TEXSIZ * $DOWNSAMPLE;
my $pid = open PS, "|gs -r$res -g${res}x${res} -sDEVICE=ppm -sOutputFile=$FONT.ppm > /dev/null";
die "Couldn't spawn ghostscript interpreter" if !defined $pid;
print PS join("\n", @$PS), "\n";
close PS;
waitpid($pid, 0);
#
# Downsample with ImageMagick
#
print STDERR "Antialiasing image...\n";
system("mogrify -geometry ${TEXSIZ}x${TEXSIZ} $FONT.ppm") == 0
or die "Couldn't rescale $FONT.ppm";
#
# Generate the .txf file
#
print STDERR "Generating textured font file...\n";
# Prune undefined glyphs
foreach my $c (keys %metrics) {
delete $metrics{$c} if !defined $CHARS{$c};
}
sub round { sprintf "%.0f", $_[0] }
open TXF, ">$FONT.txf" or die;
print TXF pack "V", 0x667874ff;
print TXF pack "V", 0x12345678;
print TXF pack "V", 0;
print TXF pack "V", $TEXSIZ;
print TXF pack "V", $TEXSIZ;
print TXF pack "V", round($TEXSIZ * $LINEHGT);
print TXF pack "V", 0;
print TXF pack "V", scalar(keys(%metrics));
my @chars = sort { $CHARS{$a} <=> $CHARS{$b} } (keys %metrics);
foreach my $c (@chars) {
my $m = $metrics{$c};
my $p = $positions{$c};
my $step = round($m->[0] * $LINEHGT * $TEXSIZ);
# Pad the bounding box, to handle areas that outside. This can
# happen due to thick lines in the font path, or be an artifact of
# the downsampling.
my $w = round($m->[3] * $LINEHGT * $TEXSIZ + 2*$PADDING);
my $h = round($m->[4] * $LINEHGT * $TEXSIZ + 2*$PADDING);
my $xoff = -round($m->[1] * $LINEHGT * $TEXSIZ - $PADDING);
my $yoff = -round($m->[2] * $LINEHGT * $TEXSIZ - $PADDING);
my $x = round($p->[0] * $TEXSIZ - $PADDING);
my $y = round($p->[1] * $TEXSIZ - $PADDING);
print TXF pack "v", $CHARS{$c};
print TXF pack "C", $w;
print TXF pack "C", $h;
print TXF pack "c", $xoff;
print TXF pack "c", $yoff;
print TXF pack "C", $step;
print TXF pack "C", 0;
print TXF pack "v", $x;
print TXF pack "v", $y;
}
# Read in the .ppm file, dump the duplicate color values (ghostscript
# won't generate pgm's) and write to the end of the .txf. Remember to
# swap the order of the rows; OpenGL textures are bottom-up.
open PPM, "$FONT.ppm" or die;
seek PPM, -3*$TEXSIZ*$TEXSIZ, 2 or die;
my @rows = ();
my $pixel;
for(my $r=0; $r<$TEXSIZ; $r++) {
my @row = ();
for(my $c=0; $c<$TEXSIZ; $c++) {
read PPM, $pixel, 3 or die;
push @row, substr($pixel, 0, 1);
}
push @rows, \@row;
}
close PPM;
for(my $r=(@rows - 1); $r>=0; $r--) {
print TXF join('', @{$rows[$r]});
}
close TXF;
# Clean up
#system("rm $FONT.ppm");
########################################################################
########################################################################
########################################################################
sub genPostscript {
my $rows = shift;
my $rowhgt = 1/$rows;
my @PS = ();
# The canonical "point size" number, in texture space
$LINEHGT = ($rowhgt - 2*$PADDING/$TEXSIZ) / $maxhgt;
# Get to where we want. Draw the whole thing in a 1 inch square at
# the bottom left of the "page".
push @PS, "72 72 scale";
# Fill the square with black
push @PS, "0 setgray";
push @PS, "-1 -1 moveto";
push @PS, "-1 1 lineto 1 1 lineto 1 -1 lineto";
push @PS, "closepath";
push @PS, "fill";
# Draw in white
push @PS, "1 setgray";
# Generate our PUSH @PS, font
push @PS, "/$FONT findfont $LINEHGT scalefont setfont";
my $x = $PADDING/$TEXSIZ;
my $y = 1 - $rowhgt + $PADDING/$TEXSIZ;
my @chars = sort { $CHARS{$a} <=> $CHARS{$b} } (keys %CHARS);
foreach my $c (@chars) {
my $m = $metrics{$c};
next if !defined $m;
my $id = sprintf "%2.2x", $CHARS{$c};
# No space?
my $w = $m->[3]*$LINEHGT;
if($x + $w + $PADDING/$TEXSIZ > 1) {
$x = $PADDING/$TEXSIZ;
$y -= $rowhgt;
return undef if $y < 0;
}
# Record where in the texture the box ended up
$positions{$c} = [$x, $y];
my $vx = $x + $m->[1]*$LINEHGT;
my $vy = $y + $m->[2]*$LINEHGT;
push @PS, "$vx $vy moveto";
push @PS, "<$id> show";
# Next box...
$x += $w + 2*$PADDING/$TEXSIZ;
}
push @PS, "showpage";
return \@PS;
}

99
tools/src/plibconvert.cxx Normal file
View File

@@ -0,0 +1,99 @@
// plibconvert.cxx
//
// Written by Bram Stolk
// Published as part of Steve Baker's PLIB under GPL
//
// Build with :
// g++ -o plibconvert plibconvert.cxx -lplibssg -lplibsg -lplibul -lGL
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glx.h>
#include <plib/ssg.h>
int main(int argc, char *argv[])
{
if (argc!=3)
{
fprintf(stderr,"Usage: %s source destination\n", argv[0]);
exit(1);
}
assert(strcmp(argv[1], argv[2]));
#ifdef GLX_VERSION_1_3
// Although we will not be doing any rendering, we must create
// a valid rendering context before we can call ssgInit()
Display *dpy = XOpenDisplay(0);
int scn=DefaultScreen(dpy);
int cnt;
GLXFBConfig *configs = glXGetFBConfigs(dpy, scn, &cnt);
if (!configs)
{
perror("glXGetFBConfigs");
exit(1);
}
fprintf(stderr,"glXGetFBConfigs returned %p (%d matches)\n", configs, cnt);
assert(cnt);
GLXFBConfig fbc = configs[0];
XVisualInfo *vinf = glXGetVisualFromFBConfig(dpy, fbc);
if (!vinf)
{
perror("glXGetVisualFromFBConfig");
exit(1);
}
fprintf
(
stderr,
"visualid=0x%lx (depth=%d,R/G/B=%lx/%lx/%lx)\n",
vinf->visualid,
vinf->depth,
vinf->red_mask,
vinf->green_mask,
vinf->blue_mask
);
GLXContext cx = glXCreateNewContext(dpy, fbc, GLX_RGBA_TYPE, 0, GL_TRUE);
if (!cx)
{
perror("glXCreateNewContext");
exit(1);
}
else
{
fprintf(stderr,"glX context created\n");
}
int attrlist[] =
{
GLX_PBUFFER_WIDTH, 1,
GLX_PBUFFER_HEIGHT, 1,
0
};
GLXPbuffer pBuffer = glXCreatePbuffer(dpy, fbc, attrlist);
fprintf(stderr,"pBuffer = %lx\n", pBuffer);
bool ok=glXMakeContextCurrent(dpy, pBuffer, pBuffer, cx);
if (!ok)
{
perror("glXMakeContextCurrent");
exit(1);
}
// Initialize plib
fprintf(stderr,"Initializing plib...\n");
ssgInit();
ssgTexturePath ( "." ) ;
ssgModelPath ( "." ) ;
ssgEntity *e = ssgLoad(argv[1]); // Load
e->print(stdout); // Inform
ssgSave(argv[2], e); // Store
#else
fprintf(stderr,"This util uses a pbuffer as context for plib. To build the source, you need glx protocol 1.3 or higher.\n");
#endif
}

93
tools/src/txfdump/txfdump.pl Executable file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/perl -w
use strict;
## txfdump.pl - A .txf font file parser and image extractor
##
## Usage: txfdump.pl blahblah.txf
##
## Human readable font metric information will be printed to stdout,
## and a blahblah.pgm file will be written containing the texture
## image from the file. Note that the resulting image will be
## vertically reflected, owing to the difference between cartesian x/y
## coordinates used by .txf and the screen raster convention of the
## .pgm format (well, and the author's laziness). Load it up in your
## favorite viewer and flip it if you care.
##
## Copyright (C) 2002 Andrew James Ross
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License version 2 as
## published by the Free Software Foundation.
my $file = shift or die;
open TXF, $file or die;
# Start out assuming intel byte order
# These get used in the getshort/getint functions below
my $shortType = "v";
my $longType = "V";
sub getsbyte { my $v=getbyte(); if($v>127) { $v-=256; } return $v; }
sub getbyte { my $val; read TXF, $val, 1 or die; return ord $val; }
sub getshort { my $val; read TXF, $val, 2 or die; return unpack $shortType, $val; }
sub getint { my $val; read TXF, $val, 4 or die; return unpack $longType, $val; }
# Check the magic number; it is endian-independant
my $magic = sprintf "0x%8.8x", getint();
die "Bad magic number ($magic)" if $magic ne "0x667874ff";
# Read the next four bytes to determine endianness
my $endian = sprintf "0x%8.8x", getint();
if($endian eq "0x12345678") {
} elsif($endian eq "0x78563412") {
# Network byte order
$shortType = "n";
$longType = "N";
} else {
die "Bad endianness tag ($endian)";
}
# Read the rest of the header
my $format = getint();
my $texwid = getint();
my $texhgt = getint();
my $linehgt = getint();
my $unk = getint();
my $nglyph = getint();
printf "Magic $magic Endian $endian Format 0x%8.8x\n", $format;
print "Texture: ${texwid}x$texhgt Line: $linehgt Glyphs: $nglyph Unk: $unk\n";
# Read each glyph's metadata
for(my $i=0; $i<$nglyph; $i++) {
print "Glyph $i\n";
my $c = getshort();
print " char: $c ('", chr($c), "')\n";
print " width: ", getbyte(), "\n";
print " height: ", getbyte(), "\n";
print " xoff: ", getsbyte(), "\n";
print " yoff: ", getsbyte(), "\n";
print " step: ", getbyte(), "\n";
print " unk: ", getbyte(), "\n";
print " X: ", getshort(), "\n";
print " Y: ", getshort(), "\n";
}
# The rest of the file is an image. Write it out as a .pgm file with
# the same name as the font file.
$file =~ s/\.txf$/.pgm/;
open PGM, ">$file" or die;
print PGM "P2\n$texwid $texhgt\n255\n";
if($format == 0) {
for(my $i=0; $i<($texwid*$texhgt); $i++) { print PGM getbyte(), " "; }
} else {
for(my $i=0; $i<($texwid*$texhgt/8); $i++) {
my $byte = getbyte();
for(my $j=0; $j<8; $j++) {
print PGM ($byte & (1<<$j)) ? "255 " : "0 ";
}
}
}