📄 pfm2afm.java
字号:
fontname = in.readIntLE();
if (h_len != in.length() || extlen != 30 || fontname < 75 || fontname > 512)
throw new IOException("Not a valid PFM file.");
in.seek(psext + 14);
capheight = in.readShortLE();
xheight = in.readShortLE();
ascender = in.readShortLE();
descender = in.readShortLE();
}
private void putheader() throws IOException {
out.print("StartFontMetrics 2.0\n");
if (copyright.length() > 0)
out.print("Comment " + copyright + '\n');
out.print("FontName ");
in.seek(fontname);
String fname = readString();
out.print(fname);
out.print("\nEncodingScheme ");
if (charset != 0)
out.print("FontSpecific\n");
else
out.print("AdobeStandardEncoding\n");
/*
* The .pfm is missing full name, so construct from font name by
* changing the hyphen to a space. This actually works in a lot
* of cases.
*/
out.print("FullName " + fname.replace('-', ' '));
if (face != 0) {
in.seek(face);
out.print("\nFamilyName " + readString());
}
out.print("\nWeight ");
if (weight > 475 || fname.toLowerCase().indexOf("bold") >= 0)
out.print("Bold");
else if ((weight < 325 && weight != 0) || fname.toLowerCase().indexOf("light") >= 0)
out.print("Light");
else if (fname.toLowerCase().indexOf("black") >= 0)
out.print("Black");
else
out.print("Medium");
out.print("\nItalicAngle ");
if (italic != 0 || fname.toLowerCase().indexOf("italic") >= 0)
out.print("-12.00");
/* this is a typical value; something else may work better for a
specific font */
else
out.print("0");
/*
* The mono flag in the pfm actually indicates whether there is a
* table of font widths, not if they are all the same.
*/
out.print("\nIsFixedPitch ");
if ((kind & 1) == 0 || /* Flag for mono */
avgwidth == maxwidth ) { /* Avg width = max width */
out.print("true");
isMono = true;
}
else {
out.print("false");
isMono = false;
}
/*
* The font bounding box is lost, but try to reconstruct it.
* Much of this is just guess work. The bounding box is required in
* the .afm, but is not used by the PM font installer.
*/
out.print("\nFontBBox");
if (isMono)
outval(-20); /* Just guess at left bounds */
else
outval(-100);
outval(-(descender+5)); /* Descender is given as positive value */
outval(maxwidth+10);
outval(ascent+5);
/*
* Give other metrics that were kept
*/
out.print("\nCapHeight");
outval(capheight);
out.print("\nXHeight");
outval(xheight);
out.print("\nDescender");
outval(descender);
out.print("\nAscender");
outval(ascender);
out.print('\n');
}
private void putchartab() throws IOException {
int count = lastchar - firstchar + 1;
int ctabs[] = new int[count];
in.seek(chartab);
for (int k = 0; k < count; ++k)
ctabs[k] = in.readUnsignedShortLE();
int back[] = new int[256];
if (charset == 0) {
for (int i = firstchar; i <= lastchar; ++i) {
if (Win2PSStd[i] != 0)
back[Win2PSStd[i]] = i;
}
}
/* Put out the header */
out.print("StartCharMetrics");
outval(count);
out.print('\n');
/* Put out all encoded chars */
if (charset != 0) {
/*
* If the charset is not the Windows standard, just put out
* unnamed entries.
*/
for (int i = firstchar; i <= lastchar; i++) {
if (ctabs[i - firstchar] != 0) {
outchar(i, ctabs[i - firstchar], null);
}
}
}
else {
for (int i = 0; i < 256; i++) {
int j = back[i];
if (j != 0) {
outchar(i, ctabs[j - firstchar], WinChars[j]);
ctabs[j - firstchar] = 0;
}
}
/* Put out all non-encoded chars */
for (int i = firstchar; i <= lastchar; i++) {
if (ctabs[i - firstchar] != 0) {
outchar(-1, ctabs[i - firstchar], WinChars[i]);
}
}
}
/* Put out the trailer */
out.print("EndCharMetrics\n");
}
private void putkerntab() throws IOException {
if (kernpairs == 0)
return;
in.seek(kernpairs);
int count = in.readUnsignedShortLE();
int nzero = 0;
int kerns[] = new int[count * 3];
for (int k = 0; k < kerns.length;) {
kerns[k++] = in.read();
kerns[k++] = in.read();
if ((kerns[k++] = in.readShortLE()) != 0)
++nzero;
}
if (nzero == 0)
return;
out.print("StartKernData\nStartKernPairs");
outval(nzero);
out.print('\n');
for (int k = 0; k < kerns.length; k += 3) {
if (kerns[k + 2] != 0) {
out.print("KPX ");
out.print(WinChars[kerns[k]]);
out.print(' ');
out.print(WinChars[kerns[k + 1]]);
outval(kerns[k + 2]);
out.print('\n');
}
}
/* Put out trailer */
out.print("EndKernPairs\nEndKernData\n");
}
private void puttrailer() {
out.print("EndFontMetrics\n");
}
private short vers;
private int h_len; /* Total length of .pfm file */
private String copyright; /* Copyright string [60]*/
private short type;
private short points;
private short verres;
private short horres;
private short ascent;
private short intleading;
private short extleading;
private byte italic;
private byte uline;
private byte overs;
private short weight;
private byte charset; /* 0=windows, otherwise nomap */
private short pixwidth; /* Width for mono fonts */
private short pixheight;
private byte kind; /* Lower bit off in mono */
private short avgwidth; /* Mono if avg=max width */
private short maxwidth; /* Use to compute bounding box */
private int firstchar; /* First char in table */
private int lastchar; /* Last char in table */
private byte defchar;
private byte brkchar;
private short widthby;
private int device;
private int face; /* Face name */
private int bits;
private int bitoff;
private short extlen;
private int psext; /* PostScript extension */
private int chartab; /* Character width tables */
private int res1;
private int kernpairs; /* Kerning pairs */
private int res2;
private int fontname; /* Font name */
/*
* Some metrics from the PostScript extension
*/
private short capheight; /* Cap height */
private short xheight; /* X height */
private short ascender; /* Ascender */
private short descender; /* Descender (positive) */
private boolean isMono;
/*
* Translate table from 1004 to psstd. 1004 is an extension of the
* Windows translate table used in PM.
*/
private int Win2PSStd[] = {
0, 0, 0, 0, 197, 198, 199, 0, 202, 0, 205, 206, 207, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32, 33, 34, 35, 36, 37, 38, 169, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
193, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
0, 0, 184, 0, 185, 188, 178, 179, 94, 189, 0, 172, 234, 0, 0, 0,
0, 96, 0, 170, 186, 0, 177, 208, 126, 0, 0, 173, 250, 0, 0, 0,
0, 161, 162, 163, 168, 165, 0, 167, 200, 0, 227, 171, 0, 0, 0, 0,
0, 0, 0, 0, 194, 0, 182, 180, 203, 0, 235, 187, 0, 0, 0, 191,
0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 251,
0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0
};
/*
* Character class. This is a minor attempt to overcome the problem that
* in the pfm file, all unused characters are given the width of space.
*/
private int WinClass[] = {
0, 0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 0, 0, 0, /* 00 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, /* 70 */
0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, /* 80 */
0, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, /* 90 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a0 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -