/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2006 - 2017 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.engine.classic.bugs; import com.lowagie.text.pdf.PdfDictionary; import com.lowagie.text.pdf.PdfLiteral; import com.lowagie.text.pdf.PdfName; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.parser.Matrix; import com.lowagie.text.pdf.parser.PdfContentReaderTool; import com.lowagie.text.pdf.parser.PdfContentStreamProcessor; import org.junit.Before; import org.junit.Test; import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot; import org.pentaho.reporting.engine.classic.core.MasterReport; import org.pentaho.reporting.engine.classic.core.ReportProcessingException; import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.PdfReportUtil; import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys; import org.pentaho.reporting.libraries.resourceloader.ResourceException; import org.pentaho.reporting.libraries.resourceloader.ResourceManager; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URL; import java.util.ArrayList; import java.util.Objects; import java.util.Stack; /** * @author Thomas Morgner */ public class Prd5873Test { @Before public void setUp() throws Exception { ClassicEngineBoot.getInstance().start(); } @Test public void validateWithUnderline() throws ResourceException, ReportProcessingException, IOException { final URL resource = getClass().getResource("Prd-5873.prpt"); final MasterReport report = (MasterReport) new ResourceManager().createDirectly(resource, MasterReport.class).getResource(); report.getPageFooter().getElement(0).getStyle().setBooleanStyleProperty(TextStyleKeys.UNDERLINED, false); runTest(report); } @Test public void validateCorrectness() throws ResourceException, ReportProcessingException, IOException { final URL resource = getClass().getResource("Prd-5873.prpt"); final MasterReport report = (MasterReport) new ResourceManager().createDirectly(resource, MasterReport.class).getResource(); runTest(report); } private void runTest(MasterReport report) throws ResourceException, ReportProcessingException, IOException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); PdfReportUtil.createPDF(report, bout); PdfReader reader = new PdfReader(bout.toByteArray()); printPdfPage(reader); final PdfDictionary pageN = reader.getPageN(1); final PdfDictionary asDict = pageN.getAsDict(PdfName.RESOURCES); final byte[] pageContent = reader.getPageContent(1); PdfValidator pv = new PdfValidator(); pv.processContent(pageContent, asDict); } private void printPdfPage(PdfReader reader) throws IOException { final StringWriter out = new StringWriter(); PdfContentReaderTool.listContentStreamForPage(reader, 1, new PrintWriter(out)); System.out.println(out); } class PdfValidator extends PdfContentStreamProcessor { Stack graphicsState; boolean textModeActive; PdfValidator() { graphicsState = new Stack(); } @Override public void processContent(byte[] bytes, PdfDictionary pdfDictionary) { graphicsState.clear(); super.processContent(bytes, pdfDictionary); if (!graphicsState.isEmpty()) { throw new RuntimeException(); } } @Override public void displayText(String s, Matrix matrix) { } @Override public void invokeOperator(PdfLiteral pdfLiteral, ArrayList arrayList) { super.invokeOperator(pdfLiteral, arrayList); String op = pdfLiteral.toString(); if (Objects.equals(op, "q")) { if (textModeActive) { throw new RuntimeException("Cannot mix text mode and graphics operations."); } graphicsState.push(Boolean.TRUE); } else if (Objects.equals(op, "Q")) { if (textModeActive) { throw new RuntimeException("Cannot mix text mode and graphics operations."); } graphicsState.pop(); } else if (Objects.equals(op, "BT")) { textModeActive = true; } else if (Objects.equals(op, "ET")) { textModeActive = false; } } } }