从资产文件夹的文件中获取字体名称 [英] Get the font name from the file from the asset folder

查看:201
本文介绍了从资产文件夹的文件中获取字体名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个功能,用户从不同的字体列表中选择。现在我想得到我正在尝试使用的字体文件的确切名称。

我正在显示字体文件名,但不是字体的名称。防爆。 Arial.tff或BROADW.tff。

这是我想要从文件中获得的。





我想在这里获得标题字段。这是可能的吗?



这是我的代码,当试图从我的资产文件夹中获取所有的字体文件。 $ p> String [] fileList;
AssetManager aMan = getAssets();
尝试{
fileList = aMan.list();
} catch(IOException e){
// TODO自动生成的catch块
e.printStackTrace();





$ b然后,我只是将其显示到一个适配器中,当用户选择该字体时,我转换它。有任何想法吗?谢谢。

解决方案

您将需要解析字体文件。我将首先粘贴示例代码获取字体名称。然后,我将粘贴从中提取和修改的代码。



示例用法:

  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();



$ b

将以下类复制到您的项目中:

FontFileReader.java

  / * 
* Apache Software Foundation(ASF)根据一个或多个
* contributor许可协议。有关版权所有权的更多信息,请参阅本文件中以
*分发的NOTICE文件。
* ASF根据Apache许可证版本2.0
*(许可证)将此文件授权给您。您不得使用此文件,除非符合
*许可证。您可以在
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*上获得许可证副本*除非适用法律要求或以书面形式同意,根据许可证分发的软件
*以原样基础,
*分发,不附有任何种类的明示或暗示的保证或条件。
*请参阅许可证以获取许可证下的特定语言管理权限和
*限制。
* /

/ * $ 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;

/ **
*将TrueType字体文件读入字节数组,并为数组访问提供像文件一样的函数。
* /
public class FontFileReader {

/ **
*读取一个字体文件
*
* @param path绝对路径字体文件。
* @return
* @throws IOException如果读取字体时发生错误。
* /
public static TTFFile readTTF(String path)throws IOException {
TTFFile ttfFile = new TTFFile();
ttfFile.readFont(new FontFileReader(path));
return ttfFile;

$ b $ **
读取字体文件
*
* @param inputStream InputStream从
读取* @return
*如果在读取字体时发生错误,则抛出IOException。
* /
public static TTFFile readTTF(InputStream inputStream)throws IOException {
TTFFile ttfFile = new TTFFile();
ttfFile.readFont(new FontFileReader(inputStream));
return ttfFile;
}

private int fsize; //文件大小

private int current; //文件中的当前位置

private byte [] file;
$ b $ **
*构造函数
*
* @param in
* InputStream从
读取* @throws IOException
*如果发生I / O问题
* /
public FontFileReader(InputStream in)会抛出IOException {
init(in);

$ b / **
*构造函数
*
* @param文件名
*文件名读取
* @throws IOException
*如果发生I / O问题
* /
public FontFileReader(String fileName)throws IOException {
File f = new File(fileName);
InputStream in = new FileInputStream(f);
尝试{
init(in);
} finally {
in.close();
}
}

/ **
*返回文件的完整字节数组表示形式。
*
* @return字节数组。
* /
public byte [] getAllBytes(){
return file;
}

/ **
*返回当前文件位置。
*
* @return int当前位置。
* /
public int getCurrentPos(){
return current;
}

/ **
*返回文件的大小。
*
* @return int文件大小
* /
public int getFileSize(){
return fsize;
}

/ **
*初始化类并读取流。初始化不关闭流。
*
* @param in
* InputStream从大小为+的新数组中读取
* @throws IOException
*如果发生I / O问题
* /
private void init(InputStream in)会抛出java.io.IOException {
file = IOUtils.toByteArray(in);
fsize = file.length;
current = 0;
}

/ **
*读取1个字节。
*
* @return一个字节
* @throws IOException
*如果到达EOF
* /
private byte read()throws IOException { b $ b if(current> = fsize){
抛出新的EOFException(Reached EOF,file size =+ fsize);
}

字节ret = file [current ++];
return ret;
}

/ **
*读取1个带符号的字节。
*
* @return一个字节
* @throws IOException
*如果到达EOF
* /
public byte readTTFByte()throws IOException { b $ b返回read();
}

/ **
*读取4个字节。
*
* @return一个有符号整数
* @throws IOException
*如果到达EOF
* /
public int readTTFLong()throws IOException {
long ret = readTTFUByte(); //<< 8;
ret =(ret <8)+ readTTFUByte();
ret =(ret <8)+ readTTFUByte();
ret =(ret <8)+ readTTFUByte();

return(int)ret;
}

/ **
*读取ISO字节的ISO-8859-1字符串。
*
* @param len
*字符串的bytesToUpload读取
* @return A字符串
* @throws IOException
*如果EOF是达到
* /
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;
字符串编码; ((tmp.length> 0)&(tmp [0] == 0)){
encoding =UTF-16BE;
} else {
encoding =ISO-8859-1;

return new String(tmp,encoding);
}

/ **
*读取ISO字节的ISO-8859-1字符串。
*
* @param len
*字符串的bytesToUpload读取
* @param encodingID
*字符串编码id(目前被忽略;总是使用UTF- 16BE)
* @return一个字符串
* @throws IOException
*如果到达EOF
* /
public String readTTFString(int len,int encodingID)throws IOException {
if((len + current)> fsize){
抛出新的java.io.EOFException(Reached EOF,file size =+ fsize);
}

byte [] tmp = new byte [len];
System.arraycopy(file,current,tmp,0,len);
current + = len;
字符串编码;
encoding =UTF-16BE; //现在为所有已知的编码ID使用这个
return new String(tmp,encoding);
}

/ **
*读取1个无符号字节。
*
* @return一个无符号字节
* @throws IOException
*如果到达EOF
* /
public int readTTFUByte()throws IOException {
字节buf = read();

if(buf <0){
return 256 + buf;
} else {
return buf;
}
}

/ **
*读取4个字节。
*
* @return一个无符号整数
* @throws IOException
*如果到达EOF
* /
public long readTTFULong()throws IOException {
long ret = readTTFUByte();
ret =(ret <8)+ readTTFUByte();
ret =(ret <8)+ readTTFUByte();
ret =(ret <8)+ readTTFUByte();

return ret;
}

/ **
*读取2个字节的无符号数。
*
* @return一个unsigned short
* @throws IOException
*如果到达EOF
* /
public int readTTFUShort()throws IOException {
int ret =(readTTFUByte()<8)+ readTTFUByte();
return ret;

$ b $ **
*设置当前文件位置以抵消
*
* @param offset
*设置新的偏移量
* @throws IOException
*遇到I / O问题
* /
public void seekSet(long offset)抛出IOException {
if(offset> fsize || offset< 0){
throw new EOFException(Reached EOF,file size =+ fsize +offset =+ offset);
}
current =(int)offset;
}

/ **
*跳过给定的字节数。
*
* @param add
*要预先处理的字节数
* @throws IOException
*如果发生I / O问题
* /
public void skip(long add)throws IOException {
seekSet(current + add);




$ b

TTFDirTabEntry.java

  / * 
*在一个或多个$ b $下授权给Apache Software Foundation(ASF) b *贡献者许可协议。有关版权所有权的更多信息,请参阅本文件中以
*分发的NOTICE文件。
* ASF根据Apache许可证版本2.0
*(许可证)将此文件授权给您。您不得使用此文件,除非符合
*许可证。您可以在
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*上获得许可证副本*除非适用法律要求或以书面形式同意,根据许可证分发的软件
*以原样基础,
*分发,没有任何明示或暗示的保证或条件。
*请参阅许可证以获取许可证下的特定语言管理权限和
*限制。
* /

/ * $ Id:TTFDirTabEntry.java gadgets $ * /
$ b $ import java.io. IOException异常;
import java.io.UnsupportedEncodingException;

/ **
*此类表示TrueType字体的Dir选项卡的条目。
* /
public class TTFDirTabEntry {

private final byte [] tag = new byte [4];

私人多头抵消;

私人长度;

TTFDirTabEntry(){
}

public TTFDirTabEntry(long offset,long length){
this.offset = offset;
this.length = length;
}

/ **
*返回bytesToUpload。
*
* @return long
* /
public long getLength(){
return length;
}

/ **
*返回偏移量。
*
* @return long
* /
public long getOffset(){
return offset;
}

/ **
*返回标签字节。
*
* @return byte []
* /
public byte [] getTag(){
return tag;
}

/ **
*返回标签字节。
*
* @return byte []
* /
public String getTagString(){
try {
return new String(tag,ISO- 8859-1\" );
} catch(UnsupportedEncodingException e){
return toString(); //不应该发生。
}
}

/ **
*阅读Dir标签。
*
* @param in
*字体文件读取器
* @return标记名称
* @throws IOException
* I / O异常
* /
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); //跳过校验码

offset = in.readTTFULong();
length = in.readTTFULong();
String tagStr = new String(tag,ISO-8859-1);

return tagStr;

$ b @Override
public String toString(){
returnRead dir tab [+ tag [0] ++ tag [1] + + tag [2] ++ tag [3] +]
+offset:+ offset +bytesToUpload:+ length +name:+ tag;




$ b

TTFFile.java

  / * 
*在一个或多个$ b $下授权给Apache Software Foundation(ASF) b *贡献者许可协议。有关版权所有权的更多信息,请参阅本文件中以
*分发的NOTICE文件。
* ASF根据Apache许可证版本2.0
*(许可证)将此文件授权给您。您不得使用此文件,除非符合
*许可证。您可以在
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*上获得许可证副本*除非适用法律要求或以书面形式同意,根据许可证分发的软件
*以原样基础,
*分发,没有任何明示或暗示的保证或条件。
*请参阅许可证以获取许可证下的特定语言管理权限和
*限制。
* /

/ * $ Id:TTFFile.java jeremias $ * /
$ b $ import java.io. IOException异常;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/ **
*读取TrueType文件或TrueType集合。 TrueType规范可以在微软找到。
*排版网站:http://www.microsoft.com/truetype/
* /
公共类TTFFile {

/ ** FontFileReader用于读取这个TrueType字体。 * /
private FontFileReader fontFile;
$ b $ **
*表格目录
* /
私人地图< TTFTableName,TTFDirTabEntry> dirTabs;

private String postScriptName =;

private String fullName =;

private String notice =;

private final Set< String> familyNames = new HashSet< String>();

private String subFamilyName =;

TTFFile(){

}

/ **
*返回字体的字体名称。
*
* @return设置系列名称(一组字符串)
* /
public Set< String> getFamilyNames(){
return familyNames;
}

/ **
*返回字体的全名。
*
* @return字符串全名
* /
public String getFullName(){
return fullName;
}

public String getNotice(){
return notice;
}

/ **
*返回字体的PostScript名称。
*
* @return String PostScript名称
* /
public String getPostScriptName(){
return postScriptName;
}

/ **
*返回字体的字体子族名称。
*
* @return字符串子族名称
* /
public String getSubFamilyName(){
return subFamilyName;

$ b $ ** b $ b *从FontFileReader中的当前位置读取Table Directory,并将表名称(String)填入全局
* HashMap dirTabs中键和一个TTFDirTabEntry值。
*
* @throws IOException
*如果发生I / O问题
* /
private void readDirTabs()抛出IOException {
fontFile。 readTTFLong(); // TTF_FIXED_SIZE(4字节)
int ntabs = fontFile.readTTFUShort();
fontFile.skip(6); // 3xTTF_USHORT_SIZE

dirTabs = new HashMap<>();
TTFDirTabEntry [] pd = new TTFDirTabEntry [ntabs];

(int i = 0; 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()));
}

/ **
*使用FontFileReader读取字体。
*
* @param in
* FontFileReader使用
* @throws IOException异常
*遇到I / O问题
* /
void readFont(FontFileReader in)抛出IOException {
fontFile = in;
readDirTabs();
readName();
}

/ **
*阅读名称表。
*
* @throws IOException
*遇到I / O问题
* /
private void readName()抛出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(); (((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;
案例1://字体系列名称
案例16://首选系列
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;
默认值:
break;
}
}
i + = 6 * 2;


$ b $ **
*将输入流定位到dirtab偏移中指定的位置+偏移
*
* @param in
*字体文件读取器
* @param表名
*(标签)表
* @param偏移量
*从表格开始
* @return如果查找成功,则返回true
* @throws IOException
*如果在seek中发生I / O异常
* /
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);
}
返回true;




$ b

TTFTableName.java

  / * 
*在一个或多个$ b $下授权给Apache Software Foundation(ASF) b *贡献者许可协议。有关版权所有权的更多信息,请参阅本文件中以
*分发的NOTICE文件。
* ASF根据Apache许可证版本2.0
*(许可证)将此文件授权给您。您不得使用此文件,除非符合
*许可证。您可以在
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*上获得许可证副本*除非适用法律要求或以书面形式同意,根据许可证分发的软件
*以原样基础,
*分发,不附有任何种类的明示或暗示的保证或条件。
*请参阅许可证以获取许可证下的特定语言管理权限和
*限制。
* /

/ * $ Id:TTFTableName.java 1357883 2012-07-05 20:29:53Z gadams $ * /

/ **
*表示在TrueType字体的表目录中找到的表名。 TrueType字体可能有
*自定义表,所以我们不能使用枚举。
* /
public final class TTFTableName {

/ ** TrueType字体文件中的第一个表格,其中包含有关其他表格的元数据。 * /
public static final TTFTableName TABLE_DIRECTORY = new TTFTableName(tableDirectory);

/ **命名表。 * /
public static final TTFTableName NAME = new TTFTableName(name);

/ **
*返回与给定的字符串表示相对应的这个类的一个实例。
*
* @param tableName
*表名,如表所示
* @return TTFTableName
* /
public static TTFTableName getValue(String tableName ){
if(tableName!= null){
return new TTFTableName(tableName);

throw new IllegalArgumentException(TrueType字体表名不能为空);
}

private final String name;

private TTFTableName(String name){
this.name = name;

$ b @Override
public boolean equals(Object o){
if(o == this){
return true;

if(!(o instanceof TTFTableName)){
return false;
}
TTFTableName to =(TTFTableName)o;
返回name.equals(to.getName());
}

/ **
*返回目录表中的表名称。
* /
public String getName(){
return name;


@Override
public int hashCode(){
return name.hashCode();
}

@Override
public String toString(){
return name;


$ b $ / code $ / pre
$ b

IOUtils.java (在FontFileReader中使用)

$ $ p $ 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; //文件结尾

/ **
*将InputStream的内容作为一个字节[]}获取。
*< p />
*此方法在内部缓冲输入,因此不需要使用
* BufferedInputStream。
*
* @param输入
*从
读取的InputStream}返回请求的字节数组
* @throws NullPointerException
*如果输入为空
* @throws IOException
*如果发生I / O错误
* /
public static byte [] toByteArray(InputStream input)throws IOException { b $ b ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input,output);
return output.toByteArray();
}

/ **
*将InputStream中的字节复制到OutputStream中。< / p>
*< p />
*此方法在内部缓冲输入,因此不需要使用
* BufferedInputStream。< / p>
*< p />
*由于正确的字节数不能以int形式返回,大数据流(超过2GB)在拷贝完成
*之后将返回{@code -1}的字节复制值。对于大型流
*使用{@code copyLarge(InputStream,OutputStream)}方法。< / p>
*
* @param输入
* InputStream}从
读取* @param输出
* {OutputStream}写入
* @返回拷贝的字节数,或者-1& gt; Integer.MAX_VALUE
* @throws NullPointerException
*如果输入或输出为空
* @throws IOException
*如果发生I / O错误
* /
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;
}

/ **
*将一个大于2GB的InputStream中的字节复制到OutputStream中< / p>
*< p />
*此方法在内部缓冲输入,因此不需要使用
* BufferedInputStream。< / p>
*< p />
*缓冲区大小由{@link #DEFAULT_BUFFER}给出。< / p>
*
* @param输入
* InputStream}从
读取* @param输出
* {OutputStream}写入
* @return复制的字节数
* @throws NullPointerException
*如果输入或输出为空
* @throws IOException
*如果I / O错误发生
* /
public static long copyLarge(InputStream input,OutputStream output)throws
IOException
{
return copyLarge(input,output,new byte [DEFAULT_BUFFER]) ;
}

/ **
*将一个大于2GB的InputStream中的字节复制到OutputStream中< / p>
*< p />
*此方法使用提供的缓冲区,因此不需要使用
* BufferedInputStream。< / p>
*
* @param输入
* InputStream}从
读取* @param输出
* {OutputStream}写入
* @param缓冲区
*用于复制的缓冲区
* @return复制的字节数
* @throws NullPointerException
*如果输入或输出是null
* @throws IOException
*如果发生I / O错误
* /
public static long copyLarge(InputStream input,OutputStream output,byte [] buffer)
抛出IOException
{
long count = 0;
int n = 0; (EOF!=(n = input.read(buffer))){
output.write(buffer,0,n);
count + = n;
}
return count;

$ b $ private IOUtils(){

}

}


I have this function that the user selects from a list of different fonts. Now I want to get the exact name of the font file I'm trying to use.

I'm displaying the font file name, but not the name of the font. Ex. "Arial.tff" or "BROADW.tff".

This is the one that I want to get from the file.

I want to get the title field here. Is that possible?

Here's my code when trying to get all the font files from my asset folder.

String[] fileList;
AssetManager aMan = getAssets();
    try {
        fileList = aMan.list("");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Then I just display this into a adapter and when the user choose that font, I convert it. Any Ideas? Thanks.

解决方案

You will need to parse the font file. I will first paste example code on getting the font name. Then I will paste the code I extracted and modified from Apache FOP.

Example usage:

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();
}

Copy the following classes to your project:

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 (used in 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 &gt; 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() {

    }

}

这篇关于从资产文件夹的文件中获取字体名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