我有这个功能,用户从不同字体列表中选择。现在我想获得我试图使用的字体文件的确切名称。
我显示字体文件名,但不显示字体名称。防爆。 " Arial.tff"或" BROADW.tff"。
这是我想从文件中获取的那个。
我想在这里获得标题字段。这可能吗?
在尝试从我的资产文件夹中获取所有字体文件时,这是我的代码。
String[] fileList;
AssetManager aMan = getAssets();
try {
fileList = aMan.list("");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
然后我只是将它显示到适配器中,当用户选择该字体时,我将其转换。有任何想法吗?感谢。
答案 0 :(得分:8)
您需要解析字体文件。我将首先粘贴示例代码以获取字体名称。然后我将粘贴我从Apache FOP中提取和修改的代码。
try {
String pathToFontInAssets = "fonts/Arrial.ttf";
InputStream inputStream = getAssets().open(pathToFontInAssets);
TTFFile ttfFile = FontFileReader.readTTF(inputStream);
String fontName = ttfFile.getFullName();
} catch (IOException e) {
e.printStackTrace();
}
<强> FontFileReader.java 强>
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: FontFileReader.java 1357883 2012-07-05 20:29:53Z gadams $ */
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Reads a TrueType font file into a byte array and provides file like functions for array access.
*/
public class FontFileReader {
/**
* Read a font file
*
* @param path absolute path to the font file.
* @return
* @throws IOException if an error occurred while reading the font.
*/
public static TTFFile readTTF(String path) throws IOException {
TTFFile ttfFile = new TTFFile();
ttfFile.readFont(new FontFileReader(path));
return ttfFile;
}
/**
* Read a font file
*
* @param inputStream InputStream to read from
* @return
* @throws IOException if an error occurred while reading the font.
*/
public static TTFFile readTTF(InputStream inputStream) throws IOException {
TTFFile ttfFile = new TTFFile();
ttfFile.readFont(new FontFileReader(inputStream));
return ttfFile;
}
private int fsize; // file size
private int current; // current position in file
private byte[] file;
/**
* Constructor
*
* @param in
* InputStream to read from
* @throws IOException
* In case of an I/O problem
*/
public FontFileReader(InputStream in) throws IOException {
init(in);
}
/**
* Constructor
*
* @param fileName
* filename to read
* @throws IOException
* In case of an I/O problem
*/
public FontFileReader(String fileName) throws IOException {
File f = new File(fileName);
InputStream in = new FileInputStream(f);
try {
init(in);
} finally {
in.close();
}
}
/**
* Returns the full byte array representation of the file.
*
* @return byte array.
*/
public byte[] getAllBytes() {
return file;
}
/**
* Returns current file position.
*
* @return int The current position.
*/
public int getCurrentPos() {
return current;
}
/**
* Returns the size of the file.
*
* @return int The filesize
*/
public int getFileSize() {
return fsize;
}
/**
* Initializes class and reads stream. Init does not close stream.
*
* @param in
* InputStream to read from new array with size + inc
* @throws IOException
* In case of an I/O problem
*/
private void init(InputStream in) throws java.io.IOException {
file = IOUtils.toByteArray(in);
fsize = file.length;
current = 0;
}
/**
* Read 1 byte.
*
* @return One byte
* @throws IOException
* If EOF is reached
*/
private byte read() throws IOException {
if (current >= fsize) {
throw new EOFException("Reached EOF, file size=" + fsize);
}
byte ret = file[current++];
return ret;
}
/**
* Read 1 signed byte.
*
* @return One byte
* @throws IOException
* If EOF is reached
*/
public byte readTTFByte() throws IOException {
return read();
}
/**
* Read 4 bytes.
*
* @return One signed integer
* @throws IOException
* If EOF is reached
*/
public int readTTFLong() throws IOException {
long ret = readTTFUByte(); // << 8;
ret = (ret << 8) + readTTFUByte();
ret = (ret << 8) + readTTFUByte();
ret = (ret << 8) + readTTFUByte();
return (int) ret;
}
/**
* Read an ISO-8859-1 string of len bytes.
*
* @param len
* The bytesToUpload of the string to read
* @return A String
* @throws IOException
* If EOF is reached
*/
public String readTTFString(int len) throws IOException {
if ((len + current) > fsize) {
throw new EOFException("Reached EOF, file size=" + fsize);
}
byte[] tmp = new byte[len];
System.arraycopy(file, current, tmp, 0, len);
current += len;
String encoding;
if ((tmp.length > 0) && (tmp[0] == 0)) {
encoding = "UTF-16BE";
} else {
encoding = "ISO-8859-1";
}
return new String(tmp, encoding);
}
/**
* Read an ISO-8859-1 string of len bytes.
*
* @param len
* The bytesToUpload of the string to read
* @param encodingID
* the string encoding id (presently ignored; always uses UTF-16BE)
* @return A String
* @throws IOException
* If EOF is reached
*/
public String readTTFString(int len, int encodingID) throws IOException {
if ((len + current) > fsize) {
throw new java.io.EOFException("Reached EOF, file size=" + fsize);
}
byte[] tmp = new byte[len];
System.arraycopy(file, current, tmp, 0, len);
current += len;
String encoding;
encoding = "UTF-16BE"; // Use this for all known encoding IDs for now
return new String(tmp, encoding);
}
/**
* Read 1 unsigned byte.
*
* @return One unsigned byte
* @throws IOException
* If EOF is reached
*/
public int readTTFUByte() throws IOException {
byte buf = read();
if (buf < 0) {
return 256 + buf;
} else {
return buf;
}
}
/**
* Read 4 bytes.
*
* @return One unsigned integer
* @throws IOException
* If EOF is reached
*/
public long readTTFULong() throws IOException {
long ret = readTTFUByte();
ret = (ret << 8) + readTTFUByte();
ret = (ret << 8) + readTTFUByte();
ret = (ret << 8) + readTTFUByte();
return ret;
}
/**
* Read 2 bytes unsigned.
*
* @return One unsigned short
* @throws IOException
* If EOF is reached
*/
public int readTTFUShort() throws IOException {
int ret = (readTTFUByte() << 8) + readTTFUByte();
return ret;
}
/**
* Set current file position to offset
*
* @param offset
* The new offset to set
* @throws IOException
* In case of an I/O problem
*/
public void seekSet(long offset) throws IOException {
if (offset > fsize || offset < 0) {
throw new EOFException("Reached EOF, file size=" + fsize + " offset=" + offset);
}
current = (int) offset;
}
/**
* Skip a given number of bytes.
*
* @param add
* The number of bytes to advance
* @throws IOException
* In case of an I/O problem
*/
public void skip(long add) throws IOException {
seekSet(current + add);
}
}
<强> TTFDirTabEntry.java 强>
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: TTFDirTabEntry.java 1357883 2012-07-05 20:29:53Z gadams $ */
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* This class represents an entry to a TrueType font's Dir Tab.
*/
public class TTFDirTabEntry {
private final byte[] tag = new byte[4];
private long offset;
private long length;
TTFDirTabEntry() {
}
public TTFDirTabEntry(long offset, long length) {
this.offset = offset;
this.length = length;
}
/**
* Returns the bytesToUpload.
*
* @return long
*/
public long getLength() {
return length;
}
/**
* Returns the offset.
*
* @return long
*/
public long getOffset() {
return offset;
}
/**
* Returns the tag bytes.
*
* @return byte[]
*/
public byte[] getTag() {
return tag;
}
/**
* Returns the tag bytes.
*
* @return byte[]
*/
public String getTagString() {
try {
return new String(tag, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
return toString(); // Should never happen.
}
}
/**
* Read Dir Tab.
*
* @param in
* font file reader
* @return tag name
* @throws IOException
* upon I/O exception
*/
public String read(FontFileReader in) throws IOException {
tag[0] = in.readTTFByte();
tag[1] = in.readTTFByte();
tag[2] = in.readTTFByte();
tag[3] = in.readTTFByte();
in.skip(4); // Skip checksum
offset = in.readTTFULong();
length = in.readTTFULong();
String tagStr = new String(tag, "ISO-8859-1");
return tagStr;
}
@Override
public String toString() {
return "Read dir tab [" + tag[0] + " " + tag[1] + " " + tag[2] + " " + tag[3] + "]"
+ " offset: " + offset + " bytesToUpload: " + length + " name: " + tag;
}
}
<强> TTFFile.java 强>
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: TTFFile.java 1395925 2012-10-09 09:13:18Z jeremias $ */
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Reads a TrueType file or a TrueType Collection. The TrueType spec can be found at the Microsoft.
* Typography site: http://www.microsoft.com/truetype/
*/
public class TTFFile {
/** The FontFileReader used to read this TrueType font. */
private FontFileReader fontFile;
/**
* Table directory
*/
private Map<TTFTableName, TTFDirTabEntry> dirTabs;
private String postScriptName = "";
private String fullName = "";
private String notice = "";
private final Set<String> familyNames = new HashSet<String>();
private String subFamilyName = "";
TTFFile() {
}
/**
* Returns the font family names of the font.
*
* @return Set The family names (a Set of Strings)
*/
public Set<String> getFamilyNames() {
return familyNames;
}
/**
* Returns the full name of the font.
*
* @return String The full name
*/
public String getFullName() {
return fullName;
}
public String getNotice() {
return notice;
}
/**
* Returns the PostScript name of the font.
*
* @return String The PostScript name
*/
public String getPostScriptName() {
return postScriptName;
}
/**
* Returns the font sub family name of the font.
*
* @return String The sub family name
*/
public String getSubFamilyName() {
return subFamilyName;
}
/**
* Read Table Directory from the current position in the FontFileReader and fill the global
* HashMap dirTabs with the table name (String) as key and a TTFDirTabEntry as value.
*
* @throws IOException
* in case of an I/O problem
*/
private void readDirTabs() throws IOException {
fontFile.readTTFLong(); // TTF_FIXED_SIZE (4 bytes)
int ntabs = fontFile.readTTFUShort();
fontFile.skip(6); // 3xTTF_USHORT_SIZE
dirTabs = new HashMap<>();
TTFDirTabEntry[] pd = new TTFDirTabEntry[ntabs];
for (int i = 0; i < ntabs; i++) {
pd[i] = new TTFDirTabEntry();
String tableName = pd[i].read(fontFile);
dirTabs.put(TTFTableName.getValue(tableName), pd[i]);
}
dirTabs.put(TTFTableName.TABLE_DIRECTORY, new TTFDirTabEntry(0L, fontFile.getCurrentPos()));
}
/**
* Reads the font using a FontFileReader.
*
* @param in
* The FontFileReader to use
* @throws IOException
* In case of an I/O problem
*/
void readFont(FontFileReader in) throws IOException {
fontFile = in;
readDirTabs();
readName();
}
/**
* Read the "name" table.
*
* @throws IOException
* In case of a I/O problem
*/
private void readName() throws IOException {
seekTab(fontFile, TTFTableName.NAME, 2);
int i = fontFile.getCurrentPos();
int n = fontFile.readTTFUShort();
int j = fontFile.readTTFUShort() + i - 2;
i += 2 * 2;
while (n-- > 0) {
fontFile.seekSet(i);
int platformID = fontFile.readTTFUShort();
int encodingID = fontFile.readTTFUShort();
int languageID = fontFile.readTTFUShort();
int k = fontFile.readTTFUShort();
int l = fontFile.readTTFUShort();
if (((platformID == 1 || platformID == 3) && (encodingID == 0 || encodingID == 1))) {
fontFile.seekSet(j + fontFile.readTTFUShort());
String txt;
if (platformID == 3) {
txt = fontFile.readTTFString(l, encodingID);
} else {
txt = fontFile.readTTFString(l);
}
switch (k) {
case 0:
if (notice.length() == 0) {
notice = txt;
}
break;
case 1: // Font Family Name
case 16: // Preferred Family
familyNames.add(txt);
break;
case 2:
if (subFamilyName.length() == 0) {
subFamilyName = txt;
}
break;
case 4:
if (fullName.length() == 0 || (platformID == 3 && languageID == 1033)) {
fullName = txt;
}
break;
case 6:
if (postScriptName.length() == 0) {
postScriptName = txt;
}
break;
default:
break;
}
}
i += 6 * 2;
}
}
/**
* Position inputstream to position indicated in the dirtab offset + offset
*
* @param in
* font file reader
* @param tableName
* (tag) of table
* @param offset
* from start of table
* @return true if seek succeeded
* @throws IOException
* if I/O exception occurs during seek
*/
private boolean seekTab(FontFileReader in, TTFTableName tableName, long offset)
throws IOException
{
TTFDirTabEntry dt = dirTabs.get(tableName);
if (dt == null) {
return false;
} else {
in.seekSet(dt.getOffset() + offset);
}
return true;
}
}
<强> TTFTableName.java 强>
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: TTFTableName.java 1357883 2012-07-05 20:29:53Z gadams $ */
/**
* Represents table names as found in a TrueType font's Table Directory. TrueType fonts may have
* custom tables so we cannot use an enum.
*/
public final class TTFTableName {
/** The first table in a TrueType font file containing metadata about other tables. */
public static final TTFTableName TABLE_DIRECTORY = new TTFTableName("tableDirectory");
/** Naming table. */
public static final TTFTableName NAME = new TTFTableName("name");
/**
* Returns an instance of this class corresponding to the given string representation.
*
* @param tableName
* table name as in the Table Directory
* @return TTFTableName
*/
public static TTFTableName getValue(String tableName) {
if (tableName != null) {
return new TTFTableName(tableName);
}
throw new IllegalArgumentException("A TrueType font table name must not be null");
}
private final String name;
private TTFTableName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof TTFTableName)) {
return false;
}
TTFTableName to = (TTFTableName) o;
return name.equals(to.getName());
}
/**
* Returns the name of the table as it should be in the Directory Table.
*/
public String getName() {
return name;
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return name;
}
}
IOUtils.java (在FontFileReader中使用)
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class IOUtils {
private static int DEFAULT_BUFFER = 4096; // 4kb
private static int EOF = -1; // end of file
/**
* Get the contents of an {@code InputStream} as a {@code byte[]}.
* <p/>
* This method buffers the input internally, so there is no need to use a {@code
* BufferedInputStream}.
*
* @param input
* the {@code InputStream} to read from
* @return the requested byte array
* @throws NullPointerException
* if the input is null
* @throws IOException
* if an I/O error occurs
*/
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input, output);
return output.toByteArray();
}
/**
* Copy bytes from an {@code InputStream} to an {@code OutputStream}.</p>
* <p/>
* This method buffers the input internally, so there is no need to use a {@code
* BufferedInputStream}.</p>
* <p/>
* Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has
* completed since the correct number of bytes cannot be returned as an int. For large streams
* use the {@code copyLarge(InputStream, OutputStream)} method.</p>
*
* @param input
* the {@code InputStream} to read from
* @param output
* the {@code OutputStream} to write to
* @return the number of bytes copied, or -1 if > Integer.MAX_VALUE
* @throws NullPointerException
* if the input or output is null
* @throws IOException
* if an I/O error occurs
*/
public static int copy(InputStream input, OutputStream output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
/**
* Copy bytes from a large (over 2GB) {@code InputStream} to an {@code OutputStream}.</p>
* <p/>
* This method buffers the input internally, so there is no need to use a {@code
* BufferedInputStream}.</p>
* <p/>
* The buffer size is given by {@link #DEFAULT_BUFFER}.</p>
*
* @param input
* the {@code InputStream} to read from
* @param output
* the {@code OutputStream} to write to
* @return the number of bytes copied
* @throws NullPointerException
* if the input or output is null
* @throws IOException
* if an I/O error occurs
*/
public static long copyLarge(InputStream input, OutputStream output) throws
IOException
{
return copyLarge(input, output, new byte[DEFAULT_BUFFER]);
}
/**
* Copy bytes from a large (over 2GB) {@code InputStream} to an {@code OutputStream}.</p>
* <p/>
* This method uses the provided buffer, so there is no need to use a {@code
* BufferedInputStream}.</p>
*
* @param input
* the {@code InputStream} to read from
* @param output
* the {@code OutputStream} to write to
* @param buffer
* the buffer to use for the copy
* @return the number of bytes copied
* @throws NullPointerException
* if the input or output is null
* @throws IOException
* if an I/O error occurs
*/
public static long copyLarge(InputStream input, OutputStream output, byte[] buffer)
throws IOException
{
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
private IOUtils() {
}
}