How to use TrueType Fonts in AFP with Apache FOP? - apache-fop

I'm trying to use a TrueType font in AFP with Apache FOP 2.2.
I believe I configured things correctly, but I'm getting the following exception:
java.lang.ClassCastException: org.apache.fop.afp.modca.MapDataResource cannot be cast to org.apache.fop.afp.modca.MapCodedFont
at org.apache.fop.afp.modca.ActiveEnvironmentGroup.getCurrentMapCodedFont(ActiveEnvironmentGroup.java:286)
at org.apache.fop.afp.modca.ActiveEnvironmentGroup.createFont(ActiveEnvironmentGroup.java:201)
at org.apache.fop.afp.modca.AbstractPageObject.createFont(AbstractPageObject.java:149)
at org.apache.fop.afp.DataStream.createFont(DataStream.java:331)
at org.apache.fop.afp.DataStream.addFontsToCurrentPage(DataStream.java:313)
at org.apache.fop.render.afp.AFPDocumentHandler.endPage(AFPDocumentHandler.java:310)
at org.apache.fop.render.intermediate.util.IFDocumentHandlerProxy.endPage(IFDocumentHandlerProxy.java:167)
at org.apache.fop.render.intermediate.EventProducingFilter.endPage(EventProducingFilter.java:48)
at org.apache.fop.render.intermediate.IFRenderer.renderPage(IFRenderer.java:603)
at org.apache.fop.area.RenderPagesModel.renderPage(RenderPagesModel.java:193)
at org.apache.fop.area.RenderPagesModel.checkPreparedPages(RenderPagesModel.java:174)
at org.apache.fop.area.RenderPagesModel.addPage(RenderPagesModel.java:146)
at org.apache.fop.layoutmgr.AbstractPageSequenceLayoutManager.finishPage(AbstractPageSequenceLayoutManager.java:316)
at org.apache.fop.layoutmgr.PageSequenceLayoutManager.finishPage(PageSequenceLayoutManager.java:226)
at org.apache.fop.layoutmgr.PageSequenceLayoutManager.activateLayout(PageSequenceLayoutManager.java:145)
at org.apache.fop.area.AreaTreeHandler.endPageSequence(AreaTreeHandler.java:267)
at org.apache.fop.fo.pagination.PageSequence.endOfNode(PageSequence.java:130)
at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:360)
at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:190)
Below is a snippet of my conf.xml configuration:
<renderer mime="application/x-afp">
<fonts>
<font name="Script MT Bold" kerning="yes" embed-url="/fonts/SCRIPTBL.TTF">
<font-triplet name="Script MT Bold" style="normal" weight="normal"/>
</font>
</fonts>
</renderer>
Do I require additional configurations?
Additionally, must I embed the TrueType font in AFP or can I simply include a reference and rely on the mainframe printer to resolve it?

I also faced the same exception. It seems like while creating the fonts for rendering the current page FOP populates a list of AbstractStructuredObject.
While loading the True Type font FOP creates a MapDataResource for it and populates the same in the list of AbstractStructuredObject.
However if the page has some other font such as a raster font then before loading this raster font it gets the most recent AbstractStructuredObject from the list and typecasts it to MapCodedFont. Since, the recent most object was of of type MapDataResource we get ClassCastException.
As a workaround I am currently using only True Type fonts in my AFP document and have added the default font-triplet to one of the font configuration.
<font name="Script MT Bold" kerning="yes" embed-url="/fonts/SCRIPTBL.TTF">
<font-triplet name="Script MT Bold" style="normal" weight="normal"/>
<font-triplet name="any" style="normal" weight="normal"/>
</font>

Related

Putting SVG in PDF with FOP works on Local Machine but not on Server

On the local machine everything works fine, when I try to run it on the server I get this error, it generates fine, but without the SVG logo included.
2019-07-12 09:09:01,956 [ERROR] [main] [LoggingEventListener] Image not available. URI: (instream-object). Reason: org.apache.xmlgraphics.image.loader.ImageException: The file format is not supported. No ImagePreloader found for null (No context info available)
org.apache.xmlgraphics.image.loader.ImageException: The file format is not supported. No ImagePreloader found for null
at org.apache.xmlgraphics.image.loader.ImageManager.preloadImage(ImageManager.java:181)
at org.apache.fop.render.intermediate.AbstractIFPainter.drawImageUsingDocument(AbstractIFPainter.java:317)
at org.apache.fop.render.pdf.PDFPainter.drawImage(PDFPainter.java:286)
Here is how it is included
<fo:block margin-right="1.5cm" text-align="right">
<fo:instream-foreign-object>
#include("Logo.vm")
</fo:instream-foreign-object>
</fo:block>
Here is the SVG Include File snippet Logo.vm:
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 175 40"
enable-background="new 0 0 115 40"
xml:space="preserve"
inkscape:version="0.48.4 r9939"
width="146"
height="38"
sodipodi:docname="DL_115x40.svg"><metadata
id="metadata3067"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/d/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs3065" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="492"
inkscape:window-height="309"
id="namedview3063"
showgrid="false"
inkscape:zoom="2.7826087"
inkscape:cx="57.5"
inkscape:cy="20"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1" />
<path class="st0" d="M122.9 34.2c0 .8-.6 1.3-1 .... *MORE AND MORE NUMBERS COMMING*
For me, this problem occurred when using Amazon Corretto JDK. Java Corretto has some bug that causes issues with fonts, see issues on the Github: Broken Font support (Fontconfig) in AWS-Lambda (java11) and Generic Linux distro requires Fontconfig for font support (java8)
What actually solved this issue for us was installing package fontconfig on the OS (we are running Ubuntu virtual servers, so no problem with that):
sudo apt-get install fontconfig
After that SVG renderring was OK.

Apache FOP | custom fonts | relative URL not working

