From d6994df393ced4dd88e5edd5fdfdca38df0d875a Mon Sep 17 00:00:00 2001 From: Mehdi Houshmand Date: Thu, 23 Aug 2012 14:19:29 +0000 Subject: [PATCH] Bugfix#53766: Remove StandardEncoding as the encoding type from fonts used in the PDF renderer. Submitted by Robert Meyer. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1376500 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFEncoding.java | 99 ++++++++++++++----- src/java/org/apache/fop/pdf/PDFFactory.java | 37 +------ src/java/org/apache/fop/pdf/PDFFont.java | 2 +- status.xml | 3 + .../apache/fop/pdf/PDFEncodingTestCase.java | 76 ++++++++++++++ 5 files changed, 159 insertions(+), 58 deletions(-) create mode 100644 test/java/org/apache/fop/pdf/PDFEncodingTestCase.java diff --git a/src/java/org/apache/fop/pdf/PDFEncoding.java b/src/java/org/apache/fop/pdf/PDFEncoding.java index bf2799c70..25e791e0d 100644 --- a/src/java/org/apache/fop/pdf/PDFEncoding.java +++ b/src/java/org/apache/fop/pdf/PDFEncoding.java @@ -23,6 +23,9 @@ package org.apache.fop.pdf; import java.util.Collections; import java.util.Set; +import org.apache.fop.fonts.CodePointMapping; +import org.apache.fop.fonts.SingleByteEncoding; + /** * Class representing an /Encoding object. * @@ -73,6 +76,38 @@ public class PDFEncoding extends PDFDictionary { } } + /** + * Creates a PDFEncoding instance from a CodePointMapping instance. + * @param encoding the code point mapping (encoding) + * @param fontName ... + * @return the PDF Encoding dictionary (or a String with the predefined encoding) + */ + static Object createPDFEncoding(SingleByteEncoding encoding, String fontName) { + //If encoding type is null, return null which causes /Encoding to be omitted. + if (encoding == null) { + return null; + } + String encodingName = null; + SingleByteEncoding baseEncoding; + if (fontName.indexOf("Symbol") >= 0) { + baseEncoding = CodePointMapping.getMapping(CodePointMapping.SYMBOL_ENCODING); + encodingName = baseEncoding.getName(); + } else { + baseEncoding = CodePointMapping.getMapping(CodePointMapping.STANDARD_ENCODING); + } + PDFEncoding pdfEncoding = new PDFEncoding(encodingName); + PDFEncoding.DifferencesBuilder builder = pdfEncoding.createDifferencesBuilder(); + PDFArray differences = builder.buildDifferencesArray(baseEncoding, encoding); + // TODO This method should not be returning an Object with two different outcomes + // resulting in subsequent `if (X instanceof Y)` statements. + if (differences.length() > 0) { + pdfEncoding.setDifferences(differences); + return pdfEncoding; + } else { + return encodingName; + } + } + /** * Indicates whether a given encoding is one of the predefined encodings. * @param name the encoding name (ex. "StandardEncoding") @@ -82,6 +117,15 @@ public class PDFEncoding extends PDFDictionary { return PREDEFINED_ENCODINGS.contains(name); } + /** + * Indicates whether the given encoding type is that of standard encoding + * @param name The encoding name + * @return Returns true if it is of type standard encoding + */ + static boolean hasStandardEncoding(String encodingName) { + return encodingName.equals(STANDARD_ENCODING); + } + /** * Creates and returns a new DifferencesBuilder instance for constructing the Differences * array. @@ -104,18 +148,44 @@ public class PDFEncoding extends PDFDictionary { */ public class DifferencesBuilder { - private PDFArray differences = new PDFArray(); private int currentCode = -1; + /** + * Creates an array containing the differences between two single-byte. + * font encodings. + * @param encoding_A The first single-byte encoding + * @param encoding_B The second single-byte encoding + * @return The PDFArray of differences between encodings + */ + public PDFArray buildDifferencesArray(SingleByteEncoding encodingA, + SingleByteEncoding encodingB) { + PDFArray differences = new PDFArray(); + int start = -1; + String[] baseNames = encodingA.getCharNameMap(); + String[] charNameMap = encodingB.getCharNameMap(); + for (int i = 0, ci = charNameMap.length; i < ci; i++) { + String basec = baseNames[i]; + String c = charNameMap[i]; + if (!basec.equals(c)) { + if (start != i) { + addDifference(i, differences); + start = i; + } + addName(c, differences); + start++; + } + } + return differences; + } + /** * Start a new difference. * @param code the starting code index inside the encoding * @return this builder instance */ - public DifferencesBuilder addDifference(int code) { + private void addDifference(int code, PDFArray differences) { this.currentCode = code; - this.differences.add(new Integer(code)); - return this; + differences.add(Integer.valueOf(code)); } /** @@ -123,28 +193,11 @@ public class PDFEncoding extends PDFDictionary { * @param name the character name * @return this builder instance */ - public DifferencesBuilder addName(String name) { + private void addName(String name, PDFArray differences) { if (this.currentCode < 0) { throw new IllegalStateException("addDifference(int) must be called first"); } - this.differences.add(new PDFName(name)); - return this; - } - - /** - * Indicates whether any differences have been recorded. - * @return true if there are differences. - */ - public boolean hasDifferences() { - return (this.differences.length() > 0); - } - - /** - * Creates and returns the PDFArray representing the Differences entry. - * @return the Differences entry - */ - public PDFArray toPDFArray() { - return this.differences; + differences.add(new PDFName(name)); } } diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index 633ce9dd1..585f6d86d 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1469,42 +1469,11 @@ public class PDFFactory { /** * Creates a PDFEncoding instance from a CodePointMapping instance. * @param encoding the code point mapping (encoding) - * @param fontNameHint ... + * @param fontName ... * @return the PDF Encoding dictionary (or a String with the predefined encoding) */ - public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) { - SingleByteEncoding baseEncoding; - if (fontNameHint.indexOf("Symbol") >= 0) { - baseEncoding = CodePointMapping.getMapping( - CodePointMapping.SYMBOL_ENCODING); - } else { - baseEncoding = CodePointMapping.getMapping( - CodePointMapping.STANDARD_ENCODING); - } - PDFEncoding pdfEncoding = new PDFEncoding(baseEncoding.getName()); - PDFEncoding.DifferencesBuilder builder - = pdfEncoding.createDifferencesBuilder(); - int start = -1; - String[] baseNames = baseEncoding.getCharNameMap(); - String[] charNameMap = encoding.getCharNameMap(); - for (int i = 0, ci = charNameMap.length; i < ci; i++) { - String basec = baseNames[i]; - String c = charNameMap[i]; - if (!basec.equals(c)) { - if (start != i) { - builder.addDifference(i); - start = i; - } - builder.addName(c); - start++; - } - } - if (builder.hasDifferences()) { - pdfEncoding.setDifferences(builder.toPDFArray()); - return pdfEncoding; - } else { - return baseEncoding.getName(); - } + public Object createPDFEncoding(SingleByteEncoding encoding, String fontName) { + return PDFEncoding.createPDFEncoding(encoding, fontName); } /** diff --git a/src/java/org/apache/fop/pdf/PDFFont.java b/src/java/org/apache/fop/pdf/PDFFont.java index 191fd223e..9b9d1c129 100644 --- a/src/java/org/apache/fop/pdf/PDFFont.java +++ b/src/java/org/apache/fop/pdf/PDFFont.java @@ -70,7 +70,7 @@ public class PDFFont extends PDFDictionary { * @param encoding the encoding */ public void setEncoding(String encoding) { - if (encoding != null) { + if (encoding != null && !PDFEncoding.hasStandardEncoding(encoding)) { put("Encoding", new PDFName(encoding)); } } diff --git a/status.xml b/status.xml index bfb14e0de..5927dd82c 100644 --- a/status.xml +++ b/status.xml @@ -62,6 +62,9 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + Remove StandardEncoding as the encoding type from fonts used in the PDF renderer + Cached AFP charactersets have more unique keys preventing the two characters with but different binaries conflicting. diff --git a/test/java/org/apache/fop/pdf/PDFEncodingTestCase.java b/test/java/org/apache/fop/pdf/PDFEncodingTestCase.java new file mode 100644 index 000000000..34e48f1a6 --- /dev/null +++ b/test/java/org/apache/fop/pdf/PDFEncodingTestCase.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package org.apache.fop.pdf; + +import org.junit.Test; + +import org.apache.fop.fonts.CodePointMapping; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class PDFEncodingTestCase { + + /** + * Tests the createPDFEncoding method to ensure a null encoding type + * is handled correctly. + */ + @Test + public void testCreatePDFEncodingForNull() { + Object encoding = PDFEncoding.createPDFEncoding(null, "Test"); + assertEquals(encoding, null); + } + + /** + * Tests that when a PDFEncoding object is created, if the encoding type is + * that of StandardEncoding, the baseEncoding tag is omitted. + */ + @Test + public void testStandardEncodingDiffs() { + Object encoding = PDFEncoding.createPDFEncoding(CodePointMapping.getMapping( + CodePointMapping.SYMBOL_ENCODING), "Test"); + if (encoding instanceof PDFEncoding) { + PDFEncoding pdfEncoding = (PDFEncoding) encoding; + assertFalse(pdfEncoding.entries.containsKey("BaseEncoding")); + } + } + + /** + * Tests that when the StandardEncoding type is provided and there are no + * differences, the returned encoding object is null. + */ + @Test + public void testStandardEncodingNoDiff() { + Object encoding = PDFEncoding.createPDFEncoding(CodePointMapping.getMapping( + CodePointMapping.STANDARD_ENCODING), "Test"); + assertEquals(encoding, null); + } + + /** + * Tests that when the SymbolEncoding type is provided and there are no + * differences, the returned encoding string is that of SymbolEncoding. + */ + @Test + public void testCreatePDFEncodingSymbol() { + Object encoding = PDFEncoding.createPDFEncoding(CodePointMapping.getMapping( + CodePointMapping.SYMBOL_ENCODING), "Symbol"); + assert (encoding instanceof String); + String pdfEncoding = (String) encoding; + assertEquals(pdfEncoding, "SymbolEncoding"); + } +} -- 2.39.5