diff --git a/src/main/java/org/mabb/fontverter/opentype/CmapSubTable.java b/src/main/java/org/mabb/fontverter/opentype/CmapSubTable.java index 9119879..fa4eeb3 100644 --- a/src/main/java/org/mabb/fontverter/opentype/CmapSubTable.java +++ b/src/main/java/org/mabb/fontverter/opentype/CmapSubTable.java @@ -17,6 +17,7 @@ package org.mabb.fontverter.opentype; +import org.apache.fontbox.cff.CFFStandardEncoding; import org.mabb.fontverter.io.FontDataInput; import org.mabb.fontverter.opentype.GlyphMapReader.GlyphMapping; import org.mabb.fontverter.io.FontDataInputStream; @@ -169,6 +170,8 @@ public void readData(FontDataInput input) throws IOException { } static class Format6SubTable extends CmapSubTable { + private Map charCodeToGlyphId = new LinkedHashMap(); + public Format6SubTable() { formatNumber = 6; } @@ -186,12 +189,25 @@ public byte[] getData() throws IOException { public int glyphCount() { return 0; } + + @Override + public List getGlyphMappings() { + return GlyphMapReader.readCharCodesToGlyphs(charCodeToGlyphId, CFFStandardEncoding.getInstance()); + } public void readData(FontDataInput input) throws IOException { int length = input.readUnsignedShort(); rawReadData = input.readBytes(length - 4); input = new FontDataInputStream(rawReadData); + languageId = input.readUnsignedShort(); + int firstCode = input.readUnsignedShort(); + int entryCount = input.readUnsignedShort(); + int[] glyphIndex = input.readUnsignedShortArray( entryCount ); + + for(int i = 0; i < entryCount; i++) { + charCodeToGlyphId.put( firstCode+i, glyphIndex[i] ); + } } } diff --git a/src/main/java/org/mabb/fontverter/opentype/CmapTable.java b/src/main/java/org/mabb/fontverter/opentype/CmapTable.java index 65c3ce1..306db13 100644 --- a/src/main/java/org/mabb/fontverter/opentype/CmapTable.java +++ b/src/main/java/org/mabb/fontverter/opentype/CmapTable.java @@ -19,6 +19,7 @@ import org.mabb.fontverter.io.FontDataInput; +import org.mabb.fontverter.opentype.CmapSubTable.Format0SubTable; import org.mabb.fontverter.opentype.GlyphMapReader.GlyphMapping; import org.mabb.fontverter.io.FontDataInputStream; import org.mabb.fontverter.io.FontDataOutputStream; @@ -53,7 +54,67 @@ int numTables() { public String getTableType() { return "cmap"; } + + @Override + public void normalize() throws IOException { + super.normalize(); + + Format4SubTable newWindowsTable = null; + Format4SubTable newUnixTable = null; + Format0SubTable newMacTable = null; + + if( this.windowsTable == null ) { + newWindowsTable = new Format4SubTable(); + newWindowsTable.setPlatformId(3); + newWindowsTable.setEncodingId(1); + + this.windowsTable = newWindowsTable; + } + + if( this.unixTable == null ) { + newUnixTable = new Format4SubTable(); + newUnixTable.setPlatformId(0); + newUnixTable.setEncodingId(3); + + this.unixTable = newUnixTable; + } + if( this.macTable == null ) { + newMacTable = new Format0SubTable(); + newMacTable.setPlatformId(1); + newMacTable.setEncodingId(0); + + this.macTable = newMacTable; + } + + if( newWindowsTable != null || newUnixTable != null || newMacTable != null ) { + for( GlyphMapping m : getGlyphMappings() ) { + if( m.glyphId > 0 ) { + if( newWindowsTable != null ) { + newWindowsTable.addGlyphMapping( m.charCode, m.glyphId ); + } + if( newUnixTable != null ) { + newUnixTable.addGlyphMapping( m.charCode, m.glyphId ); + } + if( newMacTable != null ) { + newMacTable.addGlyphMapping( m.charCode, m.glyphId ); + } + } + } + if( newWindowsTable != null ) { + this.subTables.add(newWindowsTable); + } + + if( newUnixTable != null ) { + this.subTables.add(newUnixTable); + } + + if( newMacTable != null ) { + this.subTables.add(newMacTable); + } + } + } + @Override protected byte[] generateUnpaddedData() throws IOException { calculateOffsets(); @@ -117,6 +178,17 @@ else if (format == 14) subTable.setEncodingId(header.encodingID); subTable.setPlatformId(header.platformID); subTables.add(subTable); + + if( header.platformID == 0 + && subTable instanceof Format4SubTable) { + this.unixTable = (Format4SubTable) subTable; + } else if( header.platformID == 1 + && subTable instanceof Format0SubTable) { + this.macTable = (Format0SubTable) subTable; + } else if( header.platformID == 3 + && subTable instanceof Format4SubTable) { + this.windowsTable = (Format4SubTable) subTable; + } } } diff --git a/src/main/java/org/mabb/fontverter/opentype/OpenTypeFont.java b/src/main/java/org/mabb/fontverter/opentype/OpenTypeFont.java index 8b3e184..c65ddb0 100644 --- a/src/main/java/org/mabb/fontverter/opentype/OpenTypeFont.java +++ b/src/main/java/org/mabb/fontverter/opentype/OpenTypeFont.java @@ -31,6 +31,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.UUID; import static org.mabb.fontverter.opentype.SfntHeader.*; @@ -139,9 +140,34 @@ public void normalize() throws IOException { if (getOs2() == null) createNewOS2WinMetricsTable(); - if (getNameTable() == null) + if (getNameTable() == null) { setName(NameTable.createDefaultTable()); + } else { + if( getNameTable().getName( OtfNameConstants.RecordType.FONT_FAMILY ) == null ) { + getNameTable().setFontFamily( "DefaultFamily" ); + } + + if( getNameTable().getName( OtfNameConstants.RecordType.FONT_SUB_FAMILY ) == null ) { + getNameTable().setFontSubFamily( "Normal" ); + } + + if( getNameTable().getName( OtfNameConstants.RecordType.FULL_FONT_NAME ) == null ) { + getNameTable().setFontFullName( "DefaultFontFullName" ); + } + + if( getNameTable().getName( OtfNameConstants.RecordType.POSTSCRIPT_NAME ) == null ) { + getNameTable().setPostScriptName( "DefaultPostScriptName" ); + } + if( getNameTable().getName( OtfNameConstants.RecordType.UNIQUE_FONT_ID ) == null ) { + getNameTable().setUniqueId( UUID.randomUUID().toString().replace("-", "")); + } + + if( getNameTable().getName( OtfNameConstants.RecordType.VERSION_STRING ) == null ) { + getNameTable().setVersion( "Version 1.1" ); + } + } + if (getPost() == null) setPost(PostScriptTable.createDefaultTable(getOpenTypeVersion())); @@ -229,6 +255,11 @@ private void normalizeTables() throws IOException { if (sfntHeader.sfntFlavor.isEmpty()) sfntHeader.sfntFlavor = determineSfntFlavor(); + CmapTable cmap = getCmap(); + if( cmap != null ) { + cmap.normalize(); + } + if (getCmap() != null && getMxap() != null && !getMxap().isFromParsedFont) getMxap().setNumGlyphs(getCmap().getGlyphCount());