TTFSubsetter { public void writeToStream(OutputStream os) throws IOException { if (glyphIds.isEmpty() || uniToGID.isEmpty()) { throw new IllegalStateException("subset is empty"); } addCompoundReferences(); DataOutputStream out = new DataOutputStream(os); try { long[] newLoca = new long[glyphIds.size() + 1]; byte[] head = buildHeadTable(); byte[] hhea = buildHheaTable(); byte[] maxp = buildMaxpTable(); byte[] name = buildNameTable(); byte[] os2 = buildOS2Table(); byte[] glyf = buildGlyfTable(newLoca); byte[] loca = buildLocaTable(newLoca); byte[] cmap = buildCmapTable(); byte[] hmtx = buildHmtxTable(); byte[] post = buildPostTable(); Map<String, byte[]> tables = new TreeMap<String, byte[]>(); if (os2 != null) { tables.put("OS/2", os2); } if (cmap != null) { tables.put("cmap", cmap); } if (glyf != null) { tables.put("glyf", glyf); } tables.put("head", head); tables.put("hhea", hhea); tables.put("hmtx", hmtx); if (loca != null) { tables.put("loca", loca); } tables.put("maxp", maxp); if (name != null) { tables.put("name", name); } if (post != null) { tables.put("post", post); } for (Map.Entry<String, TTFTable> entry : ttf.getTableMap().entrySet()) { String tag = entry.getKey(); TTFTable table = entry.getValue(); if (!tables.containsKey(tag) && (keepTables == null || keepTables.contains(tag))) { tables.put(tag, ttf.getTableBytes(table)); } } long checksum = writeFileHeader(out, tables.size()); long offset = 12L + 16L * tables.size(); for (Map.Entry<String, byte[]> entry : tables.entrySet()) { checksum += writeTableHeader(out, entry.getKey(), offset, entry.getValue()); offset += (entry.getValue().length + 3) / 4 * 4; } checksum = 0xB1B0AFBAL - (checksum & 0xffffffffL); head[8] = (byte)(checksum >>> 24); head[9] = (byte)(checksum >>> 16); head[10] = (byte)(checksum >>> 8); head[11] = (byte)checksum; for (byte[] bytes : tables.values()) { writeTableBody(out, bytes); } } finally { out.close(); } } TTFSubsetter(TrueTypeFont ttf);  TTFSubsetter(TrueTypeFont ttf, List<String> tables); void setPrefix(String prefix); void add(int unicode); void addAll(Set<Integer> unicodeSet); Map<Integer, Integer> getGIDMap(); void writeToStream(OutputStream os);  }
@Test public void testEmptySubset() throws IOException { File testFile = null; try { testFile = new File( getClass().getResource("/fontbox/ttf/LiberationSans-Regular.ttf").toURI()); } catch (URISyntaxException e) { e.printStackTrace(); fail(); } TrueTypeFont x = new TTFParser().parse(testFile); TTFSubsetter ttfSubsetter = new TTFSubsetter(x); try { ttfSubsetter.writeToStream(new ByteArrayOutputStream()); fail("IllegalStateException should be thrown"); } catch (IllegalStateException e) { } }