Question

I am working on a project in which we have charts and a table exported to PDF. We are using Apache FOP for the PDF generation. The charts are in SVG and display fine if there's only one. However, we will have cases in which there are up to four, and in these instances only three of the four are fitting on the generated PDF. I need all images to fit regardless of number. I'm afraid simply putting the page in landscape will be a temporary solution for when we need even more to fit. The sizes of each chart are set in pixels from the svg generated in the client by the Highcharts library. It appears as though the images are inserted into the pdf without any scaling, even though I set attributes for the instream-foreign-object per an example seen here: Scaling images using scale-to-fit

So I need each chart to "shrink to fit". I have tried setting the length and width of the element that encloses each element that contains an instream-foreign object (I am also including my xsl). Within the instream-foreign -object I am assigning the svg width & height to the values from the actual chart svg. I thought maybe this was the problem, but if I don't include these dimensions the charts don't appear in the pdf. I also tried setting the scaling attribute to "non-uniform" per the question here: Scale images with fixed height and the results were no better. It actually stretched a chart across the whole page thus displaying only one of four. Here's my xsl:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <fo:root>
    <fo:layout-master-set>
        <fo:simple-page-master master-name="exportPage">
            <fo:region-body />
            </fo:simple-page-master>
        </fo:layout-master-set>
        <fo:page-sequence master-reference="exportPage">
        <fo:flow flow-name="xsl-region-body">
            <fo:block id="mainTitleBlock" font-family="arial, helvetica, sans-serif" color="#5c068c" font-weight="bold">
                <xsl:value-of  select="exports/export/charts/@mainTitle"/>
            </fo:block>
            <fo:block id="timestampBlock" font-family="arial, helvetica, sans-serif" font-size="small" color="#6D869F">
                <xsl:value-of  select="exports/export/charts/@timeStamp"/>
            </fo:block>
            <!-- This is where the charts go -->
            <!-- Within this block will be an inline element for each chart--> 
        <fo:block id="chartBlock" width="8.25in" height="6in">

          <xsl:apply-templates select="exports/export/charts/chart"/>

        </fo:block>
                <fo:block id="tableBlock" >
                    <xsl:apply-templates select="exports/export/table"/>
                </fo:block>
            </fo:flow>
            </fo:page-sequence>
         </fo:root>
</xsl:template>
   <!-- Creates the table -->
<xsl:template match="table">
<fo:table table-layout="fixed" width="100%" >
    <fo:table-header>
    <fo:table-row>
    <xsl:apply-templates select="tblRow[position() = 1]"/>
    </fo:table-row>
    </fo:table-header>
    <fo:table-body>
    <xsl:apply-templates select="tblRow[position() > 1]"/>
    </fo:table-body>
</fo:table>
</xsl:template>

<xsl:template match="hdrCell">
    <fo:table-cell background-color="#666" border-right-style="solid" border-right-width="1px" border-right-color="white" empty-cells="show">
    <fo:block color="white" font-family="arial, helvetica, sans-serif" font-size="x-small"><xsl:value-of select="."/></fo:block>
    </fo:table-cell>
</xsl:template>

<xsl:template match="tblCell">
    <fo:table-cell border-bottom-style="solid" border-bottom-width="1px" border-bottom-color="#E3E3E3" >
    <fo:block color="#7E7E7E" font-family="arial, helvetica, sans-serif" font-size="x-small"><xsl:value-of select="."/></fo:block>
    </fo:table-cell>
</xsl:template >

<xsl:template match="tblRow[position() > 1]">
    <fo:table-row>
    <xsl:apply-templates />
    </fo:table-row>
</xsl:template>

<xsl:template match="chart">
<fo:inline>
    <fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg" content-width="scale-to-fit" content-height="100%" width="100%" scaling="uniform">
    <svg:svg width="{svg:svg/@width}" height="{svg:svg/@height}">
    <xsl:copy-of select="svg:svg"/>
    </svg:svg>
    </fo:instream-foreign-object>
</fo:inline>
</xsl:template>

 </xsl:stylesheet>

What am I missing? Would it help to display the charts in table-cells (thus breaking the convention of not using tables for layout- the horror!)? How can I get these to scale and fit in the page?

Thanks, Brandt

Was it helpful?

Solution

The scale property makes the chart fit in the containing block. If you haven't set dimensions for that block, the formatting engine won't know what size to scale to so it will use 100%. I don't know what happens when you place more than one chart into one block.

You may need to put the charts in a table, one chart per column so you can set the column widths depending on the number of charts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top