home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
443.lha
/
fontwo
/
fontwo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-02
|
9KB
|
326 lines
/* fontwo.c
* Double the height or width of an Amiga font
* (C)1989 Ephraim Cohen
*
* Compile (Manx Aztec 3.6):
* cc +l fontwo.c
* ln fontwo.o -lc32
*/
#include <libraries/diskfont.h>
#include <libraries/dos.h>
#include <stdio.h>
#define REV 33
char *note[]= {
"Usage: option font height [Attributes]",
"Options:",
"t Make a tall font (double the height)",
"w Make a wide font (double the width)",
"The name of the new font ends with 'x'",
"For example",
"\tfontwo t Topaz 8",
"will create the font Fonts:Topaz/16wx",
"Attributes:",
"e Extended", "i Italic", "b Bold", "u Underline",
"t Tall Dot", "w Wide Dot", "p Proportional",
0};
extern struct TextFont *OpenDiskFont();
extern char *malloc(),
*OpenLibrary();
char *GfxBase,
*DiskfontBase;
char noroom[]= "Not Enough Memory";
char *fontab; /* The new font body */
long attab[20]; /* Relocation information */
struct TextAttr tea;
struct TextFont *tfp;
struct TextFont new;
struct DiskFontHeader dfh;
getfont(ta)struct TextAttr *ta;{ /* Get a font with these attributes */
register struct TextFont *tf;
ta->ta_Flags |= FPF_ROMFONT|FPF_DISKFONT|FPF_DESIGNED;
if(tf= OpenDiskFont(ta)){
endfont();
tfp= tf;
return TRUE;
}
return 0;
}
endfont(){ /* Done with this font */
if(tfp)CloseFont(tfp); tfp= 0;
}
char *outname(tf, name)register struct TextFont *tf; char *name;{
/* Create a name for the new font
* It is the font height, followed by some letters for
* the attributes, and followed by 'x' (because it's new)
*/
static char buf[80], attr[12];
register char *cp= attr;
if(tf->tf_Style&FSF_EXTENDED)*cp++= 'e';
if(tf->tf_Style&FSF_ITALIC)*cp++= 'i';
if(tf->tf_Style&FSF_BOLD)*cp++= 'b';
if(tf->tf_Style&FSF_UNDERLINED)*cp++= 'u';
if(tf->tf_Flags&FPF_TALLDOT)*cp++= 't';
if(tf->tf_Flags&FPF_WIDEDOT)*cp++= 'w';
if(tf->tf_Flags&FPF_PROPORTIONAL)*cp++= 'p';
*cp= 0;
sprintf(buf, "Fonts:%s/%d%sx", name, tf->tf_YSize, attr);
return buf;
}
getatts(name, hi, cp)register char *cp;{
/* Setup the TextAttr from the arguments */
static char buf[64];
strcpy(buf, name); strcat(buf, ".font");
tea.ta_Name= (STRPTR)buf;
tea.ta_YSize= hi;
tea.ta_Style= 0;
tea.ta_Flags= 0;
if(cp)while(*cp)switch(toupper(*cp++)){
case 'E': tea.ta_Style |= FSF_EXTENDED; break;
case 'I': tea.ta_Style |= FSF_ITALIC; break;
case 'B': tea.ta_Style |= FSF_BOLD; break;
case 'U': tea.ta_Style |= FSF_UNDERLINED; break;
case 'T': tea.ta_Flags |= FPF_TALLDOT; break;
case 'W': tea.ta_Flags |= FPF_WIDEDOT; break;
case 'P': tea.ta_Flags |= FPF_PROPORTIONAL; break;
}
}
char *
opelib(name)char *name;{ /* Open a library--complain if it's absent */
register char *lib;
aver(lib= OpenLibrary(name,REV), name);
return lib;
}
openlibs(){ /* Get these libraries */
GfxBase= opelib("graphics.library");
DiskfontBase= opelib("diskfont.library");
}
main(ac,av)register char **av;{
BPTR fd; /* File pointer */
register size, /* size of fontab */
fun; /* Function (Taller or Wider) */
if(ac<3){
err: for(av= note; *av; ++av)
printf("%s\n", *av);
exit(5);
}
getatts(av[2], atoi(av[3]), ac>4? av[4]:0);
fun= toupper(av[1][0]);
/* Must be Taller or Wider */
if(fun!='T' && fun!='W')goto err;
openlibs(); /* Get a font */
getfont(&tea);
aver(tfp, "No such font/size");
if(fun=='T')taller(tfp); /* Make a taller version */
else wider(tfp); /* or a wider version */
aver(size= makefont(&new), noroom); /* >>> */
fd= Open(outname(&new, av[2]), MODE_NEWFILE); /* Write it out */
aver(fd, "Cannot create the new font");
aver(writehunx(fd, fontab, size), "Write failed");
Close(fd);
aver(0,0); /* All done */
}
aver(bool, msg)char *msg;{ /* Quit cleanly if bool is false */
if(bool)return;
if(msg)printf("?%s\n", msg);
endfont();
if(GfxBase)CloseLibrary(GfxBase);
if(DiskfontBase)CloseLibrary(DiskfontBase);
exit(msg? 5:0);
}
taller(tf)register struct TextFont *tf;{ /* Double the height */
register char *sp, *dp;
register x,y;
new= *tf; /* Copy the original */
new.tf_YSize *= 2; /* Double height */
new.tf_Baseline *= 2;
if(new.tf_Flags&FPF_TALLDOT) /* It's a wider font now */
new.tf_Flags &= ~FPF_TALLDOT;
else new.tf_Flags |= FPF_WIDEDOT;
aver(dp= (char *)malloc(new.tf_YSize*new.tf_Modulo),noroom);
new.tf_CharData= (APTR)dp; /* Copy the character data */
sp= (char *)(tf->tf_CharData);
for(y= 0; y<tf->tf_YSize; y++){ /* For each scanline: */
for(x= 0; x<tf->tf_Modulo; x++) /* Copy it once */
*dp++= *sp++;
sp -= tf->tf_Modulo;
for(x= 0; x<tf->tf_Modulo; x++) /* and copy it again */
*dp++= *sp++;
}
}
APTR duexshort(wp, n)register unsigned short *wp;{
/* Copy and double all the values in a table of unsigned shorts */
register unsigned short *dp, *dp0;
aver(dp0= dp= (unsigned short *)malloc(n*sizeof(short)), noroom);
do
*dp++= (*wp++) << 1;
while(--n);
return (APTR)dp0;
}
wider(tf)register struct TextFont *tf;{
unsigned short widtab[256];
register unsigned char *cp;
register unsigned short *wp;
register x,y;
new= *tf; /* Copy the original */
new.tf_Modulo *= 2;
new.tf_XSize *= 2;
if(new.tf_Flags&FPF_WIDEDOT) /* It's a taller font now */
new.tf_Flags &= ~FPF_WIDEDOT;
else new.tf_Flags |= FPF_TALLDOT;
for(x= 0; x<256; x++){ /* Make the widening table: */
widtab[x]= 0; /* (Look up a byte, get a bbyyttee) */
for(y= 0; y<8; y++)
if(x&(1<<y))
widtab[x] |= 3 << (y+y);
}
/* space for the new character data */
wp= (unsigned short *)malloc(new.tf_YSize*new.tf_Modulo);
aver(wp ,noroom);
new.tf_CharData= (APTR)wp; /* Copy and widen: */
cp= (unsigned char *)(tf->tf_CharData);
for(y= 0; y<tf->tf_YSize; y++) /* For each (long) scanline */
for(x= 0; x<tf->tf_Modulo; x++)
*wp++= widtab[*cp++]; /* Widen chars to shorts */
y= tf->tf_HiChar + 2 - tf->tf_LoChar; /* Number of chars in font */
/* Widen and copy the other tables */
new.tf_CharLoc= duexshort(tf->tf_CharLoc, y+y);
if(tf->tf_CharSpace)
new.tf_CharSpace= duexshort(tf->tf_CharSpace, y);
if(tf->tf_CharKern)
new.tf_CharKern= duexshort(tf->tf_CharKern, y);
}
addr(at, cp)long *at; char *cp;{
/* Add a relocation datum, in hackish imitation of an assembler */
/* When loaded, the contents of at is the address of cp */
*at= cp-fontab; /* Location gets offset to data */
cp= (char *)at;
attab[attab[1]+3]= cp-fontab; /* Offset to location */
++attab[1]; /* Count of relocated stuff */
}
char *
bcopy(dp, sp, n)register char *dp, *sp;{
/* Copy and return past end of copy */
do
*dp++= *sp++;
while(--n);
return dp;
}
makefont(tf)register struct TextFont *tf;{
/* Put together the pieces for a font */
static char rts[]= {0x70, 0xff, 0x4e, 0x75}; /* rts instruction */
register struct DiskFontHeader *dfh;
register char *cp, *name;
register n, size;
/* This is the relocation hunk--start it empty */
attab[0]= 0x3EC; attab[1]= 0; attab[2]= 0;
/* How long is the font? */
n= tf->tf_HiChar + 2 - tf->tf_LoChar;
size= 4 + sizeof(*dfh) + tf->tf_Modulo*tf->tf_YSize + 4*n;
if(tf->tf_CharSpace)size+= sizeof(short)*n;
if(tf->tf_CharKern)size+= sizeof(short)*n;
fontab= (char *)malloc(size); /* Get and clear the font space */
if(!fontab)return 0;
cp= fontab+size;
do
*--cp= 0;
while(cp>fontab);
/* Start with 'return 0' (fonts look just like executables) */
bcopy(fontab, rts, 4);
/* Next comes this structure: */
dfh= (struct DiskFontHeader *)(&fontab[4]);
dfh->dfh_DF.ln_Type= NT_FONT;
addr(&dfh->dfh_DF.ln_Name, dfh->dfh_Name);
dfh->dfh_FileID= DFH_ID;
dfh->dfh_Revision= 1;
dfh->dfh_Segment= 0;
strncpy(dfh->dfh_Name,tf->tf_Message.mn_Node.ln_Name,MAXFONTNAME);
dfh->dfh_TF= *tf;
dfh->dfh_TF.tf_Message.mn_Node.ln_Succ= 0;
dfh->dfh_TF.tf_Message.mn_Node.ln_Pred= 0;
dfh->dfh_TF.tf_Message.mn_Node.ln_Type= NT_FONT;
addr(&dfh->dfh_TF.tf_Message.mn_Node.ln_Name, dfh->dfh_Name);
dfh->dfh_TF.tf_Message.mn_ReplyPort= 0;
dfh->dfh_TF.tf_Accessors= 0;
/* Now comes font data--copy it in */
cp= fontab + sizeof(*dfh) + sizeof(long);
addr(&dfh->dfh_TF.tf_CharData, cp);
cp= bcopy(cp, tf->tf_CharData, tf->tf_Modulo*tf->tf_YSize);
addr(&dfh->dfh_TF.tf_CharLoc, cp);
cp= bcopy(cp, tf->tf_CharLoc, n*2*sizeof(short));
if(tf->tf_CharSpace){
addr(&dfh->dfh_TF.tf_CharSpace, cp);
cp= bcopy(cp, tf->tf_CharSpace, n*sizeof(short));
}
if(tf->tf_CharKern){
addr(&dfh->dfh_TF.tf_CharKern, cp);
cp= bcopy(cp, tf->tf_CharKern, n*sizeof(short));
}
/* Now set the size of all this stuff */
dfh->dfh_TF.tf_Message.mn_Length= cp - ((char *)(&dfh->dfh_TF));
return size;
}
writehunx(fd, cp, size)BPTR fd; char *cp;{
/* Write the font hunks */
static long hunkstat[]= { /* Pre-canned program header */
0x000003F3, 0x00000000, 0x00000001, 0x00000000,
0x00000000, 0x000000FE, 0x000003E9, 0x000000FE};
size= (size+3) >>2;
hunkstat[5]= size; /* Put sizes in the header */
hunkstat[7]= size; /* (now we pretend we're a linker) */
/* Write the header */
if(Write(fd, hunkstat, sizeof(hunkstat))<0)return 0;
/* Font body as a code hunk */
if(Write(fd, cp, size<<2)<0)return 0;
/* Relocation hunk */
attab[attab[1]+3]= 0;
attab[attab[1]+4]= 0x3F2;
if(Write(fd, attab, (attab[1]+5)<<2)<0)return 0;
}