diff options
-rw-r--r-- | src/java/org/apache/fop/fonts/FontDescriptor.java | 5 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/LazyFont.java | 12 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/MultiByteFont.java | 40 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/SingleByteFont.java | 6 | ||||
-rw-r--r-- | src/java/org/apache/fop/pdf/PDFFactory.java | 37 | ||||
-rw-r--r-- | status.xml | 3 | ||||
-rw-r--r-- | test/java/org/apache/fop/UtilityCodeTestSuite.java | 2 | ||||
-rw-r--r-- | test/java/org/apache/fop/pdf/PDFFactoryTestCase.java | 58 |
8 files changed, 121 insertions, 42 deletions
diff --git a/src/java/org/apache/fop/fonts/FontDescriptor.java b/src/java/org/apache/fop/fonts/FontDescriptor.java index e7c81c9f3..8aea105be 100644 --- a/src/java/org/apache/fop/fonts/FontDescriptor.java +++ b/src/java/org/apache/fop/fonts/FontDescriptor.java @@ -86,5 +86,10 @@ public interface FontDescriptor extends FontMetrics { */ boolean isEmbeddable(); + /** + * Indicates whether this font is subset embedded. + * @return true if this font is subset embedded + */ + boolean isSubsetEmbedded(); } diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index a8fd447c4..f331a331e 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -27,12 +27,10 @@ import java.util.Set; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; -import org.xml.sax.InputSource; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.apps.FOPException; +import org.xml.sax.InputSource; /** * This class is used to defer the loading of a font until it is really used. @@ -375,5 +373,13 @@ public class LazyFont extends Typeface implements FontDescriptor { return realFontDescriptor.isEmbeddable(); } + /** + * {@inheritDoc} + */ + public boolean isSubsetEmbedded() { + load(true); + return realFont.isMultiByte(); + } + } diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index 629bfa1b7..397ca8a84 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -20,7 +20,6 @@ package org.apache.fop.fonts; //Java -import java.text.DecimalFormat; import java.util.Map; @@ -29,16 +28,12 @@ import java.util.Map; */ public class MultiByteFont extends CIDFont { - private static int uniqueCounter = -1; - private String ttcName = null; private String encoding = "Identity-H"; private int defaultWidth = 0; private CIDFontType cidType = CIDFontType.CIDTYPE2; - private String namePrefix = null; // Quasi unique prefix - private CIDSubset subset = new CIDSubset(); /** A map from Unicode indices to glyph indices */ @@ -49,31 +44,11 @@ public class MultiByteFont extends CIDFont { */ public MultiByteFont() { subset.setupFirstGlyph(); - - // Create a quasiunique prefix for fontname - synchronized (this.getClass()) { - uniqueCounter++; - if (uniqueCounter > 99999 || uniqueCounter < 0) { - uniqueCounter = 0; //We need maximum 5 character then we start again - } - } - DecimalFormat counterFormat = new DecimalFormat("00000"); - String cntString = counterFormat.format(uniqueCounter); - - //Subset prefix as described in chapter 5.5.3 of PDF 1.4 - StringBuffer sb = new StringBuffer("E"); - for (int i = 0, c = cntString.length(); i < c; i++) { - //translate numbers to uppercase characters - sb.append((char)(cntString.charAt(i) + (65 - 48))); - } - sb.append("+"); - namePrefix = sb.toString(); - setFontType(FontType.TYPE0); } - /** {@inheritDoc} */ - public int getDefaultWidth() { + /** {@inheritdoc} */ + public int getdefaultwidth() { return defaultWidth; } @@ -105,14 +80,10 @@ public class MultiByteFont extends CIDFont { this.cidType = cidType; } - private String getPrefixedFontName() { - return namePrefix + FontUtil.stripWhiteSpace(super.getFontName()); - } - /** {@inheritDoc} */ public String getEmbedFontName() { if (isEmbeddable()) { - return getPrefixedFontName(); + return FontUtil.stripWhiteSpace(super.getFontName()); } else { return super.getFontName(); } @@ -124,6 +95,11 @@ public class MultiByteFont extends CIDFont { } /** {@inheritDoc} */ + public boolean isSubsetEmbedded() { + return true; + } + + /** {@inheritDoc} */ public CIDSubset getCIDSubset() { return this.subset; } diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index 0605cd11e..d5901297f 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -63,7 +63,11 @@ public class SingleByteFont extends CustomFont { } /** {@inheritDoc} */ - @Override + public boolean isSubsetEmbedded() { + return false; + } + + /** {@inheritDoc} */ public String getEncodingName() { return this.mapping.getName(); } diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index 23542a49e..64941be94 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -27,6 +27,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; @@ -63,6 +64,7 @@ import org.apache.fop.fonts.truetype.FontFileReader; import org.apache.fop.fonts.truetype.TTFSubSetFile; import org.apache.fop.fonts.type1.PFBData; import org.apache.fop.fonts.type1.PFBParser; +import org.apache.xmlgraphics.xmp.Metadata; /** * This class provides method to create and register PDF objects. @@ -76,6 +78,8 @@ public class PDFFactory { private Log log = LogFactory.getLog(PDFFactory.class); + private int subsetFontCounter = -1; + /** * Creates a new PDFFactory. * @param document the parent PDFDocument needed to register the generated @@ -1377,10 +1381,15 @@ public class PDFFactory { } else { FontType fonttype = metrics.getFontType(); - PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor); + String fontPrefix = descriptor.isSubsetEmbedded() ? createSubsetFontPrefix() : ""; + + String subsetFontName = fontPrefix + basefont; + + PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor, fontPrefix); PDFFont font = null; - font = PDFFont.createFont(fontname, fonttype, basefont, null); + + font = PDFFont.createFont(fontname, fonttype, subsetFontName, null); getDocument().registerObject(font); if (fonttype == FontType.TYPE0) { @@ -1395,8 +1404,7 @@ public class PDFFactory { = new PDFCIDSystemInfo(cidMetrics.getRegistry(), cidMetrics.getOrdering(), cidMetrics.getSupplement()); - PDFCIDFont cidFont - = new PDFCIDFont(basefont, + PDFCIDFont cidFont = new PDFCIDFont(subsetFontName, cidMetrics.getCIDType(), cidMetrics.getDefaultWidth(), getSubsetWidths(cidMetrics), sysInfo, @@ -1550,18 +1558,35 @@ public class PDFFactory { return warray; } + private String createSubsetFontPrefix() { + subsetFontCounter++; + DecimalFormat counterFormat = new DecimalFormat("00000"); + String counterString = counterFormat.format(subsetFontCounter); + + // Subset prefix as described in chapter 5.5.3 of PDF 1.4 + StringBuffer sb = new StringBuffer("E"); + + for (char c : counterString.toCharArray()) { + // translate numbers to uppercase characters + sb.append((char) (c + ('A' - '0'))); + } + sb.append("+"); + return sb.toString(); + } + /** * make a /FontDescriptor object * * @param desc the font descriptor + * @param fontPrefix the String with which to prefix the font name * @return the new PDF font descriptor */ - public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc) { + private PDFFontDescriptor makeFontDescriptor(FontDescriptor desc, String fontPrefix) { PDFFontDescriptor descriptor = null; if (desc.getFontType() == FontType.TYPE0) { // CID Font - descriptor = new PDFCIDFontDescriptor(desc.getEmbedFontName(), + descriptor = new PDFCIDFontDescriptor(fontPrefix + desc.getEmbedFontName(), desc.getFontBBox(), desc.getCapHeight(), desc.getFlags(), diff --git a/status.xml b/status.xml index b843ec401..c636c33e3 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,9 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> <release version="FOP Trunk" date="TBD"> + <action context="Fonts" dev="PH" type="fix" fixes-bug="51759" due-to="Mehdi Houshmand"> + PDFFactory responsible for asdigning name to a subset font. + </action> <action context="Fonts" dev="PH" type="fix" fixes-bug="51530" due-to="Mehdi Houshmand"> Improved support for EBCDIC encoded double byte fonts fo AFP. </action> diff --git a/test/java/org/apache/fop/UtilityCodeTestSuite.java b/test/java/org/apache/fop/UtilityCodeTestSuite.java index 9ef3c5510..ac0ea00ad 100644 --- a/test/java/org/apache/fop/UtilityCodeTestSuite.java +++ b/test/java/org/apache/fop/UtilityCodeTestSuite.java @@ -25,6 +25,7 @@ import junit.framework.TestSuite; import org.apache.fop.events.BasicEventTestCase; import org.apache.fop.pdf.FileIDGeneratorTestCase; import org.apache.fop.pdf.PDFEncryptionJCETestCase; +import org.apache.fop.pdf.PDFFactoryTestCase; import org.apache.fop.pdf.PDFObjectTestCase; import org.apache.fop.traits.BorderPropsTestCase; import org.apache.fop.util.BitmapImageUtilTestCase; @@ -49,6 +50,7 @@ public class UtilityCodeTestSuite { suite.addTest(new TestSuite(PDFNumberTestCase.class)); suite.addTest(new TestSuite(PDFObjectTestCase.class)); suite.addTest(FileIDGeneratorTestCase.suite()); + suite.addTest(new TestSuite(PDFFactoryTestCase.class)); suite.addTest(new TestSuite(ColorUtilTestCase.class)); suite.addTest(new TestSuite(BorderPropsTestCase.class)); suite.addTest(new TestSuite(ElementListUtilsTestCase.class)); diff --git a/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java b/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java new file mode 100644 index 000000000..d81eb228a --- /dev/null +++ b/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.pdf; + +import junit.framework.TestCase; + +import org.apache.fop.fonts.CIDSubset; +import org.apache.fop.fonts.MultiByteFont; + +/** + * Test case for {@link PDFFactory}. + */ +public class PDFFactoryTestCase extends TestCase { + + /** + * This tests that when a font is subset embedded in a PDF, the font name is prefixed with a + * pseudo-random tag as per the PDF spec. + */ + public void testSubsetFontNamePrefix() { + class MockedFont extends MultiByteFont { + @Override + public int[] getWidths() { + return new int[] { 0 }; + } + + @Override + public CIDSubset getCIDSubset() { + return new CIDSubset(); + } + } + PDFDocument doc = new PDFDocument("Test"); + PDFFactory pdfFactory = new PDFFactory(doc); + MockedFont font = new MockedFont(); + + PDFFont pdfDejaVu = pdfFactory.makeFont("DejaVu", "DejaVu", "TTF", font, font); + assertEquals("/EAAAAA+DejaVu", pdfDejaVu.getBaseFont().toString()); + + PDFFont pdfArial = pdfFactory.makeFont("Arial", "Arial", "TTF", font, font); + assertEquals("/EAAAAB+Arial", pdfArial.getBaseFont().toString()); + } +} |