📄 truetypefont.java
字号:
dif.add(new PdfName(differences[k]));
}
else
gap = true;
}
enc.put(PdfName.DIFFERENCES, dif);
dic.put(PdfName.ENCODING, enc);
}
}
dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
dic.put(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(PdfName.WIDTHS, wd);
if (fontDescriptor != null)
dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
return dic;
}
protected byte[] getFullFont() throws IOException {
RandomAccessFileOrArray rf2 = null;
try {
rf2 = new RandomAccessFileOrArray(rf);
rf2.reOpen();
byte b[] = new byte[rf2.length()];
rf2.readFully(b);
return b;
}
finally {
try {if (rf2 != null) {rf2.close();}} catch (Exception e) {}
}
}
protected static int[] compactRanges(ArrayList ranges) {
ArrayList simp = new ArrayList();
for (int k = 0; k < ranges.size(); ++k) {
int[] r = (int[])ranges.get(k);
for (int j = 0; j < r.length; j += 2) {
simp.add(new int[]{Math.max(0, Math.min(r[j], r[j + 1])), Math.min(0xffff, Math.max(r[j], r[j + 1]))});
}
}
for (int k1 = 0; k1 < simp.size() - 1; ++k1) {
for (int k2 = k1 + 1; k2 < simp.size(); ++k2) {
int[] r1 = (int[])simp.get(k1);
int[] r2 = (int[])simp.get(k2);
if ((r1[0] >= r2[0] && r1[0] <= r2[1]) || (r1[1] >= r2[0] && r1[0] <= r2[1])) {
r1[0] = Math.min(r1[0], r2[0]);
r1[1] = Math.max(r1[1], r2[1]);
simp.remove(k2);
--k2;
}
}
}
int[] s = new int[simp.size() * 2];
for (int k = 0; k < simp.size(); ++k) {
int[] r = (int[])simp.get(k);
s[k * 2] = r[0];
s[k * 2 + 1] = r[1];
}
return s;
}
protected void addRangeUni(HashMap longTag, boolean includeMetrics, boolean subsetp) {
if (!subsetp && (subsetRanges != null || directoryOffset > 0)) {
int[] rg = (subsetRanges == null && directoryOffset > 0) ? new int[]{0, 0xffff} : compactRanges(subsetRanges);
HashMap usemap;
if (!fontSpecific && cmap31 != null)
usemap = cmap31;
else if (fontSpecific && cmap10 != null)
usemap = cmap10;
else if (cmap31 != null)
usemap = cmap31;
else
usemap = cmap10;
for (Iterator it = usemap.entrySet().iterator(); it.hasNext();) {
Map.Entry e = (Map.Entry)it.next();
int[] v = (int[])e.getValue();
Integer gi = new Integer(v[0]);
if (longTag.containsKey(gi))
continue;
int c = ((Integer)e.getKey()).intValue();
boolean skip = true;
for (int k = 0; k < rg.length; k += 2) {
if (c >= rg[k] && c <= rg[k + 1]) {
skip = false;
break;
}
}
if (!skip)
longTag.put(gi, includeMetrics ? new int[]{v[0], v[1], c} : null);
}
}
}
/** 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];
boolean subsetp = ((Boolean)params[3]).booleanValue() && subset;
if (!subsetp) {
firstChar = 0;
lastChar = shortTag.length - 1;
for (int k = 0; k < shortTag.length; ++k)
shortTag[k] = 1;
}
PdfIndirectReference ind_font = null;
PdfObject pobj = null;
PdfIndirectObject obj = null;
String subsetPrefix = "";
if (embedded) {
if (cff) {
RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
byte b[] = new byte[cffLength];
try {
rf2.reOpen();
rf2.seek(cffOffset);
rf2.readFully(b);
}
finally {
try {
rf2.close();
}
catch (Exception e) {
// empty on purpose
}
}
pobj = new StreamFont(b, "Type1C");
obj = writer.addToBody(pobj);
ind_font = obj.getIndirectReference();
}
else {
if (subsetp)
subsetPrefix = createSubsetPrefix();
HashMap glyphs = new HashMap();
for (int k = firstChar; k <= lastChar; ++k) {
if (shortTag[k] != 0) {
int[] metrics = null;
if (specialMap != null) {
int[] cd = GlyphList.nameToUnicode(differences[k]);
if (cd != null)
metrics = getMetricsTT(cd[0]);
}
else {
if (fontSpecific)
metrics = getMetricsTT(k);
else
metrics = getMetricsTT(unicodeDifferences[k]);
}
if (metrics != null)
glyphs.put(new Integer(metrics[0]), null);
}
}
addRangeUni(glyphs, false, subsetp);
byte[] b = null;
if (subsetp || directoryOffset != 0 || subsetRanges != null) {
TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), glyphs, directoryOffset, true, !subsetp);
b = sb.process();
}
else {
b = getFullFont();
}
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;
case AWT_ASCENT:
return fontSize * (int)hhea.Ascender / head.unitsPerEm;
case AWT_DESCENT:
return fontSize * (int)hhea.Descender / head.unitsPerEm;
case AWT_LEADING:
return fontSize * (int)hhea.LineGap / head.unitsPerEm;
case AWT_MAXADVANCE:
return fontSize * (int)hhea.advanceWidthMax / 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));
if (cmap31 != null)
return (int[])cmap31.get(new Integer(c));
if (cmap10 != null)
return (int[])cmap10.get(new Integer(c));
return null;
}
/** Gets the postscript font name.
* @return the postscript font name
*/
public String getPostscriptFontName() {
return fontName;
}
/** Gets the code pages supported by the font.
* @return the code pages supported by the font
*/
public String[] getCodePagesSupported() {
long cp = (((long)os_2.ulCodePageRange2) << 32) + ((long)os_2.ulCodePageRange1 & 0xffffffffL);
int count = 0;
long bit = 1;
for (int k = 0; k < 64; ++k) {
if ((cp & bit) != 0 && codePages[k] != null)
++count;
bit <<= 1;
}
String ret[] = new String[count];
count = 0;
bit = 1;
for (int k = 0; k < 64; ++k) {
if ((cp & bit) != 0 && codePages[k] != null)
ret[count++] = codePages[k];
bit <<= 1;
}
return ret;
}
/** Gets the full name of the font. If it is a True Type font
* each array element will have {Platform ID, Platform Encoding ID,
* Language ID, font name}. The interpretation of this values can be
* found in the Open Type specification, chapter 2, in the 'name' table.<br>
* For the other fonts the array has a single element with {"", "", "",
* font name}.
* @return the full name of the font
*/
public String[][] getFullFontName() {
return fullName;
}
/** Gets the family name of the font. If it is a True Type font
* each array element will have {Platform ID, Platform Encoding ID,
* Language ID, font name}. The interpretation of this values can be
* found in the Open Type specification, chapter 2, in the 'name' table.<br>
* For the other fonts the array has a single element with {"", "", "",
* font name}.
* @return the family name of the font
*/
public String[][] getFamilyFontName() {
return familyName;
}
/** Checks if the font has any kerning pairs.
* @return <CODE>true</CODE> if the font has any kerning pairs
*/
public boolean hasKernPairs() {
return kerning.size() > 0;
}
/**
* Sets the font name that will appear in the pdf font dictionary.
* Use with care as it can easily make a font unreadable if not embedded.
* @param name the new font name
*/
public void setPostscriptFontName(String name) {
fontName = name;
}
/**
* Sets the kerning between two Unicode chars.
* @param char1 the first char
* @param char2 the second char
* @param kern the kerning to apply in normalized 1000 units
* @return <code>true</code> if the kerning was applied, <code>false</code> otherwise
*/
public boolean setKerning(char char1, char char2, int kern) {
int metrics[] = getMetricsTT(char1);
if (metrics == null)
return false;
int c1 = metrics[0];
metrics = getMetricsTT(char2);
if (metrics == null)
return false;
int c2 = metrics[0];
kerning.put((c1 << 16) + c2, kern);
return true;
}
protected int[] getRawCharBBox(int c, String name) {
HashMap map = null;
if (name == null || cmap31 == null)
map = cmap10;
else
map = cmap31;
if (map == null)
return null;
int metric[] = (int[])map.get(new Integer(c));
if (metric == null || bboxes == null)
return null;
return bboxes[metric[0]];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -