/** * Creates a new empty table builder for the table type given by the table id tag. * * <p>This new table will be added to the font and will replace any existing builder for that * table. * * @param tag * @return new empty table of the type specified by tag; if tag is not known then a generic * OpenTypeTable is returned */ public Table.Builder<? extends Table> newTableBuilder(int tag) { Header header = new Header(tag); Table.Builder<? extends Table> builder = Table.Builder.getBuilder(header, null); this.tableBuilders.put(header.tag(), builder); return builder; }
private Map<Header, WritableFontData> loadTableData( SortedSet<Header> headers, WritableFontData fd) { Map<Header, WritableFontData> tableData = new HashMap<Header, WritableFontData>(headers.size()); logger.fine("######## Reading Table Data"); for (Header tableHeader : headers) { WritableFontData data = fd.slice(tableHeader.offset(), tableHeader.length()); tableData.put(tableHeader, data); } return tableData; }
private Map<Integer, Table.Builder<? extends Table>> buildAllTableBuilders( Map<Header, WritableFontData> tableData) { Map<Integer, Table.Builder<? extends Table>> builderMap = new HashMap<Integer, Table.Builder<? extends Table>>(); Set<Header> records = tableData.keySet(); for (Header record : records) { Table.Builder<? extends Table> builder = getTableBuilder(record, tableData.get(record)); builderMap.put(record.tag(), builder); } interRelateBuilders(builderMap); return builderMap; }
/** * Serialize the tables. * * @param fos the destination stream for the headers * @param tableHeaders the headers for the tables to serialize * @throws IOException */ private void serializeTables(FontOutputStream fos, List<Header> tableHeaders) throws IOException { for (Header record : tableHeaders) { Table table = this.getTable(record.tag()); if (table == null) { throw new IOException("Table out of sync with font header."); } int tableSize = table.serialize(fos); int fillerSize = ((tableSize + 3) & ~3) - tableSize; for (int i = 0; i < fillerSize; i++) { fos.write(0); } } }
private Map<Header, WritableFontData> loadTableData( SortedSet<Header> headers, FontInputStream is) throws IOException { Map<Header, WritableFontData> tableData = new HashMap<Header, WritableFontData>(headers.size()); logger.fine("######## Reading Table Data"); for (Header tableHeader : headers) { is.skip(tableHeader.offset() - is.position()); logger.finer("\t" + tableHeader); logger.finest("\t\tStream Position = " + Integer.toHexString((int) is.position())); // don't close this or the whole stream is gone FontInputStream tableIS = new FontInputStream(is, tableHeader.length()); // TODO(stuartg): start tracking bad tables and other errors WritableFontData data = WritableFontData.createWritableFontData(tableHeader.length()); data.copyFrom(tableIS, tableHeader.length()); tableData.put(tableHeader, data); } return tableData; }
/** * Searialize the headers. * * @param fos the destination stream for the headers * @param tableHeaders the headers to serialize * @throws IOException */ private void serializeHeader(FontOutputStream fos, List<Header> tableHeaders) throws IOException { fos.writeFixed(this.sfntVersion); fos.writeUShort(tableHeaders.size()); int log2OfMaxPowerOf2 = FontMath.log2(tableHeaders.size()); int searchRange = 2 << (log2OfMaxPowerOf2 - 1 + 4); fos.writeUShort(searchRange); fos.writeUShort(log2OfMaxPowerOf2); fos.writeUShort((tableHeaders.size() * 16) - searchRange); List<Header> sortedHeaders = new ArrayList<Header>(tableHeaders); Collections.sort(sortedHeaders, Header.COMPARATOR_BY_TAG); for (Header record : sortedHeaders) { fos.writeULong(record.tag()); fos.writeULong(record.checksum()); fos.writeULong(record.offset()); fos.writeULong(record.length()); } }