gpt4 book ai didi

Android -- 检索默认系统字体字符串名称

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:47:15 26 4
gpt4 key购买 nike

对于某些类型的 Android(三星、LG、HTC),看起来有可能 set the default system font without rooting .我没有这些设备可以测试(我有一台旧的联想平板电脑),但我想知道以下问题:

  1. Typeface.DEFAULT 方法是在这些设备上返回自定义字体的字体,还是总是在 Roboto 上返回信息?
  2. 如果它确实返回自定义字体的信息,我如何以编程方式获取自定义字体的字体名称(字符串)?
  3. 如果 Typeface.DEFAULT 是一条死胡同,是否有另一种获取默认系统字体名称的方法?可能是在四处寻找 TTF 文件?

编辑:我正在添加一种我认为可行但实际上行不通的方法:将 Typeface.DEFAULT 与从 /system/fonts 中的文件创建的 Typeface 对象进行比较,/system/font/data/fonts 目录。 这不是答案,但它可能有助于激励某人想出一个答案。另请注意,TTFAnalyzer 类不是我的。代码如下:

private String getDefaultFont() {
String[] fontdirs = { "/system/fonts", "/system/font", "/data/fonts" };
TTFAnalyzer analyzer = new TTFAnalyzer();
Typeface tfDefault = Typeface.DEFAULT;
Typeface tfTemp = null;
String defaultFontName = "";

System.out.println("getDefaultFont(): entry");
System.out.println("tfDefault: " + tfDefault.toString());

for ( String fontdir : fontdirs )
{
File dir = new File( fontdir );
if ( !dir.exists() )
continue;

File[] files = dir.listFiles();
if ( files == null )
continue;

for ( File file : files )
{
String fontname = analyzer.getTtfFontName( file.getAbsolutePath() );
if ( fontname != null ) {
System.out.println("found font: " + fontname);
tfTemp = Typeface.createFromFile(file);
System.out.println("tfTemp: " + tfTemp.toString());
//** THIS SHOULD BE WORKING? **//
if (tfTemp.equals(tfDefault)) {
System.out.println("Found default font: " + fontname);
defaultFontName = fontname;
}
}
}
}
return defaultFontName;
}

// The class which loads the TTF file, parses it and returns the TTF font name
class TTFAnalyzer
{
// This function parses the TTF file and returns the font name specified in the file
public String getTtfFontName( String fontFilename )
{
try
{
// Parses the TTF file format.
// See http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html
m_file = new RandomAccessFile( fontFilename, "r" );

// Read the version first
int version = readDword();

// The version must be either 'true' (0x74727565) or 0x00010000
if ( version != 0x74727565 && version != 0x00010000 )
return null;

// The TTF file consist of several sections called "tables", and we need to know how many of them are there.
int numTables = readWord();

// Skip the rest in the header
readWord(); // skip searchRange
readWord(); // skip entrySelector
readWord(); // skip rangeShift

// Now we can read the tables
for ( int i = 0; i < numTables; i++ )
{
// Read the table entry
int tag = readDword();
readDword(); // skip checksum
int offset = readDword();
int length = readDword();

// Now here' the trick. 'name' field actually contains the textual string name.
// So the 'name' string in characters equals to 0x6E616D65
if ( tag == 0x6E616D65 )
{
// Here's the name section. Read it completely into the allocated buffer
byte[] table = new byte[ length ];

m_file.seek( offset );
read( table );

// This is also a table. See http://developer.apple.com/fonts/ttrefman/rm06/Chap6name.html
// According to Table 36, the total number of table records is stored in the second word, at the offset 2.
// Getting the count and string offset - remembering it's big endian.
int count = getWord( table, 2 );
int string_offset = getWord( table, 4 );

// Record starts from offset 6
for ( int record = 0; record < count; record++ )
{
// Table 37 tells us that each record is 6 words -> 12 bytes, and that the nameID is 4th word so its offset is 6.
// We also need to account for the first 6 bytes of the header above (Table 36), so...
int nameid_offset = record * 12 + 6;
int platformID = getWord( table, nameid_offset );
int nameid_value = getWord( table, nameid_offset + 6 );

// Table 42 lists the valid name Identifiers. We're interested in 4 but not in Unicode encoding (for simplicity).
// The encoding is stored as PlatformID and we're interested in Mac encoding
if ( nameid_value == 4 && platformID == 1 )
{
// We need the string offset and length, which are the word 6 and 5 respectively
int name_length = getWord( table, nameid_offset + 8 );
int name_offset = getWord( table, nameid_offset + 10 );

// The real name string offset is calculated by adding the string_offset
name_offset = name_offset + string_offset;

// Make sure it is inside the array
if ( name_offset >= 0 && name_offset + name_length < table.length )
return new String( table, name_offset, name_length );
}
}
}
}

return null;
}
catch (FileNotFoundException e)
{
// Permissions?
return null;
}
catch (IOException e)
{
// Most likely a corrupted font file
return null;
}
}

// Font file; must be seekable
private RandomAccessFile m_file = null;

// Helper I/O functions
private int readByte() throws IOException
{
return m_file.read() & 0xFF;
}

private int readWord() throws IOException
{
int b1 = readByte();
int b2 = readByte();

return b1 << 8 | b2;
}

private int readDword() throws IOException
{
int b1 = readByte();
int b2 = readByte();
int b3 = readByte();
int b4 = readByte();

return b1 << 24 | b2 << 16 | b3 << 8 | b4;
}

private void read( byte [] array ) throws IOException
{
if ( m_file.read( array ) != array.length )
throw new IOException();
}

// Helper
private int getWord( byte [] array, int offset )
{
int b1 = array[ offset ] & 0xFF;
int b2 = array[ offset + 1 ] & 0xFF;

return b1 << 8 | b2;
}
}

编辑 2:在我的 Lenovo 平板电脑上浏览的更多信息。在 /system/etc 中,有几个感兴趣的 xml 文件:

  • system_fonts.xml -- 看起来它具有常规/斜体/粗体的默认字体作为其第一个系列条目
  • fallback_fonts.xml -- 如果 Android 在当前字体中找不到字形(例如,泰语字符),其中包含 Android 应该回退的字体。

可能值得解析 system_fonts 并从那里返回默认字体名称——但我不知道这是否是“正确”的方法。

最佳答案

好的,这是我认为可行的方法。至于它是否获得 Android 批准,好吧,这有点老套。该解决方案假设了一些事情:

  • 文件/system/etc/system_fonts.xml包含设备上的字体列表。
  • 第一个<file>中的元素system_fonts.xml文件是设备的默认字体。
  • 默认字体位于 /system/fonts .

这些假设来自于查看 Typeface来自 Android 5.x 的类文件,但我已经在其他几个版本上进行了测试,该解决方案似乎也适用于该版本。代码如下(假设上面列出了 TTFAnalyzer 类):

import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

public String getDefaultFont() {
System.out.println("getFontList(): entry");
File configFilename = new File("/system/etc/system_fonts.xml");
String defaultFontName = "";
TTFAnalyzer analyzer = new TTFAnalyzer();

try {
FileInputStream fontsIn = new FileInputStream(configFilename);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fontsIn, null);
Boolean done = false;
Boolean getTheText = false;
int eventType;
String defaultFont = "";
while (!done) {
eventType = parser.next();
if (eventType == parser.START_TAG && parser.getName().equalsIgnoreCase("file")) {
// the text is next up -- pull it
getTheText = true;
}
if (eventType == parser.TEXT && getTheText == true) {
// first name
defaultFont = parser.getText();
System.out.println("text for file tag:" + defaultFont);
done = true;
}
if (eventType == parser.END_DOCUMENT) {
System.out.println("hit end of system_fonts.xml document");
done = true;
}
}

if (defaultFont.length() > 0) {
// found the font filename, most likely in /system/fonts. Now pull out the human-readable
// string from the font file
System.out.println("Figuring out default Font info");
String fontname = analyzer.getTtfFontName("/system/fonts/" + defaultFont);
if ( fontname != null ) {
System.out.println("found font info: " + fontname);
defaultFontName = fontname;
}
}

} catch (RuntimeException e) {
System.err.println("Didn't create default family (most likely, non-Minikin build)");
// TODO: normal in non-Minikin case, remove or make error when Minikin-only
} catch (FileNotFoundException e) {
System.err.println("GetDefaultFont: config file Not found");
} catch (IOException e) {
System.err.println("GetDefaultFont: IO exception: " + e.getMessage());
} catch (XmlPullParserException e) {
System.err.println("getDefaultFont: XML parse exception " + e.getMessage());
}
return defaultFontName;
}

关于Android -- 检索默认系统字体字符串名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39707936/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com