I am creating a stylesheet for pdf and I wanted to format text with gradient color as in this image:
I couldn't find a way or any documents online. It would be very helpful if anybody could guide me.
I am creating a stylesheet for pdf and I wanted to format text with gradient color as in this image:
I couldn't find a way or any documents online. It would be very helpful if anybody could guide me.
In a generic solution that would (should) work for any XSL FO formatter, one would have two choices.
If the text content is not wrapping (i.e. does not need the formatter to calculate line endings and placement), one could replace the standard XSL template outputting text to trigger off some class and output an SVG as an instream-foreign-object.
If the text content wraps or other considerations require the formatting engine to do its job laying out the text, then one could development an XSL that modifies the area tree result from the formatter to replace the output text elements with an image that is the SVG with gradient text. Note that this could be very complex, especially if text kerning is involved and "chunks" of text are used to represent a single line.
Here is a sample for (1):
Given this simple XML:
<test>
<text>This is some text</text>
<text gradient='true'>This is some gradient text</text>
<text>This is some more text</text>
</test>
And this XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rx="http://www.renderx.com/XSL/Extensions"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<fo:root font-size="20pt" line-height="24pt">
<fo:layout-master-set>
<fo:simple-page-master master-name="page" page-width="8.5in" page-height="11in">
<fo:region-body region-name="body" margin-top="0.5in" margin-bottom="0.5in" margin-left="0.5in" margin-right="0.5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page">
<fo:flow flow-name="body">
<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="text[@gradient]">
<fo:block>
<fo:instream-foreign-object>
<svg:svg xmlns:svg="http://www.w3.org/2000/svg" viewBox="0 -4 400 30">
<svg:defs>
<svg:linearGradient id="MyGradient" gradientUnits="userSpaceOnUse">
<svg:stop offset="0%" stop-color="black"/>
<svg:stop offset="25%" stop-color="orange"/>
<svg:stop offset="50%" stop-color="yellow"/>
<svg:stop offset="70%" stop-color="green"/>
<svg:stop offset="100%" stop-color="black"/>
</svg:linearGradient>
</svg:defs>
<svg:text fill="url(#MyGradient)" x="0" y="20" font-size="20pt">
<xsl:apply-templates/>
</svg:text>
</svg:svg>
</fo:instream-foreign-object>
<fo:leader/>
</fo:block>
</xsl:template>
<xsl:template match="text">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
One would get this output:
Of course, one could play with the dimensions and get what they need. This would only work for single lines of text.
It would also be possible to use tspan with text-anchor and dy values to do simple layouts, but again it would need to be known what fragments of text to put in each text element in the tspan. If your needs reach beyond this, then only method (2) would work.
In a generic solution that would (should) work for any XSL FO formatter, one would have two choices.
If the text content is not wrapping (i.e. does not need the formatter to calculate line endings and placement), one could replace the standard XSL template outputting text to trigger off some class and output an SVG as an instream-foreign-object.
If the text content wraps or other considerations require the formatting engine to do its job laying out the text, then one could develop an XSL that modifies the area tree result from the formatter to replace the output text elements with an image that is the SVG with gradient text. Note that this could be very complex, especially if text kerning is involved and "chunks" of text are used to represent a single line.
See next answer for some additional input.