git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1175754 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_1rc1old
*/ | */ | ||||
boolean isEmbeddable(); | boolean isEmbeddable(); | ||||
/** | |||||
* Indicates whether this font is subset embedded. | |||||
* @return true if this font is subset embedded | |||||
*/ | |||||
boolean isSubsetEmbedded(); | |||||
} | } |
import javax.xml.transform.Source; | import javax.xml.transform.Source; | ||||
import javax.xml.transform.stream.StreamSource; | import javax.xml.transform.stream.StreamSource; | ||||
import org.xml.sax.InputSource; | |||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.fop.apps.FOPException; | 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. | * This class is used to defer the loading of a font until it is really used. | ||||
return realFontDescriptor.isEmbeddable(); | return realFontDescriptor.isEmbeddable(); | ||||
} | } | ||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public boolean isSubsetEmbedded() { | |||||
load(true); | |||||
return realFont.isMultiByte(); | |||||
} | |||||
} | } | ||||
package org.apache.fop.fonts; | package org.apache.fop.fonts; | ||||
//Java | //Java | ||||
import java.text.DecimalFormat; | |||||
import java.util.Map; | import java.util.Map; | ||||
*/ | */ | ||||
public class MultiByteFont extends CIDFont { | public class MultiByteFont extends CIDFont { | ||||
private static int uniqueCounter = -1; | |||||
private String ttcName = null; | private String ttcName = null; | ||||
private String encoding = "Identity-H"; | private String encoding = "Identity-H"; | ||||
private int defaultWidth = 0; | private int defaultWidth = 0; | ||||
private CIDFontType cidType = CIDFontType.CIDTYPE2; | private CIDFontType cidType = CIDFontType.CIDTYPE2; | ||||
private String namePrefix = null; // Quasi unique prefix | |||||
private CIDSubset subset = new CIDSubset(); | private CIDSubset subset = new CIDSubset(); | ||||
/** A map from Unicode indices to glyph indices */ | /** A map from Unicode indices to glyph indices */ | ||||
*/ | */ | ||||
public MultiByteFont() { | public MultiByteFont() { | ||||
subset.setupFirstGlyph(); | 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); | setFontType(FontType.TYPE0); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
public int getDefaultWidth() { | |||||
/** {@inheritdoc} */ | |||||
public int getdefaultwidth() { | |||||
return defaultWidth; | return defaultWidth; | ||||
} | } | ||||
this.cidType = cidType; | this.cidType = cidType; | ||||
} | } | ||||
private String getPrefixedFontName() { | |||||
return namePrefix + FontUtil.stripWhiteSpace(super.getFontName()); | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public String getEmbedFontName() { | public String getEmbedFontName() { | ||||
if (isEmbeddable()) { | if (isEmbeddable()) { | ||||
return getPrefixedFontName(); | |||||
return FontUtil.stripWhiteSpace(super.getFontName()); | |||||
} else { | } else { | ||||
return super.getFontName(); | return super.getFontName(); | ||||
} | } | ||||
return !(getEmbedFileName() == null && getEmbedResourceName() == null); | return !(getEmbedFileName() == null && getEmbedResourceName() == null); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
public boolean isSubsetEmbedded() { | |||||
return true; | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public CIDSubset getCIDSubset() { | public CIDSubset getCIDSubset() { | ||||
return this.subset; | return this.subset; |
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
public boolean isSubsetEmbedded() { | |||||
return false; | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public String getEncodingName() { | public String getEncodingName() { | ||||
return this.mapping.getName(); | return this.mapping.getName(); | ||||
} | } |
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.net.MalformedURLException; | import java.net.MalformedURLException; | ||||
import java.text.DecimalFormat; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.BitSet; | import java.util.BitSet; | ||||
import org.apache.fop.fonts.truetype.TTFSubSetFile; | import org.apache.fop.fonts.truetype.TTFSubSetFile; | ||||
import org.apache.fop.fonts.type1.PFBData; | import org.apache.fop.fonts.type1.PFBData; | ||||
import org.apache.fop.fonts.type1.PFBParser; | import org.apache.fop.fonts.type1.PFBParser; | ||||
import org.apache.xmlgraphics.xmp.Metadata; | |||||
/** | /** | ||||
* This class provides method to create and register PDF objects. | * This class provides method to create and register PDF objects. | ||||
private Log log = LogFactory.getLog(PDFFactory.class); | private Log log = LogFactory.getLog(PDFFactory.class); | ||||
private int subsetFontCounter = -1; | |||||
/** | /** | ||||
* Creates a new PDFFactory. | * Creates a new PDFFactory. | ||||
* @param document the parent PDFDocument needed to register the generated | * @param document the parent PDFDocument needed to register the generated | ||||
} else { | } else { | ||||
FontType fonttype = metrics.getFontType(); | 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; | PDFFont font = null; | ||||
font = PDFFont.createFont(fontname, fonttype, basefont, null); | |||||
font = PDFFont.createFont(fontname, fonttype, subsetFontName, null); | |||||
getDocument().registerObject(font); | getDocument().registerObject(font); | ||||
if (fonttype == FontType.TYPE0) { | if (fonttype == FontType.TYPE0) { | ||||
= new PDFCIDSystemInfo(cidMetrics.getRegistry(), | = new PDFCIDSystemInfo(cidMetrics.getRegistry(), | ||||
cidMetrics.getOrdering(), | cidMetrics.getOrdering(), | ||||
cidMetrics.getSupplement()); | cidMetrics.getSupplement()); | ||||
PDFCIDFont cidFont | |||||
= new PDFCIDFont(basefont, | |||||
PDFCIDFont cidFont = new PDFCIDFont(subsetFontName, | |||||
cidMetrics.getCIDType(), | cidMetrics.getCIDType(), | ||||
cidMetrics.getDefaultWidth(), | cidMetrics.getDefaultWidth(), | ||||
getSubsetWidths(cidMetrics), sysInfo, | getSubsetWidths(cidMetrics), sysInfo, | ||||
return warray; | 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 | * make a /FontDescriptor object | ||||
* | * | ||||
* @param desc the font descriptor | * @param desc the font descriptor | ||||
* @param fontPrefix the String with which to prefix the font name | |||||
* @return the new PDF font descriptor | * @return the new PDF font descriptor | ||||
*/ | */ | ||||
public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc) { | |||||
private PDFFontDescriptor makeFontDescriptor(FontDescriptor desc, String fontPrefix) { | |||||
PDFFontDescriptor descriptor = null; | PDFFontDescriptor descriptor = null; | ||||
if (desc.getFontType() == FontType.TYPE0) { | if (desc.getFontType() == FontType.TYPE0) { | ||||
// CID Font | // CID Font | ||||
descriptor = new PDFCIDFontDescriptor(desc.getEmbedFontName(), | |||||
descriptor = new PDFCIDFontDescriptor(fontPrefix + desc.getEmbedFontName(), | |||||
desc.getFontBBox(), | desc.getFontBBox(), | ||||
desc.getCapHeight(), | desc.getCapHeight(), | ||||
desc.getFlags(), | desc.getFlags(), |
documents. Example: the fix of marks layering will be such a case when it's done. | documents. Example: the fix of marks layering will be such a case when it's done. | ||||
--> | --> | ||||
<release version="FOP Trunk" date="TBD"> | <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"> | <action context="Fonts" dev="PH" type="fix" fixes-bug="51530" due-to="Mehdi Houshmand"> | ||||
Improved support for EBCDIC encoded double byte fonts fo AFP. | Improved support for EBCDIC encoded double byte fonts fo AFP. | ||||
</action> | </action> |
import org.apache.fop.events.BasicEventTestCase; | import org.apache.fop.events.BasicEventTestCase; | ||||
import org.apache.fop.pdf.FileIDGeneratorTestCase; | import org.apache.fop.pdf.FileIDGeneratorTestCase; | ||||
import org.apache.fop.pdf.PDFEncryptionJCETestCase; | import org.apache.fop.pdf.PDFEncryptionJCETestCase; | ||||
import org.apache.fop.pdf.PDFFactoryTestCase; | |||||
import org.apache.fop.pdf.PDFObjectTestCase; | import org.apache.fop.pdf.PDFObjectTestCase; | ||||
import org.apache.fop.traits.BorderPropsTestCase; | import org.apache.fop.traits.BorderPropsTestCase; | ||||
import org.apache.fop.util.BitmapImageUtilTestCase; | import org.apache.fop.util.BitmapImageUtilTestCase; | ||||
suite.addTest(new TestSuite(PDFNumberTestCase.class)); | suite.addTest(new TestSuite(PDFNumberTestCase.class)); | ||||
suite.addTest(new TestSuite(PDFObjectTestCase.class)); | suite.addTest(new TestSuite(PDFObjectTestCase.class)); | ||||
suite.addTest(FileIDGeneratorTestCase.suite()); | suite.addTest(FileIDGeneratorTestCase.suite()); | ||||
suite.addTest(new TestSuite(PDFFactoryTestCase.class)); | |||||
suite.addTest(new TestSuite(ColorUtilTestCase.class)); | suite.addTest(new TestSuite(ColorUtilTestCase.class)); | ||||
suite.addTest(new TestSuite(BorderPropsTestCase.class)); | suite.addTest(new TestSuite(BorderPropsTestCase.class)); | ||||
suite.addTest(new TestSuite(ElementListUtilsTestCase.class)); | suite.addTest(new TestSuite(ElementListUtilsTestCase.class)); |
/* | |||||
* 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()); | |||||
} | |||||
} |