📄 truetypefont.java
字号:
createEncoding(); } /** Gets the name from a composed TTC file name. * If I have for input "myfont.ttc,2" the return will * be "myfont.ttc". * @param name the full name * @return the simple file name */ protected static String getTTCName(String name) { int idx = name.toLowerCase().indexOf(".ttc,"); if (idx < 0) return name; else return name.substring(0, idx + 4); } /** * Reads the tables 'head', 'hhea', 'OS/2' and 'post' filling several variables. * @throws DocumentException the font is invalid * @throws IOException the font file could not be read */ void fillTables() throws DocumentException, IOException { int table_location[]; table_location = (int[])tables.get("head"); if (table_location == null) throw new DocumentException("Table 'head' does not exist in " + fileName + style); rf.seek(table_location[0] + 16); head.flags = rf.readUnsignedShort(); head.unitsPerEm = rf.readUnsignedShort(); rf.skipBytes(16); head.xMin = rf.readShort(); head.yMin = rf.readShort(); head.xMax = rf.readShort(); head.yMax = rf.readShort(); head.macStyle = rf.readUnsignedShort(); table_location = (int[])tables.get("hhea"); if (table_location == null) throw new DocumentException("Table 'hhea' does not exist " + fileName + style); rf.seek(table_location[0] + 4); hhea.Ascender = rf.readShort(); hhea.Descender = rf.readShort(); hhea.LineGap = rf.readShort(); hhea.advanceWidthMax = rf.readUnsignedShort(); hhea.minLeftSideBearing = rf.readShort(); hhea.minRightSideBearing = rf.readShort(); hhea.xMaxExtent = rf.readShort(); hhea.caretSlopeRise = rf.readShort(); hhea.caretSlopeRun = rf.readShort(); rf.skipBytes(12); hhea.numberOfHMetrics = rf.readUnsignedShort(); table_location = (int[])tables.get("OS/2"); if (table_location == null) throw new DocumentException("Table 'OS/2' does not exist in " + fileName + style); rf.seek(table_location[0]); int version = rf.readUnsignedShort(); os_2.xAvgCharWidth = rf.readShort(); os_2.usWeightClass = rf.readUnsignedShort(); os_2.usWidthClass = rf.readUnsignedShort(); os_2.fsType = rf.readShort(); os_2.ySubscriptXSize = rf.readShort(); os_2.ySubscriptYSize = rf.readShort(); os_2.ySubscriptXOffset = rf.readShort(); os_2.ySubscriptYOffset = rf.readShort(); os_2.ySuperscriptXSize = rf.readShort(); os_2.ySuperscriptYSize = rf.readShort(); os_2.ySuperscriptXOffset = rf.readShort(); os_2.ySuperscriptYOffset = rf.readShort(); os_2.yStrikeoutSize = rf.readShort(); os_2.yStrikeoutPosition = rf.readShort(); os_2.sFamilyClass = rf.readShort(); rf.readFully(os_2.panose); rf.skipBytes(16); rf.readFully(os_2.achVendID); os_2.fsSelection = rf.readUnsignedShort(); os_2.usFirstCharIndex = rf.readUnsignedShort(); os_2.usLastCharIndex = rf.readUnsignedShort(); os_2.sTypoAscender = rf.readShort(); os_2.sTypoDescender = rf.readShort(); if (os_2.sTypoDescender > 0) os_2.sTypoDescender = (short)(-os_2.sTypoDescender); os_2.sTypoLineGap = rf.readShort(); os_2.usWinAscent = rf.readUnsignedShort(); os_2.usWinDescent = rf.readUnsignedShort(); os_2.ulCodePageRange1 = 0; os_2.ulCodePageRange2 = 0; if (version > 0) { os_2.ulCodePageRange1 = rf.readInt(); os_2.ulCodePageRange2 = rf.readInt(); } if (version > 1) { rf.skipBytes(2); os_2.sCapHeight = rf.readShort(); } else os_2.sCapHeight = (int)(0.7 * head.unitsPerEm); table_location = (int[])tables.get("post"); if (table_location == null) { italicAngle = -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI; return; } rf.seek(table_location[0] + 4); short mantissa = rf.readShort(); int fraction = rf.readUnsignedShort(); italicAngle = mantissa + fraction / 16384.0d; underlinePosition = rf.readShort(); underlineThickness = rf.readShort(); isFixedPitch = rf.readInt() != 0; } /** * Gets the Postscript font name. * @throws DocumentException the font is invalid * @throws IOException the font file could not be read * @return the Postscript font name */ String getBaseFont() throws DocumentException, IOException { int table_location[]; table_location = (int[])tables.get("name"); if (table_location == null) throw new DocumentException("Table 'name' does not exist in " + fileName + style); rf.seek(table_location[0] + 2); int numRecords = rf.readUnsignedShort(); int startOfStorage = rf.readUnsignedShort(); for (int k = 0; k < numRecords; ++k) { int platformID = rf.readUnsignedShort(); int platformEncodingID = rf.readUnsignedShort(); int languageID = rf.readUnsignedShort(); int nameID = rf.readUnsignedShort(); int length = rf.readUnsignedShort(); int offset = rf.readUnsignedShort(); if (nameID == 6) { rf.seek(table_location[0] + startOfStorage + offset); if (platformID == 0 || platformID == 3) return readUnicodeString(length); else return readStandardString(length); } } File file = new File(fileName); return file.getName().replace(' ', '-'); } /** Extracts the names of the font in all the languages available. * @param id the name id to retrieve * @throws DocumentException on error * @throws IOException on error */ String[][] getNames(int id) throws DocumentException, IOException { int table_location[]; table_location = (int[])tables.get("name"); if (table_location == null) throw new DocumentException("Table 'name' does not exist in " + fileName + style); rf.seek(table_location[0] + 2); int numRecords = rf.readUnsignedShort(); int startOfStorage = rf.readUnsignedShort(); ArrayList names = new ArrayList(); for (int k = 0; k < numRecords; ++k) { int platformID = rf.readUnsignedShort(); int platformEncodingID = rf.readUnsignedShort(); int languageID = rf.readUnsignedShort(); int nameID = rf.readUnsignedShort(); int length = rf.readUnsignedShort(); int offset = rf.readUnsignedShort(); if (nameID == id) { int pos = rf.getFilePointer(); rf.seek(table_location[0] + startOfStorage + offset); String name; if (platformID == 0 || platformID == 3 || (platformID == 2 && platformEncodingID == 1)){ name = readUnicodeString(length); } else { name = readStandardString(length); } names.add(new String[]{String.valueOf(platformID), String.valueOf(platformEncodingID), String.valueOf(languageID), name}); rf.seek(pos); } } String thisName[][] = new String[names.size()][]; for (int k = 0; k < names.size(); ++k) thisName[k] = (String[])names.get(k); return thisName; } /** Extracts all the names of the names-Table * @throws DocumentException on error * @throws IOException on error */ String[][] getAllNames() throws DocumentException, IOException { int table_location[]; table_location = (int[])tables.get("name"); if (table_location == null) throw new DocumentException("Table 'name' does not exist in " + fileName + style); rf.seek(table_location[0] + 2); int numRecords = rf.readUnsignedShort(); int startOfStorage = rf.readUnsignedShort(); ArrayList names = new ArrayList(); for (int k = 0; k < numRecords; ++k) { int platformID = rf.readUnsignedShort(); int platformEncodingID = rf.readUnsignedShort(); int languageID = rf.readUnsignedShort(); int nameID = rf.readUnsignedShort(); int length = rf.readUnsignedShort(); int offset = rf.readUnsignedShort(); int pos = rf.getFilePointer(); rf.seek(table_location[0] + startOfStorage + offset); String name; if (platformID == 0 || platformID == 3 || (platformID == 2 && platformEncodingID == 1)){ name = readUnicodeString(length); } else { name = readStandardString(length); } names.add(new String[]{String.valueOf(nameID), String.valueOf(platformID), String.valueOf(platformEncodingID), String.valueOf(languageID), name}); rf.seek(pos); } String thisName[][] = new String[names.size()][]; for (int k = 0; k < names.size(); ++k) thisName[k] = (String[])names.get(k); return thisName; } void checkCff() { int table_location[]; table_location = (int[])tables.get("CFF "); if (table_location != null) { cff = true; cffOffset = table_location[0]; cffLength = table_location[1]; } } /** Reads the font data. * @param ttfAfm the font as a <CODE>byte</CODE> array, possibly <CODE>null</CODE> * @throws DocumentException the font is invalid * @throws IOException the font file could not be read */ void process(byte ttfAfm[]) throws DocumentException, IOException { tables = new HashMap(); try { if (ttfAfm == null) rf = new RandomAccessFileOrArray(fileName); else rf = new RandomAccessFileOrArray(ttfAfm); if (ttcIndex.length() > 0) { int dirIdx = Integer.parseInt(ttcIndex); if (dirIdx < 0) throw new DocumentException("The font index for " + fileName + " must be positive."); String mainTag = readStandardString(4); if (!mainTag.equals("ttcf")) throw new DocumentException(fileName + " is not a valid TTC file."); rf.skipBytes(4); int dirCount = rf.readInt(); if (dirIdx >= dirCount) throw new DocumentException("The font index for " + fileName + " must be between 0 and " + (dirCount - 1) + ". It was " + dirIdx + "."); rf.skipBytes(dirIdx * 4); directoryOffset = rf.readInt(); } rf.seek(directoryOffset); int ttId = rf.readInt(); if (ttId != 0x00010000 && ttId != 0x4F54544F) throw new DocumentException(fileName + " is not a valid TTF or OTF file."); int num_tables = rf.readUnsignedShort(); rf.skipBytes(6); for (int k = 0; k < num_tables; ++k) { String tag = readStandardString(4); rf.skipBytes(4); int table_location[] = new int[2]; table_location[0] = rf.readInt(); table_location[1] = rf.readInt(); tables.put(tag, table_location); } checkCff(); fontName = getBaseFont(); fullName = getNames(4); //full name familyName = getNames(1); //family name allNameEntries = getAllNames(); if (!justNames) { fillTables(); readGlyphWidths(); readCMaps(); readKerning(); readBbox(); GlyphWidths = null; } } finally { if (rf != null) { rf.close(); if (!embedded) rf = null; } } } /** Reads a <CODE>String</CODE> from the font file as bytes using the Cp1252 * encoding. * @param length the length of bytes to read * @return the <CODE>String</CODE> read * @throws IOException the font file could not be read */ protected String readStandardString(int length) throws IOException { byte buf[] = new byte[length]; rf.readFully(buf); try { return new String(buf, WINANSI); } catch (Exception e) { throw new ExceptionConverter(e); } } /** Reads a Unicode <CODE>String</CODE> from the font file. Each character is * represented by two bytes. * @param length the length of bytes to read. The <CODE>String</CODE> will have <CODE>length</CODE>/2 * characters * @return the <CODE>String</CODE> read * @throws IOException the font file could not be read */ protected String readUnicodeString(int length) throws IOException { StringBuffer buf = new StringBuffer(); length /= 2; for (int k = 0; k < length; ++k) { buf.append(rf.readChar()); } return buf.toString(); } /** Reads the glyphs widths. The widths are extracted from the table 'hmtx'. * The glyphs are normalized to 1000 units. * @throws DocumentException the font is invalid * @throws IOException the font file could not be read */ protected void readGlyphWidths() throws DocumentException, IOException { int table_location[]; table_location = (int[])tables.get("hmtx"); if (table_location == null) throw new DocumentException("Table 'hmtx' does not exist in " + fileName + style); rf.seek(table_location[0]); GlyphWidths = new int[hhea.numberOfHMetrics]; for (int k = 0; k < hhea.numberOfHMetrics; ++k) { GlyphWidths[k] = (rf.readUnsignedShort() * 1000) / head.unitsPerEm; rf.readUnsignedShort(); } } /** Gets a glyph width. * @param glyph the glyph to get the width of * @return the width of the glyph in normalized 1000 units */ protected int getGlyphWidth(int glyph) { if (glyph >= GlyphWidths.length) glyph = GlyphWidths.length - 1; return GlyphWidths[glyph]; } private void readBbox() throws DocumentException, IOException { int tableLocation[]; tableLocation = (int[])tables.get("head"); if (tableLocation == null) throw new DocumentException("Table 'head' does not exist in " + fileName + style); rf.seek(tableLocation[0] + TrueTypeFontSubSet.HEAD_LOCA_FORMAT_OFFSET); boolean locaShortTable = (rf.readUnsignedShort() == 0); tableLocation = (int[])tables.get("loca"); if (tableLocation == null) return; rf.seek(tableLocation[0]); int locaTable[]; if (locaShortTable) { int entries = tableLocation[1] / 2; locaTable = new int[entries]; for (int k = 0; k < entries; ++k) locaTable[k] = rf.readUnsignedShort() * 2; } else { int entries = tableLocation[1] / 4; locaTable = new int[entries];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -