determine text length in apache fop? - pdf-generation

I'm generating some PDFs and sometimes the User Input is too long to fit into a table cell. So at certain spots, I just truncated Strings longer than x characters. But that is always a guess. Is there any way to figure out what size a certain text will be printed?
my document looks a bit liks this:
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family="Helvetica">
<fo:table table-layout="fixed" width="200mm">
<fo:table-column column-width="20mm"/>
<fo:table-column column-width="25mm"/>
...
<fo:table-body>
<fo:table-row>
<fo:table-cell border="black 1pt solid" padding="0.6mm 1mm 0.5mm 1mm">
<fo:block text-align="right" font-weight="bold" font-size="8.4pt">Name:</fo:block>
</fo:table-cell>
<fo:table-cell border="black 1pt solid" padding="0.6mm 1mm 0.5mm 1mm">
<fo:block text-align="left" font-weight="normal" font-size="8.4pt">FirstName LastName</fo:block>
</fo:table-cell>
...
</fo:table-row>
and I'd like to know in advance if "FirstName LastName" will fit into the 25mm when rendered.

Related

xsl fo center a table and an image using display-align="center"

I'm learning xsl:fo and training using the xml example file on w3schools : https://www.w3schools.com/xml/cd_catalog.xml, which I modified a bit to add a "PICTURE" tag.
I parse the file to gather the information of each CD in a table, using xsl:for-each, fo:table and fo:external-graphic. I use display-align="center" for both of them, as suggested in previous questions, and it does not work : images and tables stay aligned on the left.
Here is a code sample (I removed most of the style attributes to make it more readable) :
<xsl:for-each select="CATALOG/CD">
<fo:block text-align="center">
<xsl:value-of select="TITLE"/> - <xsl:value-of select="ARTIST"/>
</fo:block>
<fo:block>
<fo:external-graphic content-height="scale-to-fit" width="2.00in" content-width="2.00in" display-align="center">
<xsl:attribute name="src">pictures/<xsl:value-of select="PICTURE"/>.jpg</xsl:attribute>
</fo:external-graphic>
</fo:block>
<fo:table table-layout="fixed" font-family="Helvetica" text-indent="2em" space-before="2em" display-align="center">
<fo:table-column column-width="4cm"/>
<fo:table-column column-width="4cm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell><fo:block>Country :</fo:block></fo:table-cell>
<fo:table-cell><fo:block><xsl:value-of select="COUNTRY"/></fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell><fo:block>Company :</fo:block></fo:table-cell>
<fo:table-cell><fo:block><xsl:value-of select="COMPANY"/></fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell><fo:block>Price :</fo:block></fo:table-cell>
<fo:table-cell><fo:block><xsl:value-of select="PRICE"/></fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell><fo:block>Year :</fo:block></fo:table-cell>
<fo:table-cell><fo:block><xsl:value-of select="YEAR"/></fo:block></fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</xsl:for-each>
display-align="center" is for centering vertically (i.e., in the block-progression-direction). See https://www.w3.org/TR/xsl/#display-align. (Also, display-align doesn't apply to fo:table. If you did want to center the table vertically, you'd have to use display-align="center" on the FO that contains the fo:table.)
For left-right centering (in the inline-progression-direction), use text-align="center": see https://www.w3.org/TR/xsl/#text-align
However, text-align doesn't apply to fo:table, so you need to put it on an fo:table-and-caption and put the fo:table as a child of the fo:table-and-caption (and the fo:table-caption is optional). See https://www.w3.org/TR/xsl/#fo_table-and-caption

Dotted border background on Apache FOP

I'm generating some PDF with Apache FOP and I would like to have some dotted borders on some cells. However, it seems that the border background takes its color from the Table itself and not the cell, which is rather odd IMHO.
This is a simple example :
<?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xml:lang="en">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-landscape" page-height="210mm" page-width="297mm">
<fo:region-body margin-top="15mm" margin-bottom="15mm" margin-left="15mm" margin-right="15mm" />
<fo:region-before region-name="docHeader"/>
<fo:region-after region-name="docFooter" extent="15mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-landscape" initial-page-number="1">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:table table-layout="fixed" break-after="page" background-color="red">
<fo:table-column column-width="100.0mm" />
<fo:table-body>
<fo:table-row height="25.0mm">
<fo:table-cell text-align="center" display-align="center" background-color="blue" border-top="0.35277778mm dotted green"
border-bottom="0.35277778mm solid rgb(0,0,0)"
border-left="0.35277778mm solid rgb(0,0,0)"
border-right="0.35277778mm solid rgb(0,0,0)">
<fo:block-container overflow="hidden">
<fo:block wrap-option="no-wrap">test</fo:block>
</fo:block-container>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
<fo:block id="endOfDoc"></fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
And this is the result :
Do you have any ideas how to set the border's background color?
Id this a normal behaviour?
Yes, this is normal behavior. The cell is drawn inside the border and the dotted border is split between. Using RenderX XEP with miters corners and this becomes a little more obvious in what happens. Look at this zoomed image of the corner:
Now, you could try to juggle around what you are doing as one option. Like this:
<fo:table table-layout="fixed" break-after="page" background-color="red">
<fo:table-column column-width="100.0mm" />
<fo:table-body>
<fo:table-row>
<fo:table-cell background-color="blue" display-align="center"
border-bottom="0.35277778mm solid rgb(0,0,0)"
border-left="0.35277778mm solid rgb(0,0,0)"
border-right="0.35277778mm solid rgb(0,0,0)">
<fo:block-container height="25.0mm" overflow="hidden" border-top="0.35277778mm dotted green" text-align="center" >
<fo:block wrap-option="no-wrap">test</fo:block>
</fo:block-container>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
and you would get this:

