これは純粋な XSL FO ではありませんが、RenderX のソフトウェアを使用してそのようなソリューションを実装しました。この解決策には、テキストの場所を含むページのすべての詳細を含む XML 構造であるエリア ツリーにページをそのままフォーマットすることが含まれます。特別な拡張 (rx:pinpoint 要素) を使用して、ソース XSL FO には、コンテンツをフェザーしたい場所にこれらのマーカーが含まれます。
元のドキュメントでは、フローとフッター領域に配置された色を使用して、ページで使用可能なスペースを計算します。
このすべての情報は、エリア ツリーで利用できます。XSL を使用してエリア ツリーを変更すると、使用可能な余白を「測定」し、フェザリング ピンポイントの数で割ってから、エリア ツリーを変更して、最終出力の前に構成後のコンテンツを「移動」できます。ほとんどすべてのフォーマッタで、シリアル化されたエリア ツリーを変更し、最終出力のためにソフトウェアに戻すことができます。
以下で重要なのは、領域ツリー内の後続のすべてのコンテンツを下に移動するために使用できる xep:translate 要素を知ることです。したがって、すべての領域を「ナッジ」するには、許可されたすべての「ナッジ」ポイントにこれらのいずれかを挿入して、コンテンツを (利用可能な空白/ナッジ ポイントの数) だけ下に移動します。
使用しているフォーマッタはわかりませんが、RenderX でない場合は、必要に応じて以下を変更できるかもしれません。これは、実際にはいくつかのアプリケーションで使用されています。その目的は、ページのテキスト コンテンツが常にページの最後で終了するように、すべてのページを「フェザー」することです。
サンプルへのリンク:
http://www.tandesa.com/Public/Nudge/sf-orig.pdf (これは、ナッジが適用されなかった場合に作成される元のファイルです)
http: /利用可能なナッジ領域を計算するため)
http://www.tandesa.com/Public/Nudge/sf-nudged.pdf (ナッジの結果)
http://www.tandesa.com/Public/Nudge/nudge.xsl (完全を期すために以下のファイル)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xep="http://www.renderx.com/XEP/xep" xmlns:math="http://exslt.org/math"
extension-element-prefixes="math" version="1.0">
<xsl:param name="max-feather-percent">40</xsl:param>
<xsl:param name="body-color" select="'1.0'"/>
<xsl:param name="footer-color" select="'1.0'"/>
<xsl:template match="xep:document">
<xsl:copy>
<xsl:apply-templates select="@*" mode="identity-copy"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="xep:internal-bookmark">
<xep:internal-bookmark>
<xsl:apply-templates select="@*" mode="identity-copy"/>
</xep:internal-bookmark>
</xsl:template>
<xsl:template match="xep:page">
<xep:page>
<xsl:apply-templates select="@*" mode="identity-copy"/>
<!--
1) Figure out white space
a) Extract the y-till of the footer-color rectangle
b) Find the smallest y-till of the body-color rectangle
c) (b) - (a) is white space
-->
<xsl:variable name="headertop"
select="number(xep:rectangle[preceding-sibling::xep:rgb-color[1][@red=$footer-color]]/@y-till)"/>
<xsl:variable name="pagebottom"
select="math:min(xep:rectangle[preceding-sibling::xep:rgb-color[1][@red=$body-color]]/@y-from)"/>
<xsl:variable name="whitespace" select="$pagebottom - $headertop"/>
<!--
2) Count the nudge areas
The nudge areas are all the pinpoints that start with "feather" *except* the first one on the page
and possibly the last one (need to determine it a nudge ends the page then exclude it also)
<xep:pinpoint x="90000" y="966000" value="feathersection"/>
Current implementation only ignores the first one and not the last
-->
<xsl:variable name="nudgepoints"
select="count(xep:pinpoint[starts-with(@value,'feather')]) - 1"/>
<!--
3) Calculate the nudge factor for each
-->
<xsl:variable name="nudgefactor" select="$whitespace div $nudgepoints"/>
<!--
4) Determine whether the page should be feathered at all
a) No nudgepoints
b) Space to compensate for is greater than max-feather-percent
-->
<xsl:variable name="apply-nudge">
<xsl:choose>
<xsl:when test="$nudgepoints = 0">
<xsl:text>false</xsl:text>
</xsl:when>
<xsl:when test="($whitespace div @height) > ($max-feather-percent div 100)">
<xsl:text>false</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>true</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:comment>
headertop: <xsl:value-of select="$headertop"/>
pagebottom: <xsl:value-of select="$pagebottom"/>
nudgepoints: <xsl:value-of select="$nudgepoints"/>
nudgefactor: <xsl:value-of select="$nudgefactor"/>
headertop: <xsl:value-of select="$headertop"/>
pagebottom: <xsl:value-of select="$pagebottom"/>
applynudge: <xsl:value-of select="$apply-nudge"/>
</xsl:comment>
<xsl:apply-templates select="*" mode="identity-copy">
<xsl:with-param name="nudgepoints" select="$nudgepoints"/>
<xsl:with-param name="nudgefactor" select="$nudgefactor"/>
<xsl:with-param name="apply-nudge" select="$apply-nudge"/>
</xsl:apply-templates>
</xep:page>
</xsl:template>
<!-- Replace proper pinpoints with xep:transform -->
<xsl:template match="xep:pinpoint[starts-with(@value,'feather')]" mode="identity-copy">
<xsl:param name="nudgepoints"/>
<xsl:param name="nudgefactor"/>
<xsl:param name="apply-nudge"/>
<xsl:if test="count(preceding-sibling::xep:pinpoint[starts-with(@value,'feather')]) > 0 and $apply-nudge = 'true'">
<xep:translate x="0">
<xsl:attribute name="y">
<xsl:value-of select="-1 * $nudgefactor"/>
</xsl:attribute>
</xep:translate>
</xsl:if>
</xsl:template>
<xsl:template match="xep:pinpoint[starts-with(@value,'dontfeather')]" mode="identity-copy">
<xsl:param name="nudgepoints"/>
<xsl:param name="nudgefactor"/>
<xsl:param name="apply-nudge"/>
<xsl:if test="count(preceding-sibling::xep:pinpoint[starts-with(@value,'dontfeather')]) = 0 and $apply-nudge = 'true'">
<xep:translate x="0">
<xsl:attribute name="y">
<xsl:value-of select="$nudgepoints * $nudgefactor"/>
</xsl:attribute>
</xep:translate>
</xsl:if>
</xsl:template>
<!-- Strip out the colored boxes -->
<xsl:template match="xep:rgb-color[@red='{$body-color}']" mode="identity-copy"/>
<xsl:template match="xep:rgb-color[@blue='{$footer-color}']" mode="identity-copy"/>
<xsl:template match="xep:rectangle[preceding-sibling::xep:rgb-color[1][@red='{$body-color}']]" mode="identity-copy"/>
<xsl:template match="xep:rectangle[preceding-sibling::xep:rgb-color[1][@blue='{$footer-color}']]" mode="identity-copy"/>
<!-- identity copy rules -->
<xsl:template match="node() | @*" mode="identity-copy">
<xsl:copy>
<xsl:apply-templates select="@*" mode="identity-copy"/>
<xsl:apply-templates select="node()" mode="identity-copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>