首页 > 解决方案 > 将渐变颜色样式应用于 xsl fo 中的文本

问题描述

我正在为 pdf 创建一个样式表,我想用渐变颜色格式化文本,如下图所示:

渐变色文本

我在网上找不到方法或任何文件。如果有人可以指导我,那将非常有帮助。

标签: xsl-fo

解决方案


在(应该)适用于任何 XSL FO 格式化程序的通用解决方案中,有两种选择。

  1. 如果文本内容没有换行(即不需要格式化程序来计算行尾和位置),可以替换标准 XSL 模板输出文本以触发某个类并将 SVG 作为 instream-foreign-object 输出。

  2. 如果文本内容换行或其他考虑要求格式化引擎完成其对文本进行布局的工作,那么可以开发一个 XSL 来修改来自格式化程序的区域树结果,以将输出文本元素替换为 SVG 的图像渐变文本。请注意,这可能非常复杂,尤其是在涉及文本字距调整并且文本“块”用于表示单行的情况下。

这是(1)的示例:

鉴于这个简单的 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>

而这个 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>

有人会得到这个输出:

在此处输入图像描述

当然,人们可以玩弄维度并得到他们需要的东西。这仅适用于单行文本。

也可以使用带有 text-anchor 和 dy 值的 tspan 来进行简单的布局,但同样需要知道将哪些文本片段放入 tspan 中的每个文本元素中。如果您的需求超出此范围,则只有方法 (2) 可行。


推荐阅读