Return-Path: X-Original-To: apmail-pdfbox-commits-archive@www.apache.org Delivered-To: apmail-pdfbox-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A3567111DC for ; Mon, 5 May 2014 17:47:16 +0000 (UTC) Received: (qmail 58047 invoked by uid 500); 5 May 2014 17:47:16 -0000 Delivered-To: apmail-pdfbox-commits-archive@pdfbox.apache.org Received: (qmail 58002 invoked by uid 500); 5 May 2014 17:47:16 -0000 Mailing-List: contact commits-help@pdfbox.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@pdfbox.apache.org Delivered-To: mailing list commits@pdfbox.apache.org Received: (qmail 57852 invoked by uid 99); 5 May 2014 17:47:16 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 May 2014 17:47:16 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 May 2014 17:47:14 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id C863723888E2; Mon, 5 May 2014 17:46:50 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1592586 - in /pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font: PDType1CFont.java PDType1Font.java Date: Mon, 05 May 2014 17:46:50 -0000 To: commits@pdfbox.apache.org From: lehmi@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140505174650.C863723888E2@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: lehmi Date: Mon May 5 17:46:50 2014 New Revision: 1592586 URL: http://svn.apache.org/r1592586 Log: PDFBOX-2058: fall back to PDFont.encode if the type1c doesn't provide a suitable mapping, readded some font magic needed for rendering Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1592586&r1=1592585&r2=1592586&view=diff ============================================================================== --- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original) +++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Mon May 5 17:46:50 2014 @@ -23,12 +23,16 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -38,11 +42,17 @@ import org.apache.fontbox.cff.AFMFormatt import org.apache.fontbox.cff.CFFFont; import org.apache.fontbox.cff.CFFParser; import org.apache.fontbox.cff.Type1FontFormatter; +import org.apache.fontbox.cff.charset.CFFCharset; +import org.apache.fontbox.cff.encoding.CFFEncoding; import org.apache.fontbox.util.BoundingBox; import org.apache.pdfbox.cos.COSArray; +import org.apache.pdfbox.cos.COSBase; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSFloat; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSNumber; import org.apache.pdfbox.encoding.Encoding; +import org.apache.pdfbox.encoding.EncodingManager; import org.apache.pdfbox.exceptions.WrappedIOException; import org.apache.pdfbox.pdmodel.common.PDMatrix; import org.apache.pdfbox.pdmodel.common.PDRectangle; @@ -326,30 +336,102 @@ public class PDType1CFont extends PDSimp { if (baseFontName.equals(font.getName())) { - this.cffFont = font; + cffFont = font; break; } } } - if (this.cffFont == null) + if (cffFont == null) { - this.cffFont = (CFFFont)fonts.get(0); + cffFont = (CFFFont)fonts.get(0); } // cache the font name fontname = cffFont.getName(); - Number defaultWidthX = (Number) this.cffFont.getProperty("defaultWidthX"); + Number defaultWidthX = (Number) cffFont.getProperty("defaultWidthX"); this.glyphWidths.put(null, Float.valueOf(defaultWidthX.floatValue())); - Encoding encoding = getFontEncoding(); - Map nameToCode = encoding != null ? encoding.getNameToCodeMap() : null; + CFFEncoding encoding = cffFont.getEncoding(); + PDFEncoding pdfEncoding = new PDFEncoding(encoding); + + CFFCharset charset = cffFont.getCharset(); + PDFCharset pdfCharset = new PDFCharset(charset); + + Map charStringsDict = cffFont.getCharStringsDict(); + Map pdfCharStringsDict = new LinkedHashMap(); + pdfCharStringsDict.put(".notdef", charStringsDict.get(".notdef")); + + Map codeToNameMap = new LinkedHashMap(); + Collection mappings = cffFont.getMappings(); - Map codeToNameMap = new LinkedHashMap(); - for (CFFFont.Mapping mapping : mappings) + for( Iterator it = mappings.iterator(); it.hasNext();) + { + CFFFont.Mapping mapping = it.next(); + Integer code = Integer.valueOf(mapping.getCode()); + String name = mapping.getName(); + codeToNameMap.put(code, name); + } + + Set knownNames = new HashSet(codeToNameMap.values()); + + Map codeToNameOverride = loadOverride(); + for( Iterator> it = (codeToNameOverride.entrySet()).iterator(); it.hasNext();) { - codeToNameMap.put(mapping.getCode(), mapping.getName()); + Map.Entry entry = it.next(); + Integer code = (Integer)entry.getKey(); + String name = (String)entry.getValue(); + if(knownNames.contains(name)) + { + codeToNameMap.put(code, name); + } + } + + Map nameToCharacter; + try + { + // TODO remove access by reflection + Field nameToCharacterField = Encoding.class.getDeclaredField("NAME_TO_CHARACTER"); + nameToCharacterField.setAccessible(true); + nameToCharacter = (Map)nameToCharacterField.get(null); + } + catch( Exception e ) + { + throw new RuntimeException(e); + } + + for( Iterator> it = (codeToNameMap.entrySet()).iterator(); it.hasNext();) + { + Map.Entry entry = it.next(); + Integer code = (Integer)entry.getKey(); + String name = (String)entry.getValue(); + String uniName = "uni"; + String character = (String)nameToCharacter.get(name); + if( character != null ) + { + for( int j = 0; j < character.length(); j++ ) + { + uniName += hexString(character.charAt(j), 4); + } + } + else + { + uniName += hexString(code.intValue(), 4); + character = String.valueOf((char)code.intValue()); + } + pdfEncoding.register(code.intValue(), code.intValue()); + pdfCharset.register(code.intValue(), uniName); + pdfCharStringsDict.put(uniName, charStringsDict.get(name)); } + + cffFont.setEncoding(pdfEncoding); + cffFont.setCharset(pdfCharset); + charStringsDict.clear(); + charStringsDict.putAll(pdfCharStringsDict); + + + Encoding fontEncoding = getFontEncoding(); + Map nameToCode = fontEncoding != null ? fontEncoding.getNameToCodeMap() : null; for (CFFFont.Mapping mapping : mappings) { int sid = mapping.getSID(); @@ -358,21 +440,19 @@ public class PDType1CFont extends PDSimp if (nameToCode != null && nameToCode.containsKey(name)) { sid = nameToCode.get(name); - character = encoding.getCharacter(name); + character = fontEncoding.getCharacter(name); } if (character == null) { character = Encoding.getCharacterForName(name); } - if (character == null) - { - name = "uni" + hexString(sid, 4); - character = String.valueOf(Character.toChars(sid)); - } sidToName.put(sid, name); - sidToCharacter.put(sid, character); - characterToSID.put(character, sid); codeToSID.put(mapping.getCode(), sid); + if (character != null) + { + sidToCharacter.put(sid, character); + characterToSID.put(character, sid); + } } } @@ -454,6 +534,73 @@ public class PDType1CFont extends PDSimp } } + private Map loadOverride() throws IOException + { + Map result = new LinkedHashMap(); + COSBase encoding = getEncoding(); + if( encoding instanceof COSName ) + { + COSName name = (COSName)encoding; + result.putAll(loadEncoding(name)); + } + else if( encoding instanceof COSDictionary ) + { + COSDictionary encodingDic = (COSDictionary)encoding; + COSName baseName = (COSName)encodingDic.getDictionaryObject(COSName.BASE_ENCODING); + if( baseName != null ) + { + result.putAll(loadEncoding(baseName)); + } + COSArray differences = (COSArray)encodingDic.getDictionaryObject(COSName.DIFFERENCES); + if( differences != null ) + { + result.putAll(loadDifferences(differences)); + } + } + + return result; + } + + private Map loadEncoding(COSName name) throws IOException + { + Map result = new LinkedHashMap(); + Encoding encoding = EncodingManager.INSTANCE.getEncoding(name); + for( Iterator> it = (encoding.getCodeToNameMap().entrySet()).iterator(); + it.hasNext();) + { + Map.Entry entry = it.next(); + result.put(entry.getKey(), (entry.getValue())); + } + + return result; + } + + private Map loadDifferences(COSArray differences) + { + Map result = new LinkedHashMap(); + Integer code = null; + for( int i = 0; i < differences.size(); i++) + { + COSBase element = differences.get(i); + if( element instanceof COSNumber ) + { + COSNumber number = (COSNumber)element; + code = Integer.valueOf(number.intValue()); + } + else + { + if( element instanceof COSName ) + { + COSName name = (COSName)element; + result.put(code, name.getName()); + code = Integer.valueOf(code.intValue() + 1); + } + } + } + return result; + } + + private static Font prepareAwtFont( CFFFont font ) throws IOException { byte[] type1Bytes = Type1FontFormatter.format(font); @@ -473,4 +620,49 @@ public class PDType1CFont extends PDSimp } } + /** + * This class represents a PDFEncoding. + * + */ + private static class PDFEncoding extends CFFEncoding + { + + private PDFEncoding( CFFEncoding parent ) + { + Iterator parentEntries = parent.getEntries().iterator(); + while(parentEntries.hasNext()) + { + addEntry(parentEntries.next()); + } + } + + public boolean isFontSpecific() + { + return true; + } + + } + + /** + * This class represents a PDFCharset. + * + */ + private static class PDFCharset extends CFFCharset + { + private PDFCharset( CFFCharset parent ) + { + Iterator parentEntries = parent.getEntries().iterator(); + while(parentEntries.hasNext()) + { + addEntry(parentEntries.next()); + } + } + + public boolean isFontSpecific() + { + return true; + } + + } + } Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=1592586&r1=1592585&r2=1592586&view=diff ============================================================================== --- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original) +++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Mon May 5 17:46:50 2014 @@ -463,12 +463,13 @@ public class PDType1Font extends PDSimpl { if (type1CFont != null && getFontEncoding() == null) { - return type1CFont.encode(c, offset, length); - } - else - { - return super.encode(c, offset, length); + String character = type1CFont.encode(c, offset, length); + if (character != null) + { + return character; + } } + return super.encode(c, offset, length); } /**