📄 basefont.java
字号:
* font name}.
* @return the family name of the font
*/
public abstract String[][] getFamilyFontName();
/** Gets the code pages supported by the font. This has only meaning
* with True Type fonts.
* @return the code pages supported by the font
*/
public String[] getCodePagesSupported() {
return new String[0];
}
/** Enumerates the postscript font names present inside a
* True Type Collection.
* @param ttcFile the file name of the font
* @throws DocumentException on error
* @throws IOException on error
* @return the postscript font names
*/
public static String[] enumerateTTCNames(String ttcFile) throws DocumentException, IOException {
return new EnumerateTTC(ttcFile).getNames();
}
/** Enumerates the postscript font names present inside a
* True Type Collection.
* @param ttcArray the font as a <CODE>byte</CODE> array
* @throws DocumentException on error
* @throws IOException on error
* @return the postscript font names
*/
public static String[] enumerateTTCNames(byte ttcArray[]) throws DocumentException, IOException {
return new EnumerateTTC(ttcArray).getNames();
}
/** Gets the font width array.
* @return the font width array
*/
public int[] getWidths() {
return widths;
}
/** Gets the array with the names of the characters.
* @return the array with the names of the characters
*/
public String[] getDifferences() {
return differences;
}
/** Gets the array with the unicode characters.
* @return the array with the unicode characters
*/
public char[] getUnicodeDifferences() {
return unicodeDifferences;
}
/** Gets the state of the property.
* @return value of property forceWidthsOutput
*/
public boolean isForceWidthsOutput() {
return forceWidthsOutput;
}
/** Set to <CODE>true</CODE> to force the generation of the
* widths array.
* @param forceWidthsOutput <CODE>true</CODE> to force the generation of the
* widths array
*/
public void setForceWidthsOutput(boolean forceWidthsOutput) {
this.forceWidthsOutput = forceWidthsOutput;
}
/** Gets the direct conversion of <CODE>char</CODE> to <CODE>byte</CODE>.
* @return value of property directTextToByte.
* @see #setDirectTextToByte(boolean directTextToByte)
*/
public boolean isDirectTextToByte() {
return directTextToByte;
}
/** Sets the conversion of <CODE>char</CODE> directly to <CODE>byte</CODE>
* by casting. This is a low level feature to put the bytes directly in
* the content stream without passing through String.getBytes().
* @param directTextToByte New value of property directTextToByte.
*/
public void setDirectTextToByte(boolean directTextToByte) {
this.directTextToByte = directTextToByte;
}
/** Indicates if all the glyphs and widths for that particular
* encoding should be included in the document.
* @return <CODE>false</CODE> to include all the glyphs and widths.
*/
public boolean isSubset() {
return subset;
}
/** Indicates if all the glyphs and widths for that particular
* encoding should be included in the document. When set to <CODE>true</CODE>
* only the glyphs used will be included in the font. When set to <CODE>false</CODE>
* and {@link #addSubsetRange(int[])} was not called the full font will be included
* otherwise just the characters ranges will be included.
* @param subset new value of property subset
*/
public void setSubset(boolean subset) {
this.subset = subset;
}
/** Gets the font resources.
* @param key the full name of the resource
* @return the <CODE>InputStream</CODE> to get the resource or
* <CODE>null</CODE> if not found
*/
public static InputStream getResourceStream(String key) {
return getResourceStream(key, null);
}
/** Gets the font resources.
* @param key the full name of the resource
* @param loader the ClassLoader to load the resource or null to try the ones available
* @return the <CODE>InputStream</CODE> to get the resource or
* <CODE>null</CODE> if not found
*/
public static InputStream getResourceStream(String key, ClassLoader loader) {
if (key.startsWith("/"))
key = key.substring(1);
InputStream is = null;
if (loader != null) {
is = loader.getResourceAsStream(key);
if (is != null)
return is;
}
// Try to use Context Class Loader to load the properties file.
try {
java.lang.reflect.Method getCCL =
Thread.class.getMethod("getContextClassLoader", new Class[0]);
if (getCCL != null) {
ClassLoader contextClassLoader =
(ClassLoader)getCCL.invoke(Thread.currentThread(),
new Object[0]);
if (contextClassLoader != null)
is = contextClassLoader.getResourceAsStream(key);
}
} catch (Throwable e) {}
if (is == null) {
is = BaseFont.class.getResourceAsStream("/" + key);
}
if (is == null) {
is = ClassLoader.getSystemResourceAsStream(key);
}
return is;
}
/** Gets the Unicode equivalent to a CID.
* The (inexistent) CID <FF00> is translated as '\n'.
* It has only meaning with CJK fonts with Identity encoding.
* @param c the CID code
* @return the Unicode equivalent
*/
public char getUnicodeEquivalent(char c) {
return c;
}
/** Gets the CID code given an Unicode.
* It has only meaning with CJK fonts.
* @param c the Unicode
* @return the CID equivalent
*/
public char getCidCode(char c) {
return c;
}
/** Checks if the font has any kerning pairs.
* @return <CODE>true</CODE> if the font has any kerning pairs
*/
public abstract boolean hasKernPairs();
/**
* Checks if a character exists in this font.
* @param c the character to check
* @return <CODE>true</CODE> if the character has a glyph,
* <CODE>false</CODE> otherwise
*/
public boolean charExists(char c) {
byte b[] = convertToBytes(new String(new char[]{c}));
return b.length > 0;
}
/**
* Sets the character advance.
* @param c the character
* @param advance the character advance normalized to 1000 units
* @return <CODE>true</CODE> if the advance was set,
* <CODE>false</CODE> otherwise
*/
public boolean setCharAdvance(char c, int advance) {
byte b[] = convertToBytes(new String(new char[]{c}));
if (b.length == 0)
return false;
widths[0xff & b[0]] = advance;
return true;
}
private static void addFont(PRIndirectReference fontRef, IntHashtable hits, ArrayList fonts) {
PdfObject obj = PdfReader.getPdfObject(fontRef);
if (obj == null || !obj.isDictionary())
return;
PdfDictionary font = (PdfDictionary)obj;
PdfName subtype = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
if (!PdfName.TYPE1.equals(subtype) && !PdfName.TRUETYPE.equals(subtype))
return;
PdfName name = (PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT));
fonts.add(new Object[]{PdfName.decodeName(name.toString()), fontRef});
hits.put(fontRef.getNumber(), 1);
}
private static void recourseFonts(PdfDictionary page, IntHashtable hits, ArrayList fonts, int level) {
++level;
if (level > 50) // in case we have an endless loop
return;
PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(page.get(PdfName.RESOURCES));
if (resources == null)
return;
PdfDictionary font = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.FONT));
if (font != null) {
for (Iterator it = font.getKeys().iterator(); it.hasNext();) {
PdfObject ft = font.get((PdfName)it.next());
if (ft == null || !ft.isIndirect())
continue;
int hit = ((PRIndirectReference)ft).getNumber();
if (hits.containsKey(hit))
continue;
addFont((PRIndirectReference)ft, hits, fonts);
}
}
PdfDictionary xobj = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.XOBJECT));
if (xobj != null) {
for (Iterator it = xobj.getKeys().iterator(); it.hasNext();) {
recourseFonts((PdfDictionary)PdfReader.getPdfObject(xobj.get((PdfName)it.next())), hits, fonts, level);
}
}
}
/**
* Gets a list of all document fonts. Each element of the <CODE>ArrayList</CODE>
* contains a <CODE>Object[]{String,PRIndirectReference}</CODE> with the font name
* and the indirect reference to it.
* @param reader the document where the fonts are to be listed from
* @return the list of fonts and references
*/
public static ArrayList getDocumentFonts(PdfReader reader) {
IntHashtable hits = new IntHashtable();
ArrayList fonts = new ArrayList();
int npages = reader.getNumberOfPages();
for (int k = 1; k <= npages; ++k)
recourseFonts(reader.getPageN(k), hits, fonts, 1);
return fonts;
}
/**
* Gets a list of the document fonts in a particular page. Each element of the <CODE>ArrayList</CODE>
* contains a <CODE>Object[]{String,PRIndirectReference}</CODE> with the font name
* and the indirect reference to it.
* @param reader the document where the fonts are to be listed from
* @param page the page to list the fonts from
* @return the list of fonts and references
*/
public static ArrayList getDocumentFonts(PdfReader reader, int page) {
IntHashtable hits = new IntHashtable();
ArrayList fonts = new ArrayList();
recourseFonts(reader.getPageN(page), hits, fonts, 1);
return fonts;
}
/**
* Gets the smallest box enclosing the character contours. It will return
* <CODE>null</CODE> if the font has not the information or the character has no
* contours, as in the case of the space, for example. Characters with no contours may
* also return [0,0,0,0].
* @param c the character to get the contour bounding box from
* @return an array of four floats with the bounding box in the format [llx,lly,urx,ury] or
* <code>null</code>
*/
public int[] getCharBBox(char c) {
byte b[] = convertToBytes(new String(new char[]{c}));
if (b.length == 0)
return null;
else
return charBBoxes[b[0] & 0xff];
}
protected abstract int[] getRawCharBBox(int c, String name);
/**
* iText expects Arabic Diactrics (tashkeel) to have zero advance but some fonts,
* most notably those that come with Windows, like times.ttf, have non-zero
* advance for those characters. This method makes those character to have zero
* width advance and work correctly in the iText Arabic shaping and reordering
* context.
*/
public void correctArabicAdvance() {
for (char c = '\u064b'; c <= '\u0658'; ++c)
setCharAdvance(c, 0);
setCharAdvance('\u0670', 0);
for (char c = '\u06d6'; c <= '\u06dc'; ++c)
setCharAdvance(c, 0);
for (char c = '\u06df'; c <= '\u06e4'; ++c)
setCharAdvance(c, 0);
for (char c = '\u06e7'; c <= '\u06e8'; ++c)
setCharAdvance(c, 0);
for (char c = '\u06ea'; c <= '\u06ed'; ++c)
setCharAdvance(c, 0);
}
/**
* Adds a character range when subsetting. The range is an <CODE>int</CODE> array
* where the first element is the start range inclusive and the second element is the
* end range inclusive. Several ranges are allowed in the same array.
* @param range the character range
*/
public void addSubsetRange(int[] range) {
if (subsetRanges == null)
subsetRanges = new ArrayList();
subsetRanges.add(range);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -