С некоторыми разновидностями Android (Samsung, LG, HTC), похоже, что установить системный шрифт по умолчанию без привязки. У меня нет одного из этих устройств для тестирования (у меня есть более старый планшет Lenovo), но мне интересно следующее:
- Метод Typeface.DEFAULT возвращает Typeface пользовательского шрифта на этих устройствах или всегда возвращает информацию о Roboto?
- Если он возвращает информацию о пользовательском Typeface, как я могу программным образом получить имя (строку) шрифта пользовательского Typeface?
- Если Typeface.DEFAULT является тупиком, есть ли другой способ получить имя по умолчанию для системного шрифта? Может быть, для файлов TTF может быть?
EDIT: Я добавляю способ, который, как я думал, может работать, но на самом деле это не так: сравнение Typeface.DEFAULT с объектами Typeface, созданными из файлов в каталогах /system/fonts
, /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 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 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 должен откидываться, если он не может найти глиф в текущем шрифте (например, тайские символы).
Возможно, стоит проанализировать эту системную_систему и вернуть туда имя шрифта по умолчанию, но я не знаю, правильно ли это сделать.