| /* |
| * 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. |
| */ |
| |
| package org.apache.fop.render.pdf; |
| |
| import java.awt.Rectangle; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.Rectangle2D; |
| import java.io.BufferedOutputStream; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.net.URI; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.fontbox.cff.CFFParser; |
| import org.apache.fontbox.ttf.TTFParser; |
| import org.apache.fontbox.type1.Type1Font; |
| import org.apache.pdfbox.cos.COSArray; |
| import org.apache.pdfbox.cos.COSDictionary; |
| import org.apache.pdfbox.cos.COSInteger; |
| import org.apache.pdfbox.cos.COSName; |
| import org.apache.pdfbox.cos.COSObject; |
| import org.apache.pdfbox.pdmodel.PDDocument; |
| import org.apache.pdfbox.pdmodel.PDPage; |
| import org.apache.pdfbox.pdmodel.font.PDCIDFontType2; |
| import org.apache.pdfbox.pdmodel.font.PDType0Font; |
| |
| import org.apache.xmlgraphics.image.loader.ImageException; |
| import org.apache.xmlgraphics.image.loader.ImageInfo; |
| import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; |
| import org.apache.xmlgraphics.image.loader.util.SoftMapCache; |
| import org.apache.xmlgraphics.java2d.GeneralGraphics2DImagePainter; |
| import org.apache.xmlgraphics.java2d.GraphicContext; |
| import org.apache.xmlgraphics.ps.PSGenerator; |
| |
| import org.apache.fop.apps.FOUserAgent; |
| import org.apache.fop.fonts.CustomFont; |
| import org.apache.fop.fonts.FontInfo; |
| import org.apache.fop.fonts.FontType; |
| import org.apache.fop.fonts.MultiByteFont; |
| import org.apache.fop.fonts.Typeface; |
| import org.apache.fop.pdf.PDFAnnotList; |
| import org.apache.fop.pdf.PDFArray; |
| import org.apache.fop.pdf.PDFDictionary; |
| import org.apache.fop.pdf.PDFDocument; |
| import org.apache.fop.pdf.PDFFilterList; |
| import org.apache.fop.pdf.PDFFormXObject; |
| import org.apache.fop.pdf.PDFGState; |
| import org.apache.fop.pdf.PDFPage; |
| import org.apache.fop.pdf.PDFResources; |
| import org.apache.fop.pdf.PDFStream; |
| import org.apache.fop.render.pcl.PCLGenerator; |
| import org.apache.fop.render.pcl.PCLGraphics2D; |
| import org.apache.fop.render.pdf.pdfbox.ImageConverterPDF2G2D; |
| import org.apache.fop.render.pdf.pdfbox.ImagePDF; |
| import org.apache.fop.render.pdf.pdfbox.MergeTTFonts; |
| import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter; |
| import org.apache.fop.render.pdf.pdfbox.PDFBoxImageHandler; |
| import org.apache.fop.render.pdf.pdfbox.PSPDFGraphics2D; |
| import org.apache.fop.render.ps.PSDocumentHandler; |
| import org.apache.fop.render.ps.PSImageFormResource; |
| import org.apache.fop.render.ps.PSRenderingUtil; |
| |
| public class PDFBoxAdapterTestCase { |
| protected static final String CFF1 = "test/resources/2fonts.pdf"; |
| protected static final String CFF2 = "test/resources/2fonts2.pdf"; |
| protected static final String CFF3 = "test/resources/simpleh.pdf"; |
| protected static final String TTCID1 = "test/resources/ttcid1.pdf"; |
| protected static final String TTCID2 = "test/resources/ttcid2.pdf"; |
| protected static final String TTSubset1 = "test/resources/ttsubset.pdf"; |
| protected static final String TTSubset2 = "test/resources/ttsubset2.pdf"; |
| private static final String TTSubset3 = "test/resources/ttsubset3.pdf"; |
| private static final String TTSubset5 = "test/resources/ttsubset5.pdf"; |
| protected static final String CFFCID1 = "test/resources/cffcid1.pdf"; |
| private static final String CFFCID2 = "test/resources/cffcid2.pdf"; |
| protected static final String Type1Subset1 = "test/resources/t1subset.pdf"; |
| protected static final String Type1Subset2 = "test/resources/t1subset2.pdf"; |
| private static final String Type1Subset3 = "test/resources/t1subset3.pdf"; |
| private static final String Type1Subset4 = "test/resources/t1subset4.pdf"; |
| protected static final String ROTATE = "test/resources/rotate.pdf"; |
| private static final String ANNOT = "test/resources/annot.pdf"; |
| private static final String SHADING = "test/resources/shading.pdf"; |
| private static final String LINK = "test/resources/link.pdf"; |
| private static final String IMAGE = "test/resources/image.pdf"; |
| private static final String HELLOTagged = "test/resources/taggedWorld.pdf"; |
| private static final String XFORM = "test/resources/xform.pdf"; |
| private static final String LOOP = "test/resources/loop.pdf"; |
| private static final String ERROR = "test/resources/error.pdf"; |
| private static final String LIBREOFFICE = "test/resources/libreoffice.pdf"; |
| private static final String SMASK = "test/resources/smask.pdf"; |
| private static final String TYPE0TT = "test/resources/type0tt.pdf"; |
| private static final String TYPE0CFF = "test/resources/type0cff.pdf"; |
| |
| private static PDFPage getPDFPage(PDFDocument doc) { |
| final Rectangle2D r = new Rectangle2D.Double(); |
| return new PDFPage(new PDFResources(doc), 0, r, r, r, r); |
| } |
| |
| protected static PDFBoxAdapter getPDFBoxAdapter(boolean mergeFonts, boolean formXObject) { |
| PDFDocument doc = new PDFDocument(""); |
| PDFPage pdfpage = getPDFPage(doc); |
| doc.setMergeFontsEnabled(mergeFonts); |
| doc.setFormXObjectEnabled(formXObject); |
| pdfpage.setDocument(doc); |
| pdfpage.setObjectNumber(1); |
| return new PDFBoxAdapter(pdfpage, new HashMap(), new HashMap<Integer, PDFArray>()); |
| } |
| |
| @Test |
| public void testPDFWriter() throws Exception { |
| FontInfo fi = new FontInfo(); |
| String msg = writeText(fi, CFF3); |
| Assert.assertTrue(msg, msg.contains("/Myriad_Pro")); |
| Assert.assertEquals(fi.getUsedFonts().size(), 2); |
| msg = writeText(fi, TTSubset1); |
| Assert.assertTrue(msg, msg.contains("<74>-0.168 <65>-0.1523 <73>0.1528 <74>277.832")); |
| msg = writeText(fi, TTSubset2); |
| Assert.assertTrue(msg, msg.contains("(t)-0.168 (e)-0.1523 (s)0.1528 (t)")); |
| msg = writeText(fi, TTSubset3); |
| Assert.assertTrue(msg, msg.contains("[<0001>3 <0002>-7 <0003>] TJ")); |
| msg = writeText(fi, TTSubset5); |
| Assert.assertTrue(msg, msg.contains("[<0003>2 <0004>-7 <0007>] TJ")); |
| msg = writeText(fi, TTCID1); |
| Assert.assertTrue(msg, msg.contains("<0028003B0034003000420034>")); |
| msg = writeText(fi, TTCID2); |
| Assert.assertTrue(msg, msg.contains("<000F00100001002A0034003F00430034003C00310034004100010010000E000F0011>")); |
| msg = writeText(fi, CFFCID1); |
| Assert.assertTrue(msg, msg.contains("/Fm01700251251 Do")); |
| msg = writeText(fi, CFFCID2); |
| Assert.assertTrue(msg, msg.contains("/Fm01701174772 Do")); |
| msg = writeText(fi, Type1Subset1); |
| Assert.assertTrue(msg, msg.contains("/Verdana_Type1")); |
| msg = writeText(fi, Type1Subset2); |
| Assert.assertTrue(msg, msg.contains("[(2nd example)] TJ")); |
| msg = writeText(fi, Type1Subset3); |
| Assert.assertTrue(msg, msg.contains("/URWChanceryL-MediItal_Type1 20 Tf")); |
| msg = writeText(fi, Type1Subset4); |
| Assert.assertTrue(msg, msg.contains("/F15-1521012718 40 Tf")); |
| parseFonts(fi); |
| } |
| |
| @Test |
| public void testMergeTTCFF() throws IOException { |
| FontInfo fi = new FontInfo(); |
| writeText(fi, TYPE0TT); |
| writeText(fi, TYPE0CFF); |
| parseFonts(fi); |
| } |
| |
| @Test |
| public void testMergeTT() throws IOException { |
| PDDocument doc = PDDocument.load(new File(TYPE0TT)); |
| PDType0Font type0Font = (PDType0Font) doc.getPage(0).getResources().getFont(COSName.getPDFName("C2_0")); |
| PDCIDFontType2 ttf = (PDCIDFontType2) type0Font.getDescendantFont(); |
| InputStream originalData = ttf.getTrueTypeFont().getOriginalData(); |
| byte[] originalDataBytes = IOUtils.toByteArray(originalData); |
| doc.close(); |
| |
| MergeTTFonts mergeTTFonts = new MergeTTFonts(null); |
| Map<Integer, Integer> map = new HashMap<Integer, Integer>(); |
| map.put(0, 0); |
| mergeTTFonts.readFont(new ByteArrayInputStream(originalDataBytes), null, null, map, true); |
| byte[] mergedData = mergeTTFonts.getMergedFontSubset(); |
| Assert.assertArrayEquals(mergedData, originalDataBytes); |
| } |
| |
| private void parseFonts(FontInfo fi) throws IOException { |
| for (Typeface font : fi.getUsedFonts().values()) { |
| InputStream is = ((CustomFont) font).getInputStream(); |
| if (font.getFontType() == FontType.TYPE1C || font.getFontType() == FontType.CIDTYPE0) { |
| byte[] data = IOUtils.toByteArray(is); |
| CFFParser p = new CFFParser(); |
| p.parse(data); |
| } else if (font.getFontType() == FontType.TRUETYPE) { |
| TTFParser parser = new TTFParser(); |
| parser.parse(is); |
| } else if (font.getFontType() == FontType.TYPE0) { |
| TTFParser parser = new TTFParser(true); |
| parser.parse(is); |
| } else if (font.getFontType() == FontType.TYPE1) { |
| Type1Font.createWithPFB(is); |
| } |
| Assert.assertTrue(((CustomFont) font).isEmbeddable()); |
| if (font instanceof MultiByteFont) { |
| Assert.assertTrue(((MultiByteFont) font).getWidthsMap() != null); |
| } else { |
| Assert.assertFalse(((CustomFont)font).isSymbolicFont()); |
| } |
| } |
| } |
| |
| private String writeText(FontInfo fi, String pdf) throws IOException { |
| PDDocument doc = PDDocument.load(new File(pdf)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| String c = (String) getPDFBoxAdapter(true, false) |
| .createStreamFromPDFBoxPage(doc, page, pdf, at, fi, new Rectangle()); |
| doc.close(); |
| return c; |
| } |
| |
| @Test |
| public void testTaggedPDFWriter() throws IOException { |
| PDFBoxAdapter adapter = getPDFBoxAdapter(false, false); |
| adapter.setCurrentMCID(5); |
| PDDocument doc = PDDocument.load(new File(HELLOTagged)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| Rectangle r = new Rectangle(0, 1650, 842000, 595000); |
| String stream = (String) adapter.createStreamFromPDFBoxPage(doc, page, "key", at, null, r); |
| Assert.assertTrue(stream, stream.contains("/P <</MCID 5 >>BDC")); |
| doc.close(); |
| } |
| |
| @Test |
| public void testAnnot() throws Exception { |
| PDFDocument pdfdoc = new PDFDocument(""); |
| PDFPage pdfpage = getPDFPage(pdfdoc); |
| pdfpage.setDocument(pdfdoc); |
| pdfpage.setObjectNumber(1); |
| PDFBoxAdapter adapter = new PDFBoxAdapter(pdfpage, new HashMap(), new HashMap<Integer, PDFArray>()); |
| PDDocument doc = PDDocument.load(new File(ANNOT)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| Rectangle r = new Rectangle(0, 1650, 842000, 595000); |
| ByteArrayOutputStream os = new ByteArrayOutputStream(); |
| pdfdoc.output(os); |
| os.reset(); |
| adapter.createStreamFromPDFBoxPage(doc, page, "key", at, null, r); |
| pdfdoc.outputTrailer(os); |
| Assert.assertTrue(os.toString("UTF-8").contains("/Fields [")); |
| doc.close(); |
| } |
| |
| @Test |
| public void testAnnot2() throws Exception { |
| PDFBoxAdapter adapter = getPDFBoxAdapter(false, false); |
| PDDocument doc = PDDocument.load(new File(ANNOT)); |
| PDPage page = doc.getPage(0); |
| COSArray annots = (COSArray) page.getCOSObject().getDictionaryObject(COSName.ANNOTS); |
| COSDictionary dict = (COSDictionary) ((COSObject)annots.get(0)).getObject(); |
| dict.setItem(COSName.PARENT, COSInteger.ONE); |
| |
| AffineTransform at = new AffineTransform(); |
| Rectangle r = new Rectangle(0, 1650, 842000, 595000); |
| adapter.createStreamFromPDFBoxPage(doc, page, "key", at, null, r); |
| doc.close(); |
| } |
| |
| @Test |
| public void testLink() throws Exception { |
| PDFDocument pdfdoc = new PDFDocument(""); |
| PDFPage pdfpage = getPDFPage(pdfdoc); |
| pdfpage.setDocument(pdfdoc); |
| pdfpage.setObjectNumber(1); |
| Map<Integer, PDFArray> pageNumbers = new HashMap<Integer, PDFArray>(); |
| PDFBoxAdapter adapter = new PDFBoxAdapter(pdfpage, new HashMap(), pageNumbers); |
| PDDocument doc = PDDocument.load(new File(LINK)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| Rectangle r = new Rectangle(0, 1650, 842000, 595000); |
| String stream = (String) adapter.createStreamFromPDFBoxPage(doc, page, "key", at, null, r); |
| Assert.assertTrue(stream.contains("/Link <</MCID 5 >>BDC")); |
| Assert.assertEquals(pageNumbers.size(), 4); |
| PDFAnnotList annots = (PDFAnnotList) pdfpage.get("Annots"); |
| Assert.assertEquals(annots.toPDFString(), "[\n1 0 R\n2 0 R\n]"); |
| doc.close(); |
| } |
| |
| @Test |
| public void testXform() throws Exception { |
| PDFDocument pdfdoc = new PDFDocument(""); |
| pdfdoc.getFilterMap().put(PDFFilterList.DEFAULT_FILTER, Collections.singletonList("null")); |
| pdfdoc.setMergeFontsEnabled(true); |
| PDFPage pdfpage = getPDFPage(pdfdoc); |
| pdfpage.setDocument(pdfdoc); |
| pdfpage.setObjectNumber(1); |
| Map<Integer, PDFArray> pageNumbers = new HashMap<Integer, PDFArray>(); |
| PDFBoxAdapter adapter = new PDFBoxAdapter(pdfpage, new HashMap(), pageNumbers); |
| PDDocument doc = PDDocument.load(new File(XFORM)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| Rectangle r = new Rectangle(0, 1650, 842000, 595000); |
| adapter.createStreamFromPDFBoxPage(doc, page, "key", at, new FontInfo(), r); |
| doc.close(); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| pdfdoc.output(bos); |
| Assert.assertFalse(bos.toString("UTF-8").contains("/W 5 /H 5 /BPC 8 /CS /RGB ID ÿÿÿ")); |
| } |
| |
| @Test |
| public void testPSPDFGraphics2D() throws Exception { |
| ByteArrayOutputStream stream = pdfToPS(IMAGE); |
| Assert.assertEquals(countString(stream.toString("UTF-8"), "%AXGBeginBitmap:"), 1); |
| |
| pdfToPS(CFF1); |
| pdfToPS(CFF2); |
| pdfToPS(CFF3); |
| pdfToPS(TTCID1); |
| pdfToPS(TTCID2); |
| pdfToPS(TTSubset1); |
| pdfToPS(TTSubset2); |
| pdfToPS(TTSubset3); |
| pdfToPS(TTSubset5); |
| stream = pdfToPS(CFFCID1); |
| Assert.assertEquals(countString(stream.toString("UTF-8"), "%AXGBeginBitmap:"), 2); |
| pdfToPS(CFFCID2); |
| pdfToPS(Type1Subset1); |
| pdfToPS(Type1Subset2); |
| pdfToPS(Type1Subset3); |
| pdfToPS(Type1Subset4); |
| pdfToPS(ROTATE); |
| pdfToPS(LINK); |
| pdfToPS(LOOP); |
| stream = pdfToPS(LIBREOFFICE); |
| Assert.assertTrue(stream.toString("UTF-8").contains("/MaskColor [ 255 255 255 ]")); |
| |
| } |
| |
| private int countString(String s, String value) { |
| return s.split(value).length - 1; |
| } |
| |
| @Test |
| public void testPDFToPDF() throws IOException { |
| FontInfo fi = new FontInfo(); |
| writeText(fi, CFF1); |
| writeText(fi, CFF2); |
| writeText(fi, CFF3); |
| writeText(fi, CFFCID1); |
| writeText(fi, CFFCID2); |
| writeText(fi, IMAGE); |
| writeText(fi, LINK); |
| writeText(fi, ROTATE); |
| writeText(fi, SHADING); |
| writeText(fi, TTCID1); |
| writeText(fi, TTCID2); |
| writeText(fi, TTSubset1); |
| writeText(fi, TTSubset2); |
| writeText(fi, TTSubset3); |
| writeText(fi, TTSubset5); |
| writeText(fi, Type1Subset1); |
| writeText(fi, Type1Subset2); |
| writeText(fi, Type1Subset3); |
| writeText(fi, Type1Subset4); |
| writeText(fi, LOOP); |
| } |
| |
| private ByteArrayOutputStream pdfToPS(String pdf) throws IOException, ImageException { |
| ImageConverterPDF2G2D i = new ImageConverterPDF2G2D(); |
| ImageInfo imgi = new ImageInfo(pdf, "b"); |
| PDDocument doc = PDDocument.load(new File(pdf)); |
| org.apache.xmlgraphics.image.loader.Image img = new ImagePDF(imgi, doc); |
| ImageGraphics2D ig = (ImageGraphics2D)i.convert(img, null); |
| GeneralGraphics2DImagePainter g = (GeneralGraphics2DImagePainter) ig.getGraphics2DImagePainter(); |
| ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
| PSPDFGraphics2D g2d = (PSPDFGraphics2D) g.getGraphics(true, new FOPPSGeneratorImpl(stream)); |
| Rectangle2D rect = new Rectangle2D.Float(0, 0, 100, 100); |
| GraphicContext gc = new GraphicContext(); |
| g2d.setGraphicContext(gc); |
| ig.getGraphics2DImagePainter().paint(g2d, rect); |
| doc.close(); |
| return stream; |
| } |
| |
| @Test |
| public void testSmask() throws IOException, ImageException { |
| ByteArrayOutputStream ps = pdfToPS(SMASK); |
| Assert.assertTrue(ps.toString("UTF-8").contains("/Pattern")); |
| Assert.assertTrue(ps.toString("UTF-8").contains("{<\nf1f1f1")); |
| } |
| |
| @Test |
| public void testPCL() throws IOException, ImageException { |
| String ex = ""; |
| try { |
| pdfToPCL(SHADING); |
| } catch (UnsupportedOperationException e) { |
| ex = e.getMessage(); |
| } |
| Assert.assertTrue(ex.contains("Clipping is not supported.")); |
| } |
| |
| private void pdfToPCL(String pdf) throws IOException, ImageException { |
| ImageConverterPDF2G2D i = new ImageConverterPDF2G2D(); |
| ImageInfo imgi = new ImageInfo(pdf, "b"); |
| PDDocument doc = PDDocument.load(new File(pdf)); |
| org.apache.xmlgraphics.image.loader.Image img = new ImagePDF(imgi, doc); |
| ImageGraphics2D ig = (ImageGraphics2D)i.convert(img, null); |
| ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
| PCLGraphics2D g2d = new PCLGraphics2D(new PCLGenerator(stream)); |
| Rectangle2D rect = new Rectangle2D.Float(0, 0, 100, 100); |
| GraphicContext gc = new GraphicContext(); |
| g2d.setGraphicContext(gc); |
| ig.getGraphics2DImagePainter().paint(g2d, rect); |
| doc.close(); |
| } |
| |
| static class FOPPSGeneratorImpl extends PSGenerator implements PSDocumentHandler.FOPPSGenerator { |
| public FOPPSGeneratorImpl(OutputStream out) { |
| super(out); |
| } |
| |
| public PSDocumentHandler getHandler() { |
| PSDocumentHandler handler = mock(PSDocumentHandler.class); |
| PSRenderingUtil util = mock(PSRenderingUtil.class); |
| when(util.isOptimizeResources()).thenReturn(false); |
| when(handler.getPSUtil()).thenReturn(util); |
| FOUserAgent mockedAgent = mock(FOUserAgent.class); |
| when(handler.getUserAgent()).thenReturn(mockedAgent); |
| when(mockedAgent.getTargetResolution()).thenReturn(72f); |
| when(handler.getFormForImage(any(String.class))).thenReturn(new PSImageFormResource(0, "")); |
| return handler; |
| } |
| |
| public BufferedOutputStream getTempStream(URI uri) throws IOException { |
| return new BufferedOutputStream(new ByteArrayOutputStream()); |
| } |
| |
| public Map<Integer, URI> getImages() { |
| return new HashMap<Integer, URI>(); |
| } |
| } |
| |
| @Test |
| public void testPDFBoxImageHandler() throws Exception { |
| ImageInfo imgi = new ImageInfo("a", "b"); |
| PDDocument doc = PDDocument.load(new File(SHADING)); |
| ImagePDF img = new ImagePDF(imgi, doc); |
| PDFDocument pdfdoc = new PDFDocument(""); |
| PDFPage pdfpage = getPDFPage(pdfdoc); |
| pdfpage.setDocument(pdfdoc); |
| PDFGState g = new PDFGState(); |
| pdfdoc.assignObjectNumber(g); |
| pdfpage.addGState(g); |
| PDFContentGenerator con = new PDFContentGenerator(pdfdoc, null, null); |
| FOUserAgent mockedAgent = mock(FOUserAgent.class); |
| when(mockedAgent.isAccessibilityEnabled()).thenReturn(false); |
| when(mockedAgent.getPDFObjectCache()).thenReturn(new SoftMapCache(true)); |
| PDFRenderingContext c = new PDFRenderingContext(mockedAgent, con, pdfpage, null); |
| c.setPageNumbers(new HashMap<Integer, PDFArray>()); |
| new PDFBoxImageHandler().handleImage(c, img, new Rectangle()); |
| PDFResources res = c.getPage().getPDFResources(); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| res.output(bos); |
| Assert.assertTrue(bos.toString("UTF-8").contains("/ExtGState << /GS1")); |
| } |
| |
| @Test |
| public void testPDFCache() throws IOException { |
| LoadPDFWithCache loadPDFWithCache = new LoadPDFWithCache(); |
| loadPDFWithCache.run(LOOP); |
| |
| Object item = loadPDFWithCache.pdfCache.values().iterator().next(); |
| Assert.assertEquals(item.getClass(), PDFStream.class); |
| item = loadPDFWithCache.pdfCache.keySet().iterator().next(); |
| Assert.assertEquals(item.getClass(), Integer.class); |
| Assert.assertEquals(loadPDFWithCache.pdfCache.size(), 12); |
| |
| Iterator<Object> iterator = loadPDFWithCache.objectCachePerFile.values().iterator(); |
| iterator.next(); |
| item = iterator.next(); |
| Assert.assertEquals(item.getClass(), PDFDictionary.class); |
| item = loadPDFWithCache.objectCachePerFile.keySet().iterator().next(); |
| Assert.assertEquals(item.getClass(), String.class); |
| Assert.assertEquals(loadPDFWithCache.objectCachePerFile.size(), 46); |
| } |
| |
| @Test |
| public void testPDFCache2() throws IOException { |
| LoadPDFWithCache loadPDFWithCache = new LoadPDFWithCache(); |
| String stream = loadPDFWithCache.run(LOOP); |
| String cachedStream = (String) loadPDFWithCache.objectCachePerFile.get(LOOP); |
| Assert.assertTrue(cachedStream.contains("EMC")); |
| Assert.assertTrue(stream.endsWith(cachedStream)); |
| } |
| |
| private static class LoadPDFWithCache { |
| private PDFDocument pdfdoc = new PDFDocument(""); |
| private Map<Object, Object> pdfCache = new LinkedHashMap<Object, Object>(); |
| private Map<Object, Object> objectCachePerFile = new LinkedHashMap<Object, Object>(); |
| private String run(String pdf) throws IOException { |
| PDFPage pdfpage = getPDFPage(pdfdoc); |
| pdfdoc.assignObjectNumber(pdfpage); |
| pdfpage.setDocument(pdfdoc); |
| PDFBoxAdapter adapter = new PDFBoxAdapter( |
| pdfpage, objectCachePerFile, new HashMap<Integer, PDFArray>(), pdfCache); |
| PDDocument doc = PDDocument.load(new File(pdf)); |
| PDPage page = doc.getPage(0); |
| String stream = (String) adapter.createStreamFromPDFBoxPage( |
| doc, page, pdf, new AffineTransform(), null, new Rectangle()); |
| doc.close(); |
| return stream; |
| } |
| } |
| |
| @Test |
| public void testPDFSize() throws IOException { |
| LoadPDFWithCache loadPDFWithCache = new LoadPDFWithCache(); |
| loadPDFWithCache.run(ANNOT); |
| loadPDFWithCache.run(ANNOT); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| loadPDFWithCache.pdfdoc.output(bos); |
| Assert.assertEquals(loadPDFWithCache.pdfCache.size(), 2); |
| Assert.assertTrue(bos.size() <= 6418); |
| } |
| |
| @Test |
| public void testErrorMsgToPS() throws IOException, ImageException { |
| String msg = ""; |
| try { |
| pdfToPS(ERROR); |
| } catch (RuntimeException e) { |
| msg = e.getMessage(); |
| } |
| Assert.assertTrue(msg.startsWith("Error while painting PDF page: " + ERROR)); |
| } |
| |
| @Test |
| public void testErrorMsgToPDF() throws IOException { |
| String msg = ""; |
| PDFRenderingContext context = new PDFRenderingContext(null, null, null, null); |
| ImagePDF imagePDF = new ImagePDF(new ImageInfo(ERROR, null), null); |
| try { |
| new PDFBoxImageHandler().handleImage(context, imagePDF, null); |
| } catch (RuntimeException e) { |
| msg = e.getMessage(); |
| } |
| Assert.assertTrue(msg.startsWith("Error on PDF page: " + ERROR)); |
| } |
| |
| @Test |
| public void testNoPageResource() throws IOException { |
| PDDocument doc = PDDocument.load(new File(CFF1)); |
| PDPage page = doc.getPage(0); |
| page.setResources(null); |
| AffineTransform at = new AffineTransform(); |
| getPDFBoxAdapter(false, false).createStreamFromPDFBoxPage(doc, page, CFF1, at, new FontInfo(), new Rectangle()); |
| doc.close(); |
| } |
| |
| @Test |
| public void testPDFBoxImageHandlerAccessibilityEnabled() throws Exception { |
| ImageInfo imgi = new ImageInfo("a", "b"); |
| PDDocument doc = PDDocument.load(new File(SHADING)); |
| ImagePDF img = new ImagePDF(imgi, doc); |
| PDFDocument pdfdoc = new PDFDocument(""); |
| PDFPage pdfpage = getPDFPage(pdfdoc); |
| pdfpage.setDocument(pdfdoc); |
| PDFContentGenerator con = new PDFContentGenerator(pdfdoc, null, null); |
| FOUserAgent mockedAgent = mock(FOUserAgent.class); |
| when(mockedAgent.isAccessibilityEnabled()).thenReturn(true); |
| when(mockedAgent.getPDFObjectCache()).thenReturn(new SoftMapCache(true)); |
| PDFRenderingContext c = new PDFRenderingContext(mockedAgent, con, pdfpage, null); |
| c.setPageNumbers(new HashMap<Integer, PDFArray>()); |
| new PDFBoxImageHandler().handleImage(c, img, new Rectangle()); |
| } |
| |
| @Test |
| public void testMergeFontsAndFormXObject() throws IOException { |
| String msg = ""; |
| PDDocument doc = PDDocument.load(new File(IMAGE)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| try { |
| getPDFBoxAdapter(true, true) |
| .createStreamFromPDFBoxPage(doc, page, IMAGE, at, new FontInfo(), new Rectangle()); |
| } catch (RuntimeException e) { |
| msg = e.getMessage(); |
| } |
| doc.close(); |
| Assert.assertEquals(msg, "merge-fonts and form-xobject can't both be enabled"); |
| } |
| |
| @Test |
| public void testFormXObject() throws IOException { |
| PDDocument doc = PDDocument.load(new File(IMAGE)); |
| PDPage page = doc.getPage(0); |
| AffineTransform at = new AffineTransform(); |
| PDFFormXObject formXObject = (PDFFormXObject) getPDFBoxAdapter(false, true) |
| .createStreamFromPDFBoxPage(doc, page, IMAGE, at, new FontInfo(), new Rectangle()); |
| doc.close(); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| formXObject.output(bos); |
| Assert.assertTrue(bos.toString("UTF-8").contains("/Type /XObject")); |
| } |
| } |