How can I render a list of items as 4 blocks using Freemarker and Apache FOP?

I have a list of objects that I want to iterate over using Freemarker to produce a FOP template that shows four of these items on each page.
Each item should take up a quarter of the page.
In HTML I would probably float the divs so they flow together as they fit the page, but I don't know how to do that with FOP.
I've tried using inline elements to achieve this, but that doesn't work as I expect.
<fo:page-sequence master-reference="apage">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<#list entries as entry>
<fo:inline background-color="blue" border="2px solid black">
<fo:block height="100mm" width="150mm" background-color="red" border="2px solid green">
<#include "singleCardTemplate.ftl">
</fo:block>
</fo:inline>
</#list>
</fo:block>
</fo:flow>
</fo:page-sequence>
The singleCardTemplate.ftl included is responsible for rendering a single item, which seems to be working, only it renders at full width, not 150mm as I'd hoped. I'd like 2x150mm wide blocks next to each other with 2 more underneath. So four per page.
I'm happy the Freemarker/FOP combo is working properly, I do get a PDF generated with the correct content and some borders/colours as per above.
What am I doing wrong?
I found a solution, move to table layout.
I'd prefer to use a layout that flowed like HTML inline-block elements but this seems to work...
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:table table-layout="fixed" height="100%">
<fo:table-column column-width="proportional-column-width(2)"/>
<fo:table-column column-width="proportional-column-width(2)"/>
<fo:table-body font-size="10pt">
<fo:table-row height="100mm">
<#list entries as entry>
<fo:table-cell margin="5mm">
<#include "singleCardTemplate.ftl">
</fo:table-cell>
<#assign mod = entry_index % 2 />
<#if entry_has_next>
<#if mod == 0>
</fo:table-row>
<fo:table-row height="100mm">
</#if>
</#if>
</#list>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:flow>

xsl-fo absolute placement of images

I am trying to put an image in the left upper corner of the page.
However hard I try, i cannot place the image correctly. There is always ca 1mm space between the image and the top of the page!
The problem seems to be in the placement of the external-graphic. the enclosing block (yellow) is placed correctly but the image is shifted down. you can see this in the pdf, the enclosing yellow block is visible above the gray image!
I tried some combinations of attributes trying to influence the placement of the image (absolute-position, position, space-before) but with no effect.
appreciate your help!
here is how it looks like:
boxes.pdf
here is my fo.xml:
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:r="http://xml.lazalab.com/reditor" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="DE">
<fo:layout-master-set>
<fo:simple-page-master fox:scale="1" fox:crop-offset="5mm" fox:crop-box="media-box" fox:bleed="5mm" margin-right="0mm" margin-left="0mm" margin-bottom="0mm" margin-top="0mm" master-name="MASTERsite1" page-width="214mm" page-height="301mm">
<fo:region-body background-color="green" margin="0mm"/>
<fo:region-before background-color="yellow" precedence="true" extent="0mm"/>
<fo:region-after background-color="cyan" precedence="true" extent="0mm"/>
<fo:region-start background-color="pink" extent="0mm"/>
<fo:region-end background-color="gold" extent="0mm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="MASTERsite1">
<fo:flow reference-orientation="0" border-collapse="collapse" flow-name="xsl-region-body">
<fo:block-container absolute-position="absolute" width="214mm" height="301mm" background-color="cyan">
<fo:block-container overflow="hidden" width="100mm" height="200mm" background-color="cyan">
<fo:block top="0mm" left="0mm" padding="0mm" margin="0mm" background-color="yellow">
<fo:external-graphic line-height="0mm" padding="0mm" margin="0mm" width="100mm" height="200mm" background-color="grey" src="#"/>
</fo:block>
</fo:block-container>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
Set line-height on the block with the image to "0" and test again. It is likely the image is placed according to the font baseline. As in:
<fo:block top="0mm" left="0mm" padding="0mm" margin="0mm" background-color="yellow" line-height="0mm" >
<fo:external-graphic padding="0mm" margin="0mm" content-width="100mm" height="200mm" background-color="grey" src="test.jpg"/>
</fo:block>
I tested this with a few formatters and the image goes to the top of the page.

Apache FOP: zindex does not appear to be working in overlapping blocks

I am a FOP newb. I am trying to show text on top of an image by using block-container's and zindexes. The image is always on top though. If i remove the image, i can see the text, so the text is under the image.
This is inside of a table cell. here is the relevant code:
<fo:table-cell padding="0.000pt" text-align="left" display-align="before">
<fo:block>
<fo:block-container z-index="2" position="absolute" left="0.913in" top="0.139in" width="0.946in" height="0.198in" overflow="hidden">
<fo:block><fo:inline font-family="Verdana" font-size="8pt">Leasure Station</fo:inline></fo:block>
</fo:block-container>
<fo:block-container z-index="2" position="absolute" left="0.091in" top="0.431in" width="0.302in" height="0.239in" overflow="hidden">
<fo:block><fo:inline font-family="Verdana" font-size="8pt">#1</fo:inline></fo:block>
</fo:block-container>
<fo:block-container z-index="2" position="absolute" left="0.653in" top="0.431in" width="1.186in" height="0.177in" overflow="hidden">
<fo:block><fo:inline font-family="Verdana" font-size="8pt">ASDF1234QWER</fo:inline></fo:block>
</fo:block-container>
<fo:block-container z-index="1" position="absolute" left="0in" top="0in" width="48.5mm" height="20mm" overflow="hidden">
<fo:block><fo:external-graphic src="url(.\fop-1.0\img\orange_s_text.png)" content-width="48.500mm" scaling="non-uniform" content-height="20.000mm"/></fo:block>
</fo:block-container>
</fo:block>
</fo:table-cell>
moved the block with index 1 before all the zindex=2 blocks and it worked. whatever.

Resources