blob: 64fd6f866e49eba8c2623250b712510a42bdc048 [file] [log] [blame]
/*
* 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;
// Java
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.
*
* A small object expressing the base encoding name and
* the differences from the base encoding.
*
* The three base encodings are given by their name.
*
* Encodings are specified in section 5.5.5 of the PDF 1.4 spec.
*/
public class PDFEncoding extends PDFDictionary {
/** the name for the standard encoding scheme */
public static final String STANDARD_ENCODING = "StandardEncoding";
/** the name for the Mac Roman encoding scheme */
public static final String MAC_ROMAN_ENCODING = "MacRomanEncoding";
/** the name for the Mac Export encoding scheme */
public static final String MAC_EXPERT_ENCODING = "MacExpertEncoding";
/** the name for the WinAnsi encoding scheme */
public static final String WIN_ANSI_ENCODING = "WinAnsiEncoding";
/** the name for the PDF document encoding scheme */
public static final String PDF_DOC_ENCODING = "PDFDocEncoding";
/** the set of predefined encodings that can be assumed present in a PDF viewer */
private static final Set PREDEFINED_ENCODINGS;
static {
Set encodings = new java.util.HashSet();
encodings.add(STANDARD_ENCODING);
encodings.add(MAC_ROMAN_ENCODING);
encodings.add(MAC_EXPERT_ENCODING);
encodings.add(WIN_ANSI_ENCODING);
encodings.add(PDF_DOC_ENCODING);
PREDEFINED_ENCODINGS = Collections.unmodifiableSet(encodings);
}
/**
* Create a new /Encoding object.
*
* @param basename the name of the character encoding schema
*/
public PDFEncoding(String basename) {
super();
put("Type", new PDFName("Encoding"));
if (basename != null) {
put("BaseEncoding", new PDFName(basename));
}
}
/**
* 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")
* @return true if it is a predefined encoding
*/
public static boolean isPredefinedEncoding(String name) {
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.
* @return the DifferencesBuilder
*/
public DifferencesBuilder createDifferencesBuilder() {
return new DifferencesBuilder();
}
/**
* Sets the Differences value.
* @param differences the differences.
*/
public void setDifferences(PDFArray differences) {
put("Differences", differences);
}
/**
* Builder class for constructing the Differences array.
*/
public class DifferencesBuilder {
private int currentCode = -1;
/**
* Creates an array containing the differences between two single-byte.
* font encodings.
* @param encodingA The first single-byte encoding
* @param encodingB 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
*/
private void addDifference(int code, PDFArray differences) {
this.currentCode = code;
differences.add(Integer.valueOf(code));
}
/**
* Adds a character name to the current difference.
* @param name the character name
* @return this builder instance
*/
private void addName(String name, PDFArray differences) {
if (this.currentCode < 0) {
throw new IllegalStateException("addDifference(int) must be called first");
}
differences.add(new PDFName(name));
}
}
/*
* example (p. 214)
* 25 0 obj
* <<
* /Type /Encoding
* /Differences [39 /quotesingle 96 /grave 128
* /Adieresis /Aring /Ccedilla /Eacute /Ntilde
* /Odieresis /Udieresis /aacute /agrave]
* >>
* endobj
*/
}