http://www.ulduzsoft.com/2012/01/enumerating-the-fonts-on-android-platform/

/*
* Copyright (C) 2011 George Yunaev @ Ulduzsoft
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
*/

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;

public class FontManager
{
// This function enumerates all fonts on Android system and returns the HashMap with the font
// absolute file name as key, and the font literal name (embedded into the font) as value.
static public HashMap< String, String > enumerateFonts()
{
String[] fontdirs = { “/system/fonts”, “/system/font”, “/data/fonts” };
HashMap< String, String > fonts = new HashMap< String, String >();
TTFAnalyzer analyzer = new TTFAnalyzer();

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 )
fonts.put( file.getAbsolutePath(), fontname );
}
}

return fonts.isEmpty() ? null : fonts;
}
}

// 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; } } [/php]

By admin-powenko

Dr. Powen Ko is a teacher and CEO on LoopTek LLC, and like to teaching. if you need to class, please let PowenKo know, he will love to service and sharing. LoopTek web site is www.looptek.com

Leave a Reply