diff options
author | Simon Steiner <ssteiner@apache.org> | 2020-10-30 15:06:49 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2020-10-30 15:06:49 +0000 |
commit | 3bd145534c2f6d1755835eb071a13298db7be850 (patch) | |
tree | 7e4eea996c8b327bba39b9b39851e6caea5bad6e | |
parent | e92a71fbd66bb441984f45d91227c3cedfa94f75 (diff) | |
download | xmlgraphics-fop-3bd145534c2f6d1755835eb071a13298db7be850.tar.gz xmlgraphics-fop-3bd145534c2f6d1755835eb071a13298db7be850.zip |
FOP-2981: Convert CFF CID to Type1
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1882997 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | fop-core/src/main/java/org/apache/fop/fonts/CFFToType1Font.java | 11 | ||||
-rw-r--r-- | fop-core/src/main/java/org/apache/fop/render/ps/Type1FontFormatter.java | 54 | ||||
-rw-r--r-- | fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java | 15 | ||||
-rw-r--r-- | fop/test/resources/fonts/otf/AlexBrush-Regular-cid.otf | bin | 0 -> 23240 bytes |
4 files changed, 58 insertions, 22 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/CFFToType1Font.java b/fop-core/src/main/java/org/apache/fop/fonts/CFFToType1Font.java index a1b523811..3ef9b6e33 100644 --- a/fop-core/src/main/java/org/apache/fop/fonts/CFFToType1Font.java +++ b/fop-core/src/main/java/org/apache/fop/fonts/CFFToType1Font.java @@ -30,7 +30,6 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.fontbox.cff.CFFFont; import org.apache.fontbox.cff.CFFParser; -import org.apache.fontbox.cff.CFFType1Font; import org.apache.fop.apps.io.InternalResourceResolver; import org.apache.fop.fonts.type1.PFBData; @@ -57,9 +56,6 @@ public class CFFToType1Font extends MultiByteFont { private List<InputStream> convertOTFToType1(InputStream in) throws IOException { CFFFont f = new CFFParser().parse(IOUtils.toByteArray(in)).get(0); - if (!(f instanceof CFFType1Font)) { - throw new IOException(getEmbedFileURI() + ": only OTF CFF Type1 font can be converted to Type1"); - } List<InputStream> fonts = new ArrayList<InputStream>(); Map<Integer, Integer> glyphs = cidSet.getGlyphs(); int i = 0; @@ -88,9 +84,10 @@ public class CFFToType1Font extends MultiByteFont { return allGlyphs; } - private InputStream convertOTFToType1(Map<Integer, Integer> glyphs, CFFFont f, String i) throws IOException { - byte[] t1 = new Type1FontFormatter(glyphs).format((CFFType1Font) f, i); - PFBData pfb = new PFBParser().parsePFB(new ByteArrayInputStream(t1)); + private InputStream convertOTFToType1(Map<Integer, Integer> glyphs, CFFFont cffFont, String splitGlyphsId) + throws IOException { + byte[] type1Bytes = new Type1FontFormatter(glyphs).format(cffFont, splitGlyphsId); + PFBData pfb = new PFBParser().parsePFB(new ByteArrayInputStream(type1Bytes)); ByteArrayOutputStream s1 = new ByteArrayOutputStream(); s1.write(pfb.getHeaderSegment()); ByteArrayOutputStream s2 = new ByteArrayOutputStream(); diff --git a/fop-core/src/main/java/org/apache/fop/render/ps/Type1FontFormatter.java b/fop-core/src/main/java/org/apache/fop/render/ps/Type1FontFormatter.java index 0d1936702..776d410f9 100644 --- a/fop-core/src/main/java/org/apache/fop/render/ps/Type1FontFormatter.java +++ b/fop-core/src/main/java/org/apache/fop/render/ps/Type1FontFormatter.java @@ -24,6 +24,8 @@ import java.util.Collection; import java.util.Locale; import java.util.Map; +import org.apache.fontbox.cff.CFFCIDFont; +import org.apache.fontbox.cff.CFFFont; import org.apache.fontbox.cff.CFFType1Font; import org.apache.fontbox.cff.DataOutput; import org.apache.fontbox.cff.Type1FontUtil; @@ -47,13 +49,13 @@ public final class Type1FontFormatter { * @return the Type1 font * @throws IOException if an error occurs during reading the given font */ - public byte[] format(CFFType1Font font, String i) throws IOException { + public byte[] format(CFFFont font, String i) throws IOException { DataOutput output = new DataOutput(); printFont(font, output, i); return output.getBytes(); } - private void printFont(CFFType1Font font, DataOutput output, String iStr) + private void printFont(CFFFont font, DataOutput output, String iStr) throws IOException { output.println("%!FontType1-1.0 " + font.getName() + iStr + " " + font.getTopDict().get("version")); @@ -73,7 +75,7 @@ public final class Type1FontFormatter { output.println("cleartomark"); } - private void printFontDictionary(CFFType1Font font, DataOutput output, String iStr) + private void printFontDictionary(CFFFont font, DataOutput output, String iStr) throws IOException { output.println("10 dict begin"); output.println("/FontInfo 10 dict dup begin"); @@ -112,7 +114,13 @@ public final class Type1FontFormatter { int max = 0; StringBuilder sb = new StringBuilder(); for (Map.Entry<Integer, Integer> gid : gids.entrySet()) { - String name = font.getCharset().getNameForGID(gid.getKey()); + String name = "gid_" + gid.getKey(); + if (gid.getKey() == 0) { + name = ".notdef"; + } + if (font instanceof CFFType1Font) { + name = font.getCharset().getNameForGID(gid.getKey()); + } sb.append(String.format("dup %d /%s put", gid.getValue(), name)).append('\n'); max = Math.max(max, gid.getValue()); } @@ -133,32 +141,48 @@ public final class Type1FontFormatter { output.write(eexecBytes); } - private void printEexecFontDictionary(CFFType1Font font, DataOutput output) + private void printEexecFontDictionary(CFFFont font, DataOutput output) throws IOException { output.println("dup /Private 15 dict dup begin"); output.println("/RD {string currentfile exch readstring pop} executeonly def"); output.println("/ND {noaccess def} executeonly def"); output.println("/NP {noaccess put} executeonly def"); + Map<String, Object> privDict; + if (font instanceof CFFCIDFont) { + privDict = ((CFFCIDFont)font).getPrivDicts().get(0); + } else { + privDict = ((CFFType1Font)font).getPrivateDict(); + } output.println("/BlueValues " - + formatArray(font.getPrivateDict().get("BlueValues"), true) + " ND"); + + formatArray(privDict.get("BlueValues"), true) + " ND"); output.println("/OtherBlues " - + formatArray(font.getPrivateDict().get("OtherBlues"), true) + " ND"); - output.println("/BlueScale " + font.getPrivateDict().get("BlueScale") + " def"); - output.println("/BlueShift " + font.getPrivateDict().get("BlueShift") + " def"); - output.println("/BlueFuzz " + font.getPrivateDict().get("BlueFuzz") + " def"); - output.println("/StdHW " + formatArray(font.getPrivateDict().get("StdHW"), true) + + formatArray(privDict.get("OtherBlues"), true) + " ND"); + output.println("/BlueScale " + privDict.get("BlueScale") + " def"); + output.println("/BlueShift " + privDict.get("BlueShift") + " def"); + output.println("/BlueFuzz " + privDict.get("BlueFuzz") + " def"); + output.println("/StdHW " + formatArray(privDict.get("StdHW"), true) + " ND"); - output.println("/StdVW " + formatArray(font.getPrivateDict().get("StdVW"), true) + output.println("/StdVW " + formatArray(privDict.get("StdVW"), true) + " ND"); - output.println("/ForceBold " + font.getPrivateDict().get("ForceBold") + " def"); + output.println("/ForceBold " + privDict.get("ForceBold") + " def"); output.println("/MinFeature {16 16} def"); output.println("/password 5839 def"); output.println("2 index /CharStrings " + gids.size() + " dict dup begin"); Type1CharStringFormatter formatter = new Type1CharStringFormatter(); for (int gid : gids.keySet()) { - String mapping = font.getCharset().getNameForGID(gid); - byte[] type1Bytes = formatter.format(font.getType1CharString(mapping).getType1Sequence()); + String mapping = "gid_" + gid; + if (gid == 0) { + mapping = ".notdef"; + } + byte[] type1Bytes; + if (font instanceof CFFCIDFont) { + int cid = font.getCharset().getCIDForGID(gid); + type1Bytes = formatter.format(((CFFCIDFont)font).getType2CharString(cid).getType1Sequence()); + } else { + mapping = font.getCharset().getNameForGID(gid); + type1Bytes = formatter.format(((CFFType1Font)font).getType1CharString(mapping).getType1Sequence()); + } byte[] charstringBytes = Type1FontUtil.charstringEncrypt(type1Bytes, 4); output.print("/" + mapping + " " + charstringBytes.length + " RD "); output.write(charstringBytes); diff --git a/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java index adea1d128..9194d16c7 100644 --- a/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java +++ b/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java @@ -21,6 +21,7 @@ package org.apache.fop.fonts.truetype; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.List; import org.junit.Assert; import org.junit.Test; @@ -54,6 +55,20 @@ public class OTFToType1TestCase { Assert.assertEquals(t1.getFontType(), FontType.TYPE1); } + @Test + public void testCIDFont() throws IOException { + CFFToType1Font realFont = (CFFToType1Font)getRealFont("test/resources/fonts/otf/AlexBrush-Regular-cid.otf"); + for (int i = 0; i < 10240; i++) { + realFont.mapChar((char) i); + } + List<InputStream> fonts = realFont.getInputStreams(); + InputStream is = fonts.get(0); + Type1Font t1 = Type1Font.createWithPFB(is); + Assert.assertEquals(t1.getFontName(), "AlexBrush-Regular.0"); + Assert.assertTrue(t1.getCharStringsDict().keySet().contains(".notdef")); + Assert.assertTrue(t1.getCharStringsDict().keySet().contains("gid_1")); + } + private Type1Font getFont(String s) throws IOException { InputStream is = ((CFFToType1Font)getRealFont(s)).getInputStreams().get(0); return Type1Font.createWithPFB(is); diff --git a/fop/test/resources/fonts/otf/AlexBrush-Regular-cid.otf b/fop/test/resources/fonts/otf/AlexBrush-Regular-cid.otf Binary files differnew file mode 100644 index 000000000..4b015be8c --- /dev/null +++ b/fop/test/resources/fonts/otf/AlexBrush-Regular-cid.otf |