Skip to content

Commit

Permalink
support unpatched OpenPDF versions
Browse files Browse the repository at this point in the history
fixes gh-350
  • Loading branch information
dadza committed May 5, 2023
1 parent 1822d9e commit 20fc69a
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
35 changes: 35 additions & 0 deletions jasperreports/docs/config.reference.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7636,4 +7636,39 @@ be used when original XML exporter output is required.
</configProperty>


<!-- net.sf.jasperreports.export.pdf.classic.document.language -->

<configProperty name="net.sf.jasperreports.export.pdf.classic.document.language">
<description>
The language of the document, used for glyph substitution when Apache FOP is present
and the <code>net.sf.jasperreports.export.pdf.classic.fop.glyph.substitution.enabled</code>
property is set.
<p>
See <a href="https://github.com/LibrePDF/OpenPDF/blob/0c9c4ca393b01444b7cb13bb1d12da202bd0d458/openpdf/src/main/java/com/lowagie/text/Document.java#L206">the OpenPDF code</a>.
</p>
</description>
</configProperty>


<!-- net.sf.jasperreports.export.pdf.classic.fop.glyph.substitution.enabled -->

<configProperty name="net.sf.jasperreports.export.pdf.classic.fop.glyph.substitution.enabled">
<description>
Flag that determines whether glyph substitution based on Apache FOP is enabled.
The flag is set <code>false</code> by default, disabling glyph substitution.
<p>
When Apache FOP is present on the classpath glyph substitution can only be disabled
by using a patched version of OpenPDF (1.3.30.jaspersoft.x from
<a href="https://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts/com/github/librepdf/openpdf/">https://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts/com/github/librepdf/openpdf/</a>)
is used.
The property needs to be explicitly set to <code>true</code> when using a standard/unpatched version of OpenPDF together with Apache FOP.
</p>
<p>
Also see the <a href="#net.sf.jasperreports.export.pdf.classic.document.language">net.sf.jasperreports.export.pdf.classic.document.language</a>
property which can be used to control Apache FOP glyph substitution.
</p>
</description>
</configProperty>


</configReference>
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lowagie.text.BadElementException;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
Expand All @@ -42,6 +47,7 @@
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.SplitCharacter;
import com.lowagie.text.pdf.FopGlyphProcessor;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfOutline;
Expand All @@ -50,9 +56,12 @@
import com.lowagie.text.pdf.RadioCheckField;
import com.lowagie.text.pdf.TextField;

import net.sf.jasperreports.annotations.properties.Property;
import net.sf.jasperreports.annotations.properties.PropertyScope;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPrintImage;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.PrintPageFormat;
import net.sf.jasperreports.engine.export.AbstractPdfTextRenderer;
Expand All @@ -77,6 +86,7 @@
import net.sf.jasperreports.export.pdf.PdfTextChunk;
import net.sf.jasperreports.export.pdf.PdfTextField;
import net.sf.jasperreports.export.pdf.PdfTextRendererContext;
import net.sf.jasperreports.properties.PropertyConstants;
import net.sf.jasperreports.renderers.Graphics2DRenderable;

/**
Expand All @@ -86,6 +96,39 @@
public class ClassicPdfProducer implements PdfProducer
{

private static final Log log = LogFactory.getLog(ClassicPdfProducer.class);

@Property(
category = PropertyConstants.CATEGORY_EXPORT,
defaultValue = PropertyConstants.BOOLEAN_FALSE,
scopes = {PropertyScope.CONTEXT, PropertyScope.REPORT},
sinceVersion = PropertyConstants.VERSION_6_20_5,
valueType = Boolean.class
)
public static final String PROPERTY_FOP_GLYPH_SUBSTITUTION_ENABLED = JRPropertiesUtil.PROPERTY_PREFIX + "export.pdf.classic.fop.glyph.substitution.enabled";

@Property(
category = PropertyConstants.CATEGORY_EXPORT,
scopes = {PropertyScope.CONTEXT, PropertyScope.REPORT},
sinceVersion = PropertyConstants.VERSION_6_20_5
)
public static final String PROPERTY_DOCUMENT_LANGUAGE = JRPropertiesUtil.PROPERTY_PREFIX + "export.pdf.classic.document.language";

private final static Method SET_GLYPH_SUBSTITUTION_ENABLED_METHOD;
static
{
Method setGlyphSubstitutionEnabledMethod = null;
try
{
setGlyphSubstitutionEnabledMethod = Document.class.getMethod("setGlyphSubstitutionEnabled", Boolean.TYPE);
}
catch (NoSuchMethodException | SecurityException e)
{
log.debug("Failed to detect com.lowagie.text.Document.setGlyphSubstitutionEnabled method: " + e);
}
SET_GLYPH_SUBSTITUTION_ENABLED_METHOD = setGlyphSubstitutionEnabledMethod;
}

private PdfProducerContext context;

private ClassicPdfStructure pdfStructure;
Expand Down Expand Up @@ -126,7 +169,7 @@ public PdfDocument createDocument(PrintPageFormat pageFormat)
pageFormat.getPageHeight()
)
);
pdfDocument.setGlyphSubstitutionEnabled(false);//FIXME config property?
setDocumentProperties(pdfDocument);

imageTesterDocument =
new Document(
Expand All @@ -140,6 +183,34 @@ public PdfDocument createDocument(PrintPageFormat pageFormat)
return document;
}

protected void setDocumentProperties(Document pdfDocument)
{
String documentLanguage = context.getProperties().getProperty(context.getCurrentJasperPrint(), PROPERTY_DOCUMENT_LANGUAGE);
if (documentLanguage != null)
{
pdfDocument.setDocumentLanguage(documentLanguage);
}

boolean glyphSubstitutionEnabled = context.getProperties().getBooleanProperty(context.getCurrentJasperPrint(),
PROPERTY_FOP_GLYPH_SUBSTITUTION_ENABLED, false);
if (!glyphSubstitutionEnabled && FopGlyphProcessor.isFopSupported())
{
if (SET_GLYPH_SUBSTITUTION_ENABLED_METHOD == null)
{
throw new JRRuntimeException("FOP glyph substution is disabled but patched library not detected");
}

try
{
SET_GLYPH_SUBSTITUTION_ENABLED_METHOD.invoke(pdfDocument, false);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new JRRuntimeException("Failed to invoke com.lowagie.text.Document.setGlyphSubstitutionEnabled", e);
}
}
}

@Override
public PdfDocumentWriter createWriter(OutputStream os) throws JRException
{
Expand Down

0 comments on commit 20fc69a

Please sign in to comment.