📄 truetypefont.java
字号:
r[1] = getGlyphWidth(r[0]);
h.put(new Integer(j), r);
}
}
return h;
}
/** The information in the maps of the table 'cmap' is coded in several formats.
* Format 6 is a trimmed table mapping. It is similar to format 0 but can have
* less than 256 entries.
* @return a <CODE>HashMap</CODE> representing this map
* @throws IOException the font file could not be read
*/
HashMap readFormat6() throws IOException {
HashMap h = new HashMap();
rf.skipBytes(4);
int start_code = rf.readUnsignedShort();
int code_count = rf.readUnsignedShort();
for (int k = 0; k < code_count; ++k) {
int r[] = new int[2];
r[0] = rf.readUnsignedShort();
r[1] = getGlyphWidth(r[0]);
h.put(new Integer(k + start_code), r);
}
return h;
}
/** Reads the kerning information from the 'kern' table.
* @throws IOException the font file could not be read
*/
void readKerning() throws IOException {
int table_location[];
table_location = (int[])tables.get("kern");
if (table_location == null)
return;
rf.seek(table_location[0] + 2);
int nTables = rf.readUnsignedShort();
kerning = new HashMap();
int checkpoint = table_location[0] + 4;
int length = 0;
for (int k = 0; k < nTables; ++k) {
checkpoint += length;
rf.seek(checkpoint);
rf.skipBytes(2);
length = rf.readUnsignedShort();
int coverage = rf.readUnsignedShort();
if ((coverage & 0xfff7) == 0x0001) {
int nPairs = rf.readUnsignedShort();
rf.skipBytes(6);
for (int j = 0; j < nPairs; ++j) {
Integer pair = new Integer(rf.readInt());
Integer value = new Integer(((int)rf.readShort() * 1000) / head.unitsPerEm);
kerning.put(pair, value);
}
}
}
}
/** Gets the kerning between two Unicode chars.
* @param char1 the first char
* @param char2 the second char
* @return the kerning to be applied
*/
public int getKerning(char char1, char char2) {
Integer v = (Integer)kerning.get(new Integer((((int)char1) << 16) + ((int)char2)));
if (v == null)
return 0;
else
return v.intValue();
}
/** Gets the width from the font according to the unicode char <CODE>c</CODE>.
* If the <CODE>name</CODE> is null it's a symbolic font.
* @param c the unicode char
* @param name the glyph name
* @return the width of the char
*/
protected int getRawWidth(int c, String name) {
HashMap map = null;
if (name == null)
map = cmap10;
else
map = cmap31;
if (map == null)
return 0;
int metric[] = (int[])map.get(new Integer(c));
if (metric == null)
return 0;
return metric[1];
}
/** If the embedded flag is <CODE>false</CODE> it returns <CODE>null</CODE>,
* otherwise the font is read and output in a PdfStream object.
* @return the PdfStream containing the font or <CODE>null</CODE>
* @throws DocumentException if there is an error reading the font
*/
protected PdfStream getFontStream() throws DocumentException {
if (!embedded)
return null;
InputStream is = null;
try {
File file = new File(fileName);
int fileLength = (int)file.length();
byte st[] = new byte[fileLength];
is = new FileInputStream(file);
int lengths[] = new int[]{fileLength};
int bytePtr = 0;
int size = fileLength;
while (size != 0) {
int got = is.read(st, bytePtr, size);
if (got < 0)
throw new DocumentException("Premature end in " + file.getName());
bytePtr += got;
size -= got;
}
return new StreamFont(st, lengths);
}
catch (Exception e) {
throw new DocumentException(e.getMessage());
}
finally {
if (is != null) {
try {
is.close();
}
catch (Exception e) {
}
}
}
}
/** Generates the font descriptor for this font.
* @return the PdfDictionary containing the font descriptor or <CODE>null</CODE>
* @param subsetPrefix the subset prefix
* @param fontStream the indirect reference to a PdfStream containing the font or <CODE>null</CODE>
* @throws DocumentException if there is an error
*/
protected PdfDictionary getFontDescriptor(PdfIndirectReference fontStream, String subsetPrefix) throws DocumentException {
PdfDictionary dic = new PdfDictionary(new PdfName("FontDescriptor"));
dic.put(new PdfName("Ascent"), new PdfNumber((int)os_2.sTypoAscender * 1000 / head.unitsPerEm));
dic.put(new PdfName("CapHeight"), new PdfNumber((int)os_2.sCapHeight * 1000 / head.unitsPerEm));
dic.put(new PdfName("Descent"), new PdfNumber((int)os_2.sTypoDescender * 1000 / head.unitsPerEm));
dic.put(new PdfName("FontBBox"), new PdfRectangle(
(int)head.xMin * 1000 / head.unitsPerEm,
(int)head.yMin * 1000 / head.unitsPerEm,
(int)head.xMax * 1000 / head.unitsPerEm,
(int)head.yMax * 1000 / head.unitsPerEm));
dic.put(new PdfName("FontName"), new PdfName(subsetPrefix + fontName + style));
dic.put(new PdfName("ItalicAngle"), new PdfNumber(italicAngle));
dic.put(new PdfName("StemV"), new PdfNumber(80));
if (fontStream != null)
dic.put(new PdfName("FontFile2"), fontStream);
int flags = 0;
if (isFixedPitch)
flags |= 1;
flags |= fontSpecific ? 4 : 32;
if ((head.macStyle & 2) != 0)
flags |= 64;
if ((head.macStyle & 1) != 0)
flags |= 262144;
dic.put(new PdfName("Flags"), new PdfNumber(flags));
return dic;
}
/** Generates the font dictionary for this font.
* @return the PdfDictionary containing the font dictionary
* @param subsetPrefix the subset prefx
* @param firstChar the first valid character
* @param lastChar the last valid character
* @param shortTag a 256 bytes long <CODE>byte</CODE> array where each unused byte is represented by 0
* @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or <CODE>null</CODE>
* @throws DocumentException if there is an error
*/
private PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, String subsetPrefix, int firstChar, int lastChar, byte shortTag[]) throws DocumentException {
PdfDictionary dic = new PdfDictionary(PdfName.FONT);
dic.put(PdfName.SUBTYPE, new PdfName("TrueType"));
dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
if (!fontSpecific) {
for (int k = firstChar; k <= lastChar; ++k) {
if (!differences[k].equals(notdef)) {
firstChar = k;
break;
}
}
if (encoding.equals("Cp1252") || encoding.equals("MacRoman"))
dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
else {
PdfDictionary enc = new PdfDictionary(new PdfName("Encoding"));
PdfArray dif = new PdfArray();
boolean gap = true;
for (int k = firstChar; k <= lastChar; ++k) {
if (shortTag[k] != 0) {
if (gap) {
dif.add(new PdfNumber(k));
gap = false;
}
dif.add(new PdfName(differences[k]));
}
else
gap = true;
}
enc.put(new PdfName("Differences"), dif);
dic.put(PdfName.ENCODING, enc);
}
}
dic.put(new PdfName("FirstChar"), new PdfNumber(firstChar));
dic.put(new PdfName("LastChar"), new PdfNumber(lastChar));
PdfArray wd = new PdfArray();
for (int k = firstChar; k <= lastChar; ++k) {
if (shortTag[k] == 0)
wd.add(new PdfNumber(0));
else
wd.add(new PdfNumber(widths[k]));
}
dic.put(new PdfName("Widths"), wd);
if (fontDescriptor != null)
dic.put(new PdfName("FontDescriptor"), fontDescriptor);
return dic;
}
/** Outputs to the writer the font dictionaries and streams.
* @param writer the writer for this document
* @param ref the font indirect reference
* @param params several parameters that depend on the font type
* @throws IOException on error
* @throws DocumentException error in generating the object
*/
void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
int firstChar = ((Integer)params[0]).intValue();
int lastChar = ((Integer)params[1]).intValue();
byte shortTag[] = (byte[])params[2];
PdfIndirectReference ind_font = null;
PdfObject pobj = null;
PdfIndirectObject obj = null;
String subsetPrefix = "";
if (embedded) {
subsetPrefix = createSubsetPrefix();
HashMap glyphs = new HashMap();
for (int k = firstChar; k <= lastChar; ++k) {
if (shortTag[k] != 0) {
int metrics[];
if (fontSpecific)
metrics = getMetricsTT(k);
else
metrics = getMetricsTT(unicodeDifferences[k]);
if (metrics != null)
glyphs.put(new Integer(metrics[0]), null);
}
}
TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, glyphs, directoryOffset, true);
byte b[] = sb.process();
int lengths[] = new int[]{b.length};
pobj = new StreamFont(b, lengths);
obj = writer.addToBody(pobj);
ind_font = obj.getIndirectReference();
}
pobj = getFontDescriptor(ind_font, subsetPrefix);
if (pobj != null){
obj = writer.addToBody(pobj);
ind_font = obj.getIndirectReference();
}
pobj = getFontBaseType(ind_font, subsetPrefix, firstChar, lastChar, shortTag);
writer.addToBody(pobj, ref);
}
/** Gets the font parameter identified by <CODE>key</CODE>. Valid values
* for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, <CODE>DESCENT</CODE>
* and <CODE>ITALICANGLE</CODE>.
* @param key the parameter to be extracted
* @param fontSize the font size in points
* @return the parameter in points
*/
public float getFontDescriptor(int key, float fontSize) {
switch (key) {
case ASCENT:
return (float)os_2.sTypoAscender * fontSize / (float)head.unitsPerEm;
case CAPHEIGHT:
return (float)os_2.sCapHeight * fontSize / (float)head.unitsPerEm;
case DESCENT:
return (float)os_2.sTypoDescender * fontSize / (float)head.unitsPerEm;
case ITALICANGLE:
return (float)italicAngle;
case BBOXLLX:
return fontSize * (int)head.xMin / head.unitsPerEm;
case BBOXLLY:
return fontSize * (int)head.yMin / head.unitsPerEm;
case BBOXURX:
return fontSize * (int)head.xMax / head.unitsPerEm;
case BBOXURY:
return fontSize * (int)head.yMax / head.unitsPerEm;
}
return 0;
}
/** Gets the glyph index and metrics for a character.
* @param c the character
* @return an <CODE>int</CODE> array with {glyph index, width}
*/
public int[] getMetricsTT(int c) {
if (!fontSpecific && cmap31 != null)
return (int[])cmap31.get(new Integer(c));
if (fontSpecific && cmap10 != null)
return (int[])cmap10.get(new Integer(c));
return null;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -