package com.tom_roush.pdfbox.pdmodel.font.encoding; import com.tom_roush.pdfbox.cos.COSArray; import com.tom_roush.pdfbox.cos.COSBase; import com.tom_roush.pdfbox.cos.COSDictionary; import com.tom_roush.pdfbox.cos.COSName; import com.tom_roush.pdfbox.cos.COSNumber; import java.util.HashMap; import java.util.Map; /** * This will perform the encoding from a dictionary. * * @author Ben Litchfield */ public class DictionaryEncoding extends Encoding { private final COSDictionary encoding; private final Encoding baseEncoding; private final Map<Integer, String> differences = new HashMap<Integer, String>(); /** * Creates a new DictionaryEncoding for embedding. */ public DictionaryEncoding(COSName baseEncoding, COSArray differences) { encoding = new COSDictionary(); encoding.setItem(COSName.NAME, COSName.ENCODING); encoding.setItem(COSName.DIFFERENCES, differences); if (baseEncoding != COSName.STANDARD_ENCODING) { encoding.setItem(COSName.BASE_ENCODING, baseEncoding); this.baseEncoding = Encoding.getInstance(baseEncoding); } else { this.baseEncoding = Encoding.getInstance(baseEncoding); } if (this.baseEncoding == null) { throw new IllegalArgumentException("Invalid encoding: " + baseEncoding); } codeToName.putAll(this.baseEncoding.codeToName); names.addAll(this.baseEncoding.names); applyDifferences(); } /** * Creates a new DictionaryEncoding for a Type 3 font from a PDF. * * @param fontEncoding The Type 3 encoding dictionary. */ public DictionaryEncoding(COSDictionary fontEncoding) { encoding = fontEncoding; baseEncoding = null; applyDifferences(); } /** * Creates a new DictionaryEncoding from a PDF. * * @param fontEncoding The encoding dictionary. * @param isNonSymbolic True if the font is non-symbolic. False for Type 3 fonts. * @param builtIn The font's built-in encoding. Null for Type 3 fonts. */ public DictionaryEncoding(COSDictionary fontEncoding, boolean isNonSymbolic, Encoding builtIn) { encoding = fontEncoding; Encoding base = null; if (encoding.containsKey(COSName.BASE_ENCODING)) { COSName name = encoding.getCOSName(COSName.BASE_ENCODING); base = Encoding.getInstance(name); // may be null } if (base == null) { if (isNonSymbolic) { // Otherwise, for a nonsymbolic font, it is StandardEncoding base = StandardEncoding.INSTANCE; } else { // and for a symbolic font, it is the font's built-in encoding. if (builtIn != null) { base = builtIn; } else { throw new IllegalArgumentException("Symbolic fonts must have a built-in " + "encoding"); } } } baseEncoding = base; codeToName.putAll(baseEncoding.codeToName); names.addAll(baseEncoding.names); applyDifferences(); } private void applyDifferences() { // now replace with the differences COSArray differences = (COSArray) encoding.getDictionaryObject(COSName.DIFFERENCES); int currentIndex = -1; for (int i = 0; differences != null && i < differences.size(); i++) { COSBase next = differences.getObject(i); if (next instanceof COSNumber) { currentIndex = ((COSNumber) next).intValue(); } else if (next instanceof COSName) { COSName name = (COSName) next; add(currentIndex, name.getName()); this.differences.put(currentIndex, name.getName()); currentIndex++; } } } /** * Returns the base encoding. Will be null for Type 3 fonts. */ public Encoding getBaseEncoding() { return baseEncoding; } /** * Returns the Differences array. */ public Map<Integer, String> getDifferences() { return differences; } /** * Convert this standard java object to a COS object. * * @return The cos object that matches this Java object. */ public COSBase getCOSObject() { return encoding; } }