I have got configuration file to load custom fonts for Apache FOP. I am struggling to configure embed-url on server so that font url changes as per server domain.
I have tried embed-url property value as:
Non working embed-urls:
embed-url="context:/etc/designs/projectName/clientlibs/pdffonts/Batang.ttf"
embed-url="file:/etc/designs/projectName/clientlibs/pdffonts/Batang.ttf"
Working embed-url:
embed-url="http://localhost:4503/etc/designs/projectName/clientlibs/pdffonts/Batang.ttf"
Somehow I can't seems to find proper syntax here. I am using FOP with AEM 6.0.
<?xml version="1.0"?>
<fop version="1.0">
<renderers>
<renderer mime="application/pdf">
<fonts>
<font kerning="yes"
embed-url="context:/etc/designs/projectName/clientlibs/pdffonts/Batang.ttf" -- this doesn't
embedding-mode="subset">
<font-triplet name="SimSun" style="normal" weight="normal" />
</font>
<font kerning="yes"
embed-url="file:/etc/designs/projectName/clientlibs/pdffonts/Batang.ttf" -- this doesn't
embedding-mode="subset">
<font-triplet name="Batang" style="normal" weight="normal" />
</font>
<font kerning="yes"
embed-url="http://localhost:4503/etc/designs/projectName/clientlibs/pdffonts/Batang.ttf" -- this works
embedding-mode="subset">
<font-triplet name="Batang" style="normal" weight="normal" />
</font>
</fonts>
</renderer>
</renderers>
</fop>
"Starting point" for relative paths:
if the configuration file has a font-base element (as a direct child of the document root element), its value is used to resolve relative font paths
otherwise, the value of the base element is used instead
the default configuration file included in the distribution has the element <base>.</base>, meaning that relative paths must be interpreted as relative to the position of the configuration file
Note that the values of font-base and base can be relative too, in which case they refer to the configuration file path.
<?xml version="1.0"?>
<fop version="1.0">
<base>.</base>
<font-base>/Users/lfurini/Library/Fonts</font-base>
<!-- other possible examples:
<font-base>.</font-base>
<font-base>../fonts</font-base>
-->
<!-- ... -->
</fop>
Relative paths syntax:
you don't need context: or file:
if the embed-url starts with / it's an absolute path, otherwise it's a relative one referring to the "starting point" defined before
relative paths can contain ../ to go back up in the folder hierarchy, if needed
<!-- directly in the base folder -->
<font kerning="yes" embed-url="font1.ttf">
<font-triplet name="font1" style="normal" weight="normal"/>
</font>
<!-- in a "sister" folder -->
<font kerning="yes" embed-url="../otherFonts/font2.ttf">
<font-triplet name="font2" style="normal" weight="normal"/>
</font>
<!-- in a sub-folder -->
<font kerning="yes" embed-url="specialFonts/font3.ttf">
<font-triplet name="font3" style="normal" weight="normal"/>
</font>
<!-- absolute path -->
<font kerning="yes" embed-url="/Users/lfurini/Library/Fonts/font4.ttf" embedding-mode="subset">
<font-triplet name="font4" style="normal" weight="normal"/>
</font>
(tested with FOP 1.1, 2.0 and 2.1)
(disclosure: I'm a FOP developer, though not very active nowadays)
I solved it by adding full path upto application from code. and added later patr from config file.
fopFactory.setBaseURL(this.getServletContext().getInitParameter("my_path"));
In config
embed-url="fonts/newfont.ttf"
For FOP-2.1 there is a patch for "Allow relative paths to font files/directories" at https://issues.apache.org/jira/browse/FOP-2627.

Not finding font Arial.ttf with apache fop 1.0

I use:
Apache fop 1.0
Java
I need to handle with special characters which unicode is higher than u0100. The target font I should use is Arial. As I cannot expect Arial is present on the target platform (eg. Linux), I embedded an Arial.ttf in my jar.
My actual config-file looks like this:
<fop ...>
<!-- Base URL for resolving relative URLs -->
<base>./</base>
<!-- Font Base URL for resolving relative font URLs -->
<font-base>./</font-base>
<renderers>
<renderer mime="application/pdf">
<fonts>
<font kerning="yes" embed-url="arial.ttf" encoding-mode="auto">
<font-triplet name="Arial" style="normal" weight="normal"/>
<font-triplet name="ArialMT" style="normal" weight="normal"/>
</font>
<!--<directory>C:/Windows/Fonts</directory>-->
</fonts>
<auto-detect/>
</renderer>
...
</fop>
Doing it this way I get an error loading my config-file to fop:
org.apache.fop.apps.FOPException: Failed to resolve font with embed-url 'arial.ttf'
The only way I managed to get it work until now was to hardcode the folder path into the config file:
<font kerning="yes" embed-url="C:/myapp/arial.ttf" encoding-mode="auto">
<font-triplet name="Arial" style="normal" weight="normal"/>
<font-triplet name="ArialMT" style="normal" weight="normal"/>
</font>
But obviously this cannot be the solution!
Using the "directory" tag whould work on Windows, just because you have Arial there. But as mentioned above it must also run on Linux, Macs, etc.
The "auto-detect" tag didn't work either (even not on Windows) - and isn't a solution as I cannot expect the target platform having Arial installed.
Any suggestions to solve this?
I finally found the answer. See:
https://web.archive.org/web/20120831233158/http://www.publicstaticfinal.de/2011/01/26/fop-embedding-fonts-from-classpath
The solution is to add an own URIResolver to the fopFactory.
This solution doesn't work for me. It is because ClassLoader.getSystemResourceAsStream(href); returns null.
I have found another solution but it has a different problem - if you have some other resources which you add to the FOP with the absolute system path (e.g. images selected by user), than your custom URIResolver is used either for them so they are resolved incorrectly.
If you want to correct these examples just mix them and you are getting working solution like this:
import java.io.InputStream;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
public class ClasspathUriResolver implements URIResolver {
#Override
public Source resolve(String href, String base) throws TransformerException {
Source source = null;
InputStream inputStream = getClass().getResourceAsStream(href);
if (inputStream != null) {
source = new StreamSource(inputStream);
}
return source;
}
}
Usage
[...]
FopFactory fopFactory = FopFactory.newInstance();
FOURIResolver uriResolver = (FOURIResolver) fopFactory.getURIResolver();
uriResolver.setCustomURIResolver(new ClasspathUriResolver());
[...]
You have <auto-detect/> outside the <fonts> tag. To solve our font problem we put <auto-detect/> inside the <fonts> tag.
We don't use additional <font> configurations, but just use the system fonts detected with <auto-detect/>
Not sure if it's your problem but I found out that since some version relative paths don't work for in the Fop config file. For me, it worked if I either supplied an absolute path (starting with '/') or prefixed the path with 'file:' like 'file:.'.

Image expression URL in Jasper Reports

I would like to embed an image into my JasperReports jrxml file. I have this directory structure.
Tomcat Root
webapps
reports
-->images
--> company_logo.jpg
-->reports
-->sample.jasper
-->WEB-INF
-->classes
And I tried doing this thinking that this is relative to my reports context root
<image>
<reportElement x="0" y="0" width="104" height="40"/>
<imageExpression class="java.lang.String">
<![CDATA["images/company_logo.jpg"]]>
</imageExpression>
</image>
..and this also
<image>
<reportElement x="0" y="0" width="104" height="40"/>
<imageExpression class="java.lang.String">
<![CDATA["/images/company_logo.jpg"]]>
</imageExpression>
</image>
but it always says there was an error loading bytes from location JRLoader.
I tried doing this and it works, but I am a bit confused why my first two attempt doesn't.
Is this really how you embed images in JasperReports? Do you need to supply the whole path? I am thinking that there should be a page relative
something.
<image>
<reportElement x="0" y="0" width="104" height="40"/>
<imageExpression class="java.lang.String">
<![CDATA["http://localhost:8080/reports/images/company_logo.jpg"]]>
</imageExpression>
</image>
I am a bit puzzled about the correct way.
<![CDATA["../images/company_logo.jpg"]]> should do the trick. The path is relative to your .jasper file.
You need to create a PARAMETER of type String called for example CONTEXT, and from your JSP send the servlet context:
parameters.put("CONTEXT",this.getServletContext().getRealPath("/"));
Now, in your report you use the parameter:
$P{CONTEXT}.toString()+"reports/images/logo.png"
The same apply for sub reports or other web resources, example:
$P{CONTEXT}.toString()+"reports/OrdenCompraAlmacen_Items.jasper"
I hope it is useful.
With .jrxml when use an absolute path with image, when the packaged jar filr will be deployed you will get:
java.lang.IllegalArgumentException: name
at sun.misc.URLClassPath$Loader.findResource(Unknown Source) ~[na:1.8.0_121]
at sun.misc.URLClassPath.findResource(Unknown Source) ~[na:1.8.0_121]
at java.net.URLClassLoader$2.run(Unknown Source) ~[na:1.8.0_121]
at java.net.URLClassLoader$2.run(Unknown Source) ~[na:1.8.0_121]
Try to load resource as:
<imageExpression><![CDATA[this.getClass().getResourceAsStream("/img/mdg_logo.jpg")]]></imageExpression>
sometimes is better use File.separtor: "ima" + File.separator + "logo.jpg"
Use the below expression in the image Expression of jasper report IDE on image properties of the jrxml and the relative image path
Accordingly change w.r.t path
getClass().getResource("META-INF/resources/webjars/Bank/themes/default/images/Logo.png").openStream()
This way the path is relative to your current working directory of your project. "." means current working directory.
Put your picture in the following structure:
webapps
reports
-->reports
-->sample.jasper
-->WEB-INF
-->classes
-->images
--> company_logo.jpg
<imageExpression class="java.lang.String">
<![CDATA["company_logo.jpg"]]>
</imageExpression>

WiX wxs script with option to install on Selecting current-user or all-users install

I need a complete WiX script that can be build.It had
Welcome
EULA
Install Folder
Selecting current-user or all-users install
Install
Finish
I just need a single wxs file because it is for a simple application. Also I need an option to install it for the current user or all users.
have you checked the WixUI_Advanced UI that comes built-in in Wix3?
Here are the dialogs that it has:
AdvancedWelcomeEulaDlg
BrowseDlg
DiskCostDlg
FeaturesDlg
InstallDirDlg
InstallScopeDlg (for selecting user or per machine)
InvalidDirDlg
I've also used the WixUI_InstallDir, but copied it and tweaked it according to my needs by adding some "What to do next" text at the end of the installer. I used this detailed walkthrough to take the stock Wix GUI and change a couple of the screen for my own purposes. This does require that you grab the Wix source code, but just for the purpose of getting the uncompiled versions of the actual Product.wxs file that the Wix developers include to drive the WixUI_InstallDir installer.
So basically I have something like this in a solution (using Votive add-in for VS):
MyWeb project
Wix Project
MyWeb.wxs - my product stuff obviously
Product.wxs - the Wix file that comes from the Wix source that defines the structure, flow, and content of the WixUI_InstallDir
My_InstallDir.wxs - This is where the fun happens. Essentially copied the source code Wix file, changed it to satisfy my needs, then made sure that in the Product.wxs I have a reference to my screen, not the original one.
Product.wxs
<UI>
<UIRef Id="My_InstallDir"/>
</UI>
<!-- Add the customized EULA -->
<WixVariable Id="WixUILicenseRtf" Value="$(var.SolutionDir)\doc\license.rtf" />
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
<UIRef Id="My_InstallDir" />
<!-- Add the customized banner logo -->
<WixVariable Id="WixUIBannerBmp" Value="$(var.SolutionDir)\doc\InstallerBanner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="$(var.SolutionDir)\doc\InstallerSidebar.bmp" />
My_InstallDir.wxs is totally unchanged, apart from the line referring to my exit dialog, which is where my "What to do next" notes are:
<Publish Dialog="MyExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
So then the real change is in the My_ExitDialog where I'm displaying the text:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="MyExitDialog" Width="370" Height="270" Title="!(loc.ExitDialog_Title) test">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.ExitDialogBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<!--<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogDescription)" />-->
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogTitle)" />
<Control Id="NextSteps" Type="ScrollableText" X="135" Y="70" Width="220" Height="140" Sunken="yes" TabSkip="no">
<Text SourceFile="$(var.SolutionDir)\doc\GemWebAfterInstall.rtf" />
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="MyExitDialog" OnExit="success" />
</InstallUISequence>
<AdminUISequence>
<Show Dialog="MyExitDialog" OnExit="success" />
</AdminUISequence>
</UI>
</Fragment>
I know you're looking for a solution, not pointers necessarily. However, using the article I reference as the key starting point, I think you can find all of the parts you need either in the ready-baked WixUI bits, or by replacing small pieces of the "out-of-the-box" stuff like I have. Good luck.