home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
wp_dtp
/
atap.lha
/
ATAP
/
SourceCode
/
WriteMetricsVector.c
< prev
Wrap
Text File
|
1992-06-13
|
11KB
|
417 lines
#define KERNING_AVAILABLE 0x0268
#define X_WIDTHS_AVAILABLE 0x0068
#define AMIGA_STANDARD 0x0101
#define FONT_SPECIFIC 0x0100
ULONG WriteMetricsVector(char *afmFilename, int typeWeight)
/* This function is the heart of ConvertAFM. It creates what I
call a "Metrics Vector"; a complete .metric structure with all
typeface information, character widths, and kerning tables.
It creates a file in T: named by the AFM's typeface name.
It contains the complete metrics vector except for the
typeface style, which you must supply in typeWeight. It
also returns the length of the file. */
{
static WORD kerningTables[256][256];
static char kerningCheckList[16384];
static char currentList[256],*kerningArray,*incomingString,headerCheck[26],encodingScheme[20],intString[4][20],metricFilename[26],typefaceName[68],*intChars;
static WORD metricInfo[18],xWidths[256],kerningPointers[256];
static FILE *afmFile,*metricFile;
static int test,test2,test3,test4,test5,asciiCode,asciiCode2,xWidth,kerningArrayLength,currentOffset;
static ULONG vectorLength;
static UWORD index,index2;
static BOOL goodfit;
for (index=0;index<18;index++)
metricInfo[index]=0;
for(index=0;index<68;index++)
typefaceName[index]=0;
metricInfo[0]=X_WIDTHS_AVAILABLE;
for (index=0;index<256;index++)
xWidths[index]=0;
afmFile=fopen(afmFilename,"r");
if (afmFile==0)
{
fclose(afmFile);
return(0);
}
/* If the AFM file didn't exist, it returns a vectorLength
of zero. Logical, yes? A non-existant file with zero length? */
headerCheck[0]=0;
test=-1;
while(test!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s\n",headerCheck);
test=strcmp(headerCheck,"FontName");
}
sscanf(incomingString,"%s %s",headerCheck,typefaceName);
test=-1;
while(test!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test=strcmp(headerCheck,"EncodingScheme");
}
sscanf(incomingString,"%s %s",headerCheck,encodingScheme);
test=strcmp(encodingScheme,"FontSpecific");
test2=strcmp(encodingScheme,"AppleStandard");
if (test==0 || test2==0)
metricInfo[6]=FONT_SPECIFIC;
else
metricInfo[6]=AMIGA_STANDARD;
fsetpos(afmFile,0);
/* I gotta do this for every parameter I require! Ugh! */
test=-1;
while(test!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test=strcmp(headerCheck,"UnderlinePosition");
}
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[11]=atoi(intString[0]);
test=-1;
while(test!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test=strcmp(headerCheck,"UnderlineThickness");
}
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[12]=atoi(intString[0]);
test=-1;
while(test!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test=strcmp(headerCheck,"FontBBox");
}
sscanf(incomingString,"%s %s %s %s %s",headerCheck,intString[0],intString[1],intString[2],intString[3]);
for (index=0;index<4;index++)
metricInfo[index+7]=atoi(intString[index]);
/* Some typefaces won't have letter-like qualities, like
cap height, x-height, etc. So, if the very next line is
"StartCharMetrics", then it creates these values based
on the Font Bounding Box. */
test=-1;
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test=strcmp(headerCheck,"StartCharMetrics");
if (test!=0)
{
test2=-1;
while(test2!=0)
{
sscanf(incomingString,"%s ",headerCheck);
test2=strcmp(headerCheck,"CapHeight");
}
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[13]=atoi(intString[0]);
test2=-1;
while(test2==0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test2=strcmp(headerCheck,"XHeight");
}
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[14]=atoi(intString[0]);
test2=-1;
while(test2!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test2=strcmp(headerCheck,"Descender");
}
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[16]=atoi(intString[0]);
test2=-1;
while(test2!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test2=strcmp(headerCheck,"Ascender");
}
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[15]=atoi(intString[0]);
incomingString=freadline(afmFile);
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
}
else
{
for (index=13;index<17;index++)
metricInfo[index]=0;
sscanf(incomingString,"%s %s",headerCheck,intString[0]);
metricInfo[16]=metricInfo[8];
for (index=13;index<16;index++)
metricInfo[index]=metricInfo[8]+metricInfo[10];
}
metricInfo[17]=typeWeight;
/* By now we're on the very first line of x-widths.
We start by comparing all the chars to either Amiga Standard
or Apple Standard encoding and arrange the X-widths in an
ASCII format. The check arrays #included are used for this.
If the typeface has Font Specific encoding the ASCII values
are used directly. */
vectorLength=104;
if (metricInfo[6]==FONT_SPECIFIC)
{
test2=-1;
incomingString=freadline(afmFile);
while (test2!=0)
{
sscanf(incomingString,"C %s ; WX %s ",intString[0],intString[1]);
asciiCode=atoi(intString[0]);
if (asciiCode!=-1)
xWidths[asciiCode]=atoi(intString[1]);
incomingString=freadline(afmFile);
test2=strcmp(incomingString,"EndCharMetrics");
}
vectorLength=vectorLength+256*2;
}
else
{
test2=-1;
incomingString=freadline(afmFile);
while (test2!=0)
{
sscanf(incomingString,"C %s ; WX %s ; N %s ",intString[0],intString[1],intString[2]);
index=0;asciiCode=-1;
while (asciiCode==-1 && index<256)
{
test=strcmp(amigaEncoding[index],intString[2]);
if (test==0)
asciiCode=index;
else
index=index+1;
}
if (asciiCode!=-1)
xWidths[asciiCode]=atoi(intString[1]);
incomingString=freadline(afmFile);
test2=strcmp(incomingString,"EndCharMetrics");
}
vectorLength=vectorLength+256*2;
}
/* If this is any type of standard encoding, I look for kerning
tables. This means AdobeStandard, AppleStandard, or whatever.
NOTE: Font Specific encoded typefaces CANNOT have kerning
tables or this program will ignore them. To add kerning to
a font specific encoded typeface, you'll have to wait for
my kerning pair editor to be released.
Anyway, on to kerning pair decyphering. */
test=-1;test2=-1;
while (test!=0 && test2!=0)
{
incomingString=freadline(afmFile);
test=strcmp(incomingString,"StartKernData");
test2=strcmp(incomingString,"EndFontMetrics");
}
test2=strcmp(encodingScheme,"FontSpecific");
if (test==0 && test2!=0)
{
for (index=0;index<256;index++)
for (index2=0;index2<256;index2++)
kerningTables[index][index2]=0;
test3=-1;
while (test3!=0)
{
incomingString=freadline(afmFile);
sscanf(incomingString,"%s ",headerCheck);
test3=strcmp(headerCheck,"StartKernPairs");
}
test3=-1;
incomingString=freadline(afmFile);
test=strcmp(incomingString,"EndKernPairs");
while (test3!=0)
{
sscanf(incomingString,"%s ",headerCheck);
test4=strcmp(headerCheck,"KPX");
if (test4==0)
{
sscanf(incomingString,"KPX %s %s %s",intString[0],intString[1],intString[2]);
index=0;asciiCode=-1;
while (asciiCode==-1 && index<256)
{
test5=strcmp(amigaEncoding[index],intString[0]);
if (test5==0)
asciiCode=index;
else
index=index+1;
}
index=0;asciiCode2=-1;
while (asciiCode2==-1 && index<256)
{
test5=strcmp(amigaEncoding[index],intString[1]);
if (test5==0)
asciiCode2=index;
else
index=index+1;
}
kerningTables[asciiCode][asciiCode2]=atoi(intString[2]);
}
incomingString=freadline(afmFile);
test3=strcmp(incomingString,"EndKernPairs");
}
for (index=0;index<256;index++)
for (index2=0;index2<256;index2++)
if (kerningTables[index][index2]!=0)
{
kerningPointers[index]=256;
index2=256;
}
else
kerningPointers[index]=0;
/* Since making a separate function for encoding the kerning
array doesn't work with DICE (UGH!) I have to include it
here. */
for (index=0;index<16384;index++)
kerningCheckList[index]=32;
/* kerningCheckList nulled to spaces. */
kerningArrayLength=256;
for (index=0;index<256;index++)
{
if (kerningPointers[index]!=0)
{
for (index2=0;index2<256;index2++)
{
if (kerningTables[index][index2]!=0)
currentList[index2]=index;
else
currentList[index2]=32;
}
/* CurrentList created. */
goodfit=TRUE;currentOffset=0;
for (index2=0;index2<256;index2++)
{
if (currentList[index2]!=32 && kerningCheckList[index2]!=32)
{
goodfit=FALSE;
index2=256;
}
}
while (goodfit==FALSE)
{
currentOffset=currentOffset+1;
for (index2=0;index2<256;index2++)
{
if (currentList[index2]!=32 && kerningCheckList[index2+currentOffset]!=32)
{
goodfit=FALSE;
index2=256;
}
else
goodfit=TRUE;
}
}
/* A good fit was found. Record the offset and insert
into the check array. */
for (index2=0;index2<256;index2++)
if (currentList[index2]!=32)
kerningCheckList[index2+currentOffset]=currentList[index2];
kerningPointers[index]=kerningPointers[index]+currentOffset;
if (kerningArrayLength < currentOffset+256)
kerningArrayLength=kerningArrayLength+(currentOffset+256-kerningArrayLength);
}
/* NEXT! */
}
for (index=0;index<256;index++)
if (kerningPointers[index]!=0)
{
vectorLength=vectorLength+256*4+kerningArrayLength*4;
metricInfo[2]=KERNING_AVAILABLE;
index=256;
}
}
fclose(afmFile);
strcpy(metricFilename,"T:");
strcat(metricFilename,typefaceName);
metricFile=fopen(metricFilename,"w");
for (index=0;index<68;index++)
fputc(typefaceName[index],metricFile);
for (index=0;index<18;index++)
{
intChars=&metricInfo[index];
fprintf(metricFile,"%c%c",intChars[0],intChars[1]);
}
for (index=0;index<256;index++)
{
intChars=&xWidths[index];
fprintf(metricFile,"%c%c",intChars[0],intChars[1]);
}
if (metricInfo[2]==KERNING_AVAILABLE)
{
for (index=0;index<256;index++)
if (kerningPointers[index]!=0)
{
intChars=&kerningPointers[index];
fprintf(metricFile,"%c%c%c%c",intChars[0],intChars[1],0,index);
}
else
fprintf(metricFile,"%c%c%c%c",0,0,0,0);
for (index=0;index<kerningArrayLength;index++)
if (kerningCheckList[index]!=32)
{
asciiCode=kerningCheckList[index];
asciiCode2=index-kerningPointers[asciiCode]+256;
intChars=&kerningTables[asciiCode][asciiCode2];
fprintf(metricFile,"%c%c%c%c",intChars[0],intChars[1],0,asciiCode);
}
else
fprintf(metricFile,"%c%c%c%c",0,0,0,0);
/* Cheaky way of writing the kerning table, eh? :-) */
}
fclose(metricFile);
return(vectorLength);
};