Java parsing information about ttf fonts
The TTF (TrueType Font) file format is complex and contains multiple tables, each table stores different font information.
The premise is that ttf must contain these tabular information.
By parsing the TTF file through code, you can get the following:
public static final int COPYRIGHT = 0; // Copyright informationpublic static final int FAMILY_NAME = 1; // Font family namepublic static final int FONT_SUBFAMILY_NAME = 2; // Font subfamily name (for example: bold, italic, etc.)public static final int UNIQUE_FONT_IDENTIFIER = 3; // Unique font identifierpublic static final int FULL_FONT_NAME = 4; // Complete font namepublic static final int VERSION = 5; // Font version informationpublic static final int POSTSCRIPT_NAME = 6; // PostScript namepublic static final int TRADEMARK = 7; // Trademark informationpublic static final int MANUFACTURER = 8; // Manufacturer informationpublic static final int DESIGNER = 9; // Designer informationpublic static final int DESCRIPTION = 10; // Font descriptionpublic static final int URL_VENDOR = 11; // Manufacturer's URLpublic static final int URL_DESIGNER = 12; // Designer's URLpublic static final int LICENSE_DESCRIPTION = 13; // Authorization descriptionpublic static final int LICENSE_INFO_URL = 14; // Authorized informationURL
Here is an example of the data:
{0=Digitized data copyright © 2007, Google Corporation., 1=Droid Sans Mono, 2=Regular, 3=Ascender - Droid Sans Mono, 4=Droid Sans Mono, 5=Version 1.00 build 113, 6=DroidSansMono, 7=Droid is a trademark of Google and may be registered in certain jurisdictions., 8=Ascender Corporation, 10=Droid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication., 11=/, 12=/, 13=Licensed under the Apache License, Version 2.0, 14=/licenses/LICENSE-2.0, 18=䑲Slow-locked card⁍tide�} {0=Copyright Shanghai Zihun Network Technology Co., Ltd., 1=Goodbye Monster Body(Commercial use requires authorization), 2=Regular, 3=ZHZJGST_T, 4=Goodbye Monster Body(Commercial use requires authorization), 5=Version 2.00, 6=ZHZJGST_T, 7=Word Soul ®, 8=Shanghai Zihun Network Technology Co., Ltd., 9=Word Soul网, 10=Word Soul联名系列, 11=/, 12=/, 13=Commercial use requires a purchase authorization,Please visit: /, 16=Goodbye Monster Body(Commercial use requires authorization), 17=Regular} {0=Digitized data copyright © 2007, Google Corporation., 1=Droid Sans Mono, 2=Regular, 3=Ascender - Droid Sans Mono, 4=Droid Sans Mono, 5=Version 1.00 build 113, 6=DroidSansMono, 7=Droid is a trademark of Google and may be registered in certain jurisdictions., 8=Ascender Corporation, 10=Droid Sans is a humanist sans serif typeface designed for user interfaces and electronic communication., 11=/, 12=/, 13=Licensed under the Apache License, Version 2.0, 14=/licenses/LICENSE-2.0, 18=䑲Slow-locked card⁍tide�}
1. Basic information:
- Font name: including full name, family name, sub-family name, etc.
- Version information: font version number.
- Copyright and license: Copyright statement, license description and other information.
2. Character mapping:
- Glyf: contains the actual outline of each character (i.e. vector data).
- Glyph data: defines the graphic representation of each character.
3. Table information:
- Table directory: Contains the names, offsets and lengths of all tables.
- Font head: Basic information of the font, such as the bounding box of the minimum and maximum glyph of the font.
4. Measuring information:
- Horizontal metric table (hmtx): Contains the horizontal metric data for each glyph.
- Vertical metric table (vmtx): Contains the vertical metric data for each glyph.
5. Form details:
- Name table (name): Stores various name information of the font, such as the full name of the font, family name, sub-family name, etc.
- Character mapping table (cmap): defines the mapping relationship between character code and glyph index.
- Header: Provides some basic information about the font, such as the version of the font, creation time, etc.
- Control point table (loca): Provides the offset of glyph contour data.
6. Additional forms:
- Vertical and horizontal indicator tables (hhea and vhea): Contains horizontal and vertical baseline indicators for fonts.
- Contour image table (glyf): stores the actual outline of each glyph.
Code parsing example
1. Create tool classes
package ; import ; import ; import ; import ; import ; /** * TTF Font File Parser */ public class TTFParser { public static final int COPYRIGHT = 0; public static final int FAMILY_NAME = 1; public static final int FONT_SUBFAMILY_NAME = 2; public static final int UNIQUE_FONT_IDENTIFIER = 3; public static final int FULL_FONT_NAME = 4; public static final int VERSION = 5; public static final int POSTSCRIPT_NAME = 6; public static final int TRADEMARK = 7; public static final int MANUFACTURER = 8; public static final int DESIGNER = 9; public static final int DESCRIPTION = 10; public static final int URL_VENDOR = 11; public static final int URL_DESIGNER = 12; public static final int LICENSE_DESCRIPTION = 13; public static final int LICENSE_INFO_URL = 14; private final Map<Integer, String> fontProperties = new HashMap<>(); /** * Get the full font name, if not available, get the font family name. * * @return Font name */ public String getFontName() { return (FULL_FONT_NAME, (FAMILY_NAME)); } /** * Get specific font properties. * * @param nameID Attribute ID * @return attribute value */ public String getFontProperty(int nameID) { return (nameID); } /** * Get all font properties. * * @return Font attribute mapping */ public Map<Integer, String> getFontProperties() { return fontProperties; } /** * parse the TTF file and extract the font properties. * * @param fileName TTF file path * @throws IOException If an I/O error occurs */ public void parse(String fileName) throws IOException { (); try (RandomAccessFile raf = new RandomAccessFile(fileName, "r")) { parseInner(raf); } } private void parseInner(RandomAccessFile raf) throws IOException { int majorVersion = (); int minorVersion = (); int numOfTables = (); if (majorVersion != 1 || minorVersion != 0) { return; // Unsupported version } // Skip to table directory (12); // Skip version information and table count boolean found = false; TableDirectory tableDirectory = new TableDirectory(); for (int i = 0; i < numOfTables; i++) { byte[] nameBytes = new byte[4]; (nameBytes); = new String(nameBytes, StandardCharsets.ISO_8859_1); = (); = (); = (); if ("name".equalsIgnoreCase()) { found = true; break; } } if (!found) { return; // The 'name' table not found } (); NameTableHeader nameTableHeader = new NameTableHeader(); = (); = (); = (); for (int i = 0; i < ; i++) { NameRecord nameRecord = new NameRecord(); = (); = (); = (); = (); = (); = (); long pos = (); ( + + ); byte[] bf = new byte[]; (bf); String value = new String(bf, StandardCharsets.UTF_16); (, value); // Print out possible authorization information if ( == || == TTFParser.LICENSE_DESCRIPTION) { ("Found information: " + value); (); } (pos); } } /** * Check whether the font file contains a copyright notice. * * @return Return true if the copyright statement is found; otherwise return false */ public boolean hasCopyrightInfo() { return (COPYRIGHT); } /** * Check whether the font file contains commercial authorization information. * * @return Return an array containing two boolean values, the first indicates whether commercial use is allowed, and the second indicates whether authorization is required. */ public boolean[] checkCommercialUseAndAuthorization() { boolean isCommercialUseAllowed = false; boolean isAuthorizationRequired = false; String licenseDescription = (LICENSE_DESCRIPTION); if (licenseDescription != null) { // Analyze the keywords in licenseDescription to judge String descriptionLower = (); if (("commercial use allowed")) { isCommercialUseAllowed = true; } if (("authorization required")) { isAuthorizationRequired = true; } } String licenseInfoURL = (LICENSE_INFO_URL); ("============111111" + fontProperties); if (licenseInfoURL != null) { // You can confirm authorization information by accessing this URL ("Check authorization information, please visit: " + licenseInfoURL); // Assume that if there is a URL, further confirmation of authorization is required isAuthorizationRequired = true; } return new boolean[]{isCommercialUseAllowed, isAuthorizationRequired}; } @Override public String toString() { return (); } private static class TableDirectory { String name; int checkSum; int offset; int length; } private static class NameTableHeader { int fSelector; int nRCount; int storageOffset; } private static class NameRecord { int platformID; int encodingID; int languageID; int nameID; int stringLength; int stringOffset; } }
package ; import ; import ; import ; public class TTFParserExample { public static void main(String[] args) { // Specify the directory where the TTF file is located File fontDir = new File("D:\\ Test"); // List all TTF files in the directory File[] files = (new FilenameFilter() { @Override public boolean accept(File dir, String name) { return (".ttf"); } }); // Process each TTF file if (files != null) { for (File file : files) { TTFParser parser = new TTFParser(); try { (()); // Get and print the font name String fontName = (); ("Font name: " + fontName); // If you need to get other properties, you can use a similar method String familyName = (TTFParser.FAMILY_NAME); ("Family name: " + familyName); } catch (Exception e) { ("Error parsing font file: " + ()); (); } } } else { ("No TTF files found in the specified directory."); } } }
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.