Skip to content

Commit 1acd5d5

Browse files
committed
FOP-3277: add font substitution support for PDFTranscoder
1 parent 8736bba commit 1acd5d5

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

fop-core/src/main/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,18 @@
2828
import org.apache.fop.apps.io.ResourceResolverFactory;
2929
import org.apache.fop.configuration.Configuration;
3030
import org.apache.fop.configuration.ConfigurationException;
31+
import org.apache.fop.fonts.CustomFontCollection;
3132
import org.apache.fop.fonts.DefaultFontConfig;
3233
import org.apache.fop.fonts.DefaultFontConfigurator;
3334
import org.apache.fop.fonts.EmbedFontInfo;
3435
import org.apache.fop.fonts.FontCacheManagerFactory;
36+
import org.apache.fop.fonts.FontCollection;
3537
import org.apache.fop.fonts.FontDetectorFactory;
3638
import org.apache.fop.fonts.FontInfo;
3739
import org.apache.fop.fonts.FontManager;
40+
import org.apache.fop.fonts.FontManagerConfigurator;
3841
import org.apache.fop.fonts.FontSetup;
42+
import org.apache.fop.fonts.base14.Base14FontCollection;
3943
import org.apache.fop.pdf.PDFDocument;
4044
import org.apache.fop.render.pdf.PDFRendererConfig;
4145
import org.apache.fop.render.pdf.PDFRendererConfig.PDFRendererConfigParser;
@@ -92,7 +96,11 @@ public static FontInfo createFontInfo(Configuration cfg, boolean useComplexScrip
9296
FontManager fontManager = new FontManager(resourceResolver, FontDetectorFactory.createDefault(),
9397
FontCacheManagerFactory.createDefault());
9498

95-
//TODO Make use of fontBaseURL, font substitution and referencing configuration
99+
FontManagerConfigurator fmConfigurator = new FontManagerConfigurator(cfg, thisUri,
100+
thisUri, null);
101+
fmConfigurator.configure(fontManager, strict);
102+
103+
//TODO Make use of fontBaseURL and referencing configuration
96104
//Requires a change to the expected configuration layout
97105

98106
DefaultFontConfig.DefaultFontConfigParser parser
@@ -102,7 +110,11 @@ public static FontInfo createFontInfo(Configuration cfg, boolean useComplexScrip
102110
= new DefaultFontConfigurator(fontManager, null, strict);
103111
List<EmbedFontInfo> fontInfoList = fontInfoConfigurator.configure(fontInfoConfig);
104112
fontManager.saveCache();
105-
FontSetup.setup(fontInfo, fontInfoList, resourceResolver, useComplexScriptFeatures);
113+
FontCollection[] fontCollections = new FontCollection[] {
114+
new Base14FontCollection(fontManager.isBase14KerningEnabled()),
115+
new CustomFontCollection(resourceResolver, fontInfoList, useComplexScriptFeatures)
116+
};
117+
fontManager.setup(fontInfo, fontCollections);
106118
} else {
107119
FontSetup.setup(fontInfo, useComplexScriptFeatures);
108120
}

fop-core/src/test/java/org/apache/fop/svg/BasicPDFTranscoderTestCase.java

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,42 @@
1919

2020
package org.apache.fop.svg;
2121

22-
import org.junit.Test;
22+
import java.io.ByteArrayInputStream;
23+
import java.io.File;
24+
import java.io.FileOutputStream;
25+
import java.io.IOException;
26+
import java.io.OutputStream;
27+
import java.util.HashMap;
28+
import java.util.Map;
2329

30+
import org.junit.Rule;
31+
import org.junit.Test;
32+
import org.junit.rules.TemporaryFolder;
2433
import static org.junit.Assert.assertEquals;
2534

35+
import org.apache.pdfbox.Loader;
36+
import org.apache.pdfbox.pdmodel.PDDocument;
37+
import org.apache.pdfbox.text.PDFTextStripper;
38+
import org.apache.pdfbox.text.TextPosition;
39+
2640
import org.apache.batik.transcoder.Transcoder;
41+
import org.apache.batik.transcoder.TranscoderException;
42+
import org.apache.batik.transcoder.TranscoderInput;
43+
import org.apache.batik.transcoder.TranscoderOutput;
2744

2845
import org.apache.fop.configuration.Configuration;
46+
import org.apache.fop.configuration.ConfigurationException;
47+
import org.apache.fop.configuration.DefaultConfigurationBuilder;
2948

3049
/**
3150
* Basic runtime test for the PDF transcoder. It is used to verify that
3251
* nothing obvious is broken after compiling.
3352
*/
3453
public class BasicPDFTranscoderTestCase extends AbstractBasicTranscoderTest {
3554

55+
@Rule
56+
public TemporaryFolder tempFolder = new TemporaryFolder();
57+
3658
@Override
3759
protected Transcoder createTranscoder() {
3860
return new PDFTranscoder();
@@ -52,4 +74,70 @@ public void testFontAutoDetect() {
5274
autoDetectConf.getClass().getSimpleName());
5375
}
5476

77+
@Test
78+
public void testFontSubstitution() throws ConfigurationException, IOException, TranscoderException {
79+
80+
PDFTranscoder transcoder = (PDFTranscoder) createTranscoder();
81+
82+
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
83+
String cfgFragment =
84+
"<pdf-renderer>"
85+
+ "<fonts>"
86+
+ "<substitutions>"
87+
+ "<substitution>"
88+
+ "<from font-family=\"Helvetica\"/>"
89+
+ "<to font-family=\"Courier\"/>"
90+
+ "</substitution>"
91+
+ "</substitutions>"
92+
+ "</fonts>"
93+
+ "</pdf-renderer>";
94+
Configuration cfg = cfgBuilder.build(new ByteArrayInputStream(cfgFragment.getBytes()));
95+
transcoder.configure(cfg);
96+
97+
String svgFragment = "<svg xml:space=\"preserve\" x=\"-1.70458in\" y=\"0.198315in\" "
98+
+ "width=\"2.6622in\" height=\"1.89672in\""
99+
+ " viewBox=\"-4330 0 6762 4818\" xmlns=\"http://www.w3.org/2000/svg\">"
100+
+ " <text x=\"-3653\" y=\"841\" style=\"fill:#1F1A17;font-size:639;font-family:Helvetica\">H</text>"
101+
+ "</svg>";
102+
TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(svgFragment.getBytes()));
103+
104+
File outputFile = tempFolder.newFile("output.pdf");
105+
OutputStream os = new FileOutputStream(outputFile);
106+
TranscoderOutput output = new TranscoderOutput(os);
107+
108+
try {
109+
transcoder.transcode(input, output);
110+
} finally {
111+
os.close();
112+
}
113+
114+
PDDocument pdfDocument = null;
115+
try {
116+
pdfDocument = Loader.loadPDF(outputFile);
117+
FontExtractor fontExtractor = new FontExtractor();
118+
fontExtractor.getText(pdfDocument);
119+
assertEquals("Courier", fontExtractor.getFontUsage().get("H"));
120+
} finally {
121+
if (pdfDocument != null) {
122+
pdfDocument.close();
123+
}
124+
}
125+
}
126+
127+
class FontExtractor extends PDFTextStripper {
128+
129+
private Map<String, String> fontUsage = new HashMap<>();
130+
131+
@Override
132+
protected void processTextPosition(TextPosition text) {
133+
String fontName = text.getFont().getName();
134+
fontUsage.put(text.toString(), fontName);
135+
super.processTextPosition(text);
136+
}
137+
138+
public Map<String, String> getFontUsage() {
139+
return fontUsage;
140+
}
141+
}
142+
55143
}

0 commit comments

Comments
 (0)