Today I expanded the test site so that it covers tests of Unicode characters and ft:query searches with match-tagging. These work fine. Then I started working on the FOP configuration, to make fonts available to FOP through a portable configuration in the sitemap, following my own instructions here. However, various things have changed. First of all, to generate the font-metrics files, you need slightly different jar file names. Change to the cocoon/build/webapp/WEB-INF/lib directory, and then issue something like this:
java -cp fop.jar:xercesImpl-2.9.1.jar:xml-apis-1.3.04.jar org.apache.fop.fonts.apps.TTFReader /home/mholmes/cocoon_with_exist/testsite/fop-fonts/GentiumPlus-R.ttf /home/mholmes/cocoon_with_exist/testsite/fop-fonts/GentiumPlus-R.ttf.xml
where the first is the path to the TTF, and the second the path to the metric file you're creating. I did this for the two Gentium Plus fonts, and four base DejaVu Sans fonts.
Next, I created this customized fo2pdf serializer definition in the sitemap:
<map:components>
<map:serializers>
<map:serializer logger="sitemap.serializer.fo2pdf" mime-type="application/pdf" name="fo2pdf_custom" src="org.apache.cocoon.serialization.FOPSerializer">
<user-config>cocoon://testsite/fop-config.xml</user-config>
</map:serializer>
</map:serializers>
This tells FOP to use a specific config file, which is delivered from a pipeline elsewhere in the sitemap. That pipeline looks like this:
<map:match pattern="fop-config.xml">
<map:generate src="fop-fonts/fop-config-src.xml" />
<map:transform type="saxon" src="fop-config.xsl">
<map:parameter name="fontPath" value="{realpath:/}testsite/" />
</map:transform>
<map:serialize type="xml"/>
</map:match>
It gets its source from fop-config-src.xml, which looks like this:
<fop version="1.0">
<renderers>
<renderer mime="application/pdf">
<fonts>
<font metrics-url="fop-fonts/GentiumPlus-I.ttf.xml"
kerning="yes" embed-url="fop-fonts/GentiumPlus-I.ttf">
<font-triplet name="GentiumPlus" style="italic" weight="normal"/>
</font>
<font metrics-url="fop-fonts/GentiumPlus-R.ttf.xml"
kerning="yes" embed-url="fop-fonts/GentiumPlus-R.ttf">
<font-triplet name="GentiumPlus" style="normal" weight="normal"/>
</font>
<font metrics-url="fop-fonts/DejaVuSans.ttf.xml"
kerning="yes" embed-url="fop-fonts/DejaVuSans.ttf">
<font-triplet name="DejaVuSans" style="normal" weight="normal"/>
</font>
<font metrics-url="fop-fonts/DejaVuSans-Bold.ttf.xml"
kerning="yes" embed-url="fop-fonts/DejaVuSans-Bold.ttf">
<font-triplet name="DejaVuSans" style="normal" weight="bold"/>
</font>
<font metrics-url="fop-fonts/DejaVuSans-Oblique.ttf.xml"
kerning="yes" embed-url="fop-fonts/DejaVuSans-Oblique.ttf">
<font-triplet name="DejaVuSans" style="italic" weight="normal"/>
</font>
<font metrics-url="fop-fonts/DejaVuSans-BoldOblique.ttf.xml"
kerning="yes" embed-url="fop-fonts/DejaVuSans-BoldOblique.ttf">
<font-triplet name="DejaVuSans" style="italic" weight="bold"/>
</font>
</fonts>
</renderer>
</renderers>
</fop>
That source is transformed into the actual config file using this XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs xd"
version="2.0">
<xsl:param name="fontPath" />
<!-- On Windows, Cocoon's {realpath:/} omits the trailing slash. Since we
know where to expect it, we should be able to fix this. -->
<xsl:variable name="fixedFontPath" select="if (contains($fontPath, '\')) then replace(replace($fontPath, 'testsite', '/testsite'), '/', '\\') else $fontPath" />
<!-- XSLT Template to copy anything, priority="-1" -->
<xsl:template match="@*|node()|text()|comment()|processing-instruction()" priority="-1">
<xsl:copy>
<xsl:apply-templates select="@*|node()|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>
<!-- Massage the path attributes. -->
<xsl:template match="@metrics-url">
<xsl:attribute name="metrics-url"><xsl:value-of select="$fixedFontPath"/><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
<xsl:template match="@embed-url">
<xsl:attribute name="embed-url"><xsl:value-of select="$fixedFontPath"/><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Note: the structure of this file has changed considerably for the new FOP 1.0. The reason we use this setup instead of a hard-coded fop-config.xml is that we want our projects to be entirely portable without configuration changes; this system fills in the required hard-coded paths to the fonts directory on the fly, using Cocoon's realpath module, so it effectively makes those paths relative in the source XML file.
This actually works, in that I can use the GentiumPlus font family to render Russian characters (which will not render with the default fonts). One gotcha: I didn't realize how important it is to restart the servlet (Cocoon, or better, Tomcat); just making changes to the sitemap and other files seems to have little effect without this, so perhaps Cocoon reads and caches the config file for FOP on startup (or FOP gets started up when Cocoon is started, and reads it then).
I've also set up my test setup so that:
- The built webapp is symbolic-linked from the Tomcat webapps directory, so I actually don't need to copy it into Tomcat.
- The testsite code is symbolic-linked from inside the built webapp, so I don't need to copy it into the webapp. Obviously I'll have to have the Ant build recreate this link at the end of the build. I haven't done that yet.
- To make the tests work, you still have to manually upload some stuff into the database through the client. This is OK, really, as it's a test of the client, but it would be cool if this could be done somehow from the Ant build as well.
Next steps:
- Create a collection of fonts and font-metrics files that cover all the ranges we care about (we need something for CJK, and perhaps also Aboriginal Sans). We need a licence-free redistributable font array that will cover all our needs. For any given project, it would be trimmed down, of course.
- Enhance the Ant build script as above.
- Run another test build and archive the results.
- Start testing real sites inside the new build.