Jan de Kloe, August 2002, updated November 15, 2011
Introduction
Recently, a request was addressed to me for the explanation of the PSC file structure which I
had published in February 2002 on the SCORE forum. The text has been slightly edited.
Scope
SCORE needs to compute the width of text when it wants to center or justify it. Also it needs
to know the length of a syllable when dashes must be centered in lyrics. The information on
character widths is kept in FMnn.PSC files which reside in the LIB directory.
FM stands for font metrics, nn is the number of the font which you see in Code16 items
as _nn or __nn. Also, this number may be used in Code10 items, Par7, the default being 00 for
Times Roman.
Note that the font prefix in Code16 items is not required – it will take a default as well
(Text uses the font from the previous text item on EPS generation, if there is none it assumes
Times Roman. Note that ordering items can influence this so it not suggested to omit the font
prefix. When entering lyrics, the font of the previous syllable is copied immediately).
PSC probably stands for Points in SCORE. The standards 35 fonts that come with SCORE have the
PSC files FM00.PSC to FM34.PSC.
Other fonts than the standard 35
When you want another font than the ones provided with SCORE you can, but you need to construct
a PSC file for that font so that SCORE has detailed information on each character in the set.
SCORE provides a utility for making PSC files which is called FONTCONV.EXE.
FONTCONV and points
As input, FONTCONV takes an AFM file and for demonstration’s sake we will use LAUSANNE.AFM.
(Note that non-standard fonts requires that your printer recognizes them as firmware or
downloaded). AFM stands for Adobe Font Metrics. You can display an AFM file with Notepad,
Wordpad or any text processor since it is a plain text file.
In the AFM file are many details on the character set. For each character there is a
line which looks like this:
C 48 ; WX 556 ; N zero ; B 38 -18 519 704 ;
It means that the character with the internal value of 48 (C-field) is 556 (WX-field) points
wide.
Since Tom Brodhead’s exposé we all know
now what a point is for SCORE (almost the same as a point used in the printing industry). The
N-field tells us that this is the character for ‘zero’ but this is comment only. The B-field
is not of interest to us as it is information not used by FONTCONV.
FONTCONV only uses the C- and the WX-fields from the AFM file to construct a PSC file.
There is one more thing used from this file – the font name. It comes from one of the header
records in the AFM file, in our case:
FontName Lausanne
Note that this name is truncated to 28 character if longer. SCORE needs this name to pass it
on to the EPS file.
The PSC file structure
PSC files have a format which does not allow it to be listed with any of the above mentioned
utilities and I used a hexadecimal dump program to analyze it. All PSC files have the same
length of 694 bytes and the format, like that of DRW files is known as doubly linked list.
This format dates from the days that computers had much smaller memories than today’s machine
and the file had to be read in pieces. Today we would select a different format if we had to
design the PSC file. This is the structure of the first record (length 130 bytes):
byte contents
1 hex 4B decimal 75 indicates the recording format
(probably)
2 hex 81 decimal 129 indicates how many bytes of
data follow including myself
3 28 bytes containing the font name, space padded
31 100 bytes representing 50 integers with character width info
Byte 1 and 2 are the record header. There are five more records with just integers in the file
with record headers at byte 133, 263, 363, 493 and 623. At the end of the file, there is another
record header without data. This means the records have 64, 49, 64, 64, and 35 integers,
including the first 50 bringing the total of integers (widths) to 326.
Why are these records of different length? The reason can only be historic. In the early days,
SCORE must have had a limited character set and 50 + 64 + 49 = 163 was probably the maximum of
characters it supported. When more characters were added, FONTCONV was modified by just adding
records until what it supports today: 326 characters, in theory.
In theory because not all characters are used in all character sets.
The format of an integer, or halfword as I like to call it, is best demonstrated by taking
the first integer from our LAUSANNE.PSC which is hex 2C02. This means hex 2c (decimal 44)
plus hex 02 (decimal 2) times 256. The high order byte is on the right in the Intel
architecture, unlike humans who put the high order digits at the left since the Arabs
invented our number system.
2*256+44=556.
This 556 is the width in points for the first character in the table.
Here follows the beginning of the PSC table for Lausanne:
address contents
1 556
2 556
3 556
4 556
5 556
6 556
7 556
8 556
9 556
10 556
11 667
12 667
13 722
14 722
15 667
etc.
Thus we have 326 values or character widths, one for each character. SCORE looks up the
width for each character in this table but this is, again for historic reasons, not a
straightforward process.
Two phase table lookup
Logically one would expect that character ‘zero’, our example’s 48 would point to the 48th
entry in the table to find 556. In stead there is another translation done by FONTCONV,
probably because the originator initially used internal character values as they were used
by another architecture than Intel’s. Anyway, it turned out to be necessary to do some reverse
engineering and look at FONTCONV from the inside. In it is a table (for those who want to
take a look, it is at hex A14A) which translates the AFM C-field to the address in our PSC
table. The beginning of the equivalence is:
byte contents in decimal
0 112
1 97
2 99
3 101
etc.
32 1
33 2
34 3
35 4
etc.
With this the circle is closed. Take our ‘zero’ with internal value 48. First we subtract 16,
apparently there is no provision for characters with values 0 through 15 (?). 48-16=32.
We look in the equivalence table at displacement 32 and find 1. This 1 is then used as an
index to the PSC table and there is where we find 556.
Epilogue
This information is now shared with all members of the SCORE forum. If someone is interested
in the translation routines I have developed for the PSC interpretation, just ask (source only,
VB6, includes the equivalence table).
The following persons are herewith thanked for their contribution: Paul Terry and Matanya
Ophee for pointing out the function of the AFM file and its relation to PSC; Andrew Parker
for suggesting to share my knowledge of SCORE internals with the forum; Krzysztof Rogalski
for supplying the file LAUSANNE.AFM; Tom Brodhead for letting me refer to his points explanation;
and of course Leland Smith because I peaked into FONTCONV.EXE.
Following publication of this text on the forum, Chanvrelin and Tom Owen ("I am using
this technique for proper centering of punctuated lyrics") suggested to manipulate PSC
files to influence placement of dashes between lyrics. Do not modify a standard PSC file but
rather copy one to an unused number (FM36.PSC – FM89.PSC) which is then manipulated to define
a zero length for punctuation characters.
This study was performed as part of the development of SipSib, the Sibelius EPS to SCORE
converter.