[xsl] XSL-FO - start-indent and end-indent

Subject: [xsl] XSL-FO - start-indent and end-indent
From: MURAKAMI Shinyu <murakami@xxxxxxxxxx>
Date: Wed, 10 Jan 2001 03:11:39 +0900
I've found some problems of XSL-FO CR spec about start-indent and end-indent.

Problem 1: Formulae for indents (indent=margin+padding+border?)
===============================================================

In [5.3.2 Margin, Space, and Indent Properties] of XSL-FO CR spec:
<quote>
The formulae for calculating the computed value of the "start-indent", 
and "end-indent" properties are as follows (where "margin-corresponding" 
is a variable for the corresponding absolute "margin" property):

end-indent = margin-corresponding + padding-end + border-end-width 
start-indent = margin-corresponding + padding-start + border-start-width 
</quote>

I understand that the margin- properties and the above formulae are 
provided for compatibility with CSS.
However the compatibility is imperfect.

Case 1: Indents on nested blocks

CSS (with HTML):
<div style="margin-left: 0pt; padding-left: 9pt; border-left: 6pt solid red">
  Outer Block
  <div style="margin-left: 0pt; padding-left: 9pt; border-left: 6pt solid blue">
    Inner Block
  </div>
</div>

Formatted as:
| Outer Block
| | Inner Block

XSL-FO (simply converted):
<fo:block margin-left="0pt" padding-left="9pt" border-left="6pt solid red">
  Outer Block
  <fo:block margin-left="0pt" padding-left="9pt" border-left="6pt solid blue">
    Inner Block
  </fo:block>
</fo:block>

Then, let's calculate the start-indents using the formula:

  start-indent = margin-corresponding + padding-start + border-start-width 
    = 0pt + 9pt + 6pt = 15pt  (on both outer and inner blocks)

and the equivalent XSL-FO will be:

<fo:block start-indent="15pt" padding-left="9pt" border-left="6pt solid red">
  Outer Block
  <fo:block start-indent="15pt" padding-left="9pt" border-left="6pt solid blue">
    Inner Block
  </fo:block>
</fo:block>

Formatted as:
| Outer Block
| Inner Block

Problem: Both start-indents have same value and the two borders overlap.
(because indents are measured from the containing reference-area, not the 
containing block)

To solve the problem
--------------------
The formulae should be corrected as:
  end-indent = inherit + margin-corresponding + padding-end + border-end-width 
  start-indent = inherit + margin-corresponding + padding-start + border-start-width 

Then,

  outer block: (here, inherit=0pt)
    start-indent = 0pt + 0pt + 9pt + 6pt = 15pt

  inner block: (here, inherit=(outer start-indent)=15pt)
    start-indent = 15pt + 0pt + 9pt + 6pt = 30pt

<fo:block start-indent="15pt" padding-left="9pt" border-left="6pt solid red">
  Outer Block
  <fo:block start-indent="30pt" padding-left="9pt" border-left="6pt solid blue">
    Inner Block
  </fo:block>
</fo:block>

and the formatted results are same as the original. 


Case 2: Indents on blocks without margin-corresponding specified

On the previous case, I did not omit margin-left:0pt.  In CSS, it can 
be omitted because zero is the initial value of margin- properties and 
these are not inheritable.  But in XSL-FO, it's not so easy since 
start- and end-indent are inheritable.

In CSS (with HTML):
<div style="padding-left: 9pt; border-left: 6pt solid red">
  Outer Block
  <div style="padding-left: 9pt; border-left: 6pt solid blue">
    Inner Block
  </div>
</div>

Formatted as:
| Outer Block
| | Inner Block
(same as when margin-left:0pt is specified on both block)

In XSL-FO (simply converted):
<fo:block padding-left="9pt" border-left="6pt solid red">
  Outer Block
  <fo:block padding-left="9pt" border-left="6pt solid blue">
    Inner Block
  </fo:block>
</fo:block>

The problem is how to get the start-indent values.
Since the margin-corresponding (margin-left) is not specified, the 
formulae for indents are not applicable.  In the XSL-FO spec, 
start/end-indent properties are inheritable and its initial value is 0pt.
Therefore, start-indent="0pt" is the answer (?)

If this is the correct interpretation, the above XSL-FO is equivalent to:

<fo:block start-indent="0pt" padding-left="9pt" border-left="6pt solid red">
  Outer Block
  <fo:block start-indent="0pt" padding-left="9pt" border-left="6pt solid blue">
    Inner Block
  </fo:block>
</fo:block>

Formatted as:
Outer Block
Inner Block
(borders are outside of the containing reference-area!!)

The results are very different from the original CSS.

I think this is very serious problem of compatibility with CSS. 

To solve the problem
--------------------
The formulae should be used although margin-corresponding are not 
explicitly specified.

  end-indent = inherit + margin-corresponding + padding-end + border-end-width 
  start-indent = inherit + margin-corresponding + padding-start + border-start-width
  (in this case, margin-corresponding defaults to 0pt)

Then, the start-indents are computed as follows:
  outer block: (here, inherit=0pt)
    start-indent = 0pt + 0pt + 9pt + 6pt = 15pt

  inner block: (here, inherit=(outer start-indent)=15pt)
    start-indent = 15pt + 0pt + 9pt + 6pt = 30pt

The omitted start-indents are filled as follows:

<fo:block start-indent="15pt" padding-left="9pt" border-left="6pt solid red">
  Outer Block
  <fo:block start-indent="30pt" padding-left="9pt" border-left="6pt solid blue">
    Inner Block
  </fo:block>
</fo:block>



Problem 2: Inherited start-indent and end-indent on reference areas
===================================================================

This problem has already been pointed out by other people.
In http://www.renderx.com/Tests/doc/html/spec.html [XSL FO in XEP 2.01]
<quote>
Another situation where holistic inheritance scheme adopted in XSL FO CR 
produces indesirable side effects. According to the spec, indents are 
inherited from fo:table to its descendants, i.e. table cells. But inside 
cells, indents are measured from another reference edge! Apparently, this 
has the following effect: when you specify an indent for the table, the 
contents of each cell is shifted by the same amount from the edge of the 
cell. 

In XEP 2.01, the inheritance is broken at this point: if an object 
introduces a new reference area, start-indent and end-indent for it are 
not inherited from its parent. In particular, this applies to fo:table-
cell, fo:block-container, and fo:inline-container. 
</quote>

In my implementation, too.



Problem 3: Indents on list-item-label and list-item-body
========================================================

As shown in the above, inherited start- and end-indent values are 
sometimes not useful and should be modified.

I request the following modification for solving the problem of inherited 
indents on list-item-label and list-item-body (label and body overlap 
when indents are not specified).

on list-item-label:
  end-indent defaults to label-end()
on list-item-body:
  start-indent defaults to body-start()

Then,

<fo:list-block>
  <fo:list-item>
    <fo:list-item-label>
      <fo:block>(1)</fo:block>
    </fo:list-item-label>
    <fo:list-item-body>
      <fo:block>List Item Body</fo:block>
    </fo:list-item-body>
  </fo:list-item>
</fo:list-block>

is now not an error and equivalent to:

<fo:list-block>
  <fo:list-item>
    <fo:list-item-label end-indent="label-end()">
      <fo:block>(1)</fo:block>
    </fo:list-item-label>
    <fo:list-item-body start-indent="body-start()">
      <fo:block>List Item Body</fo:block>
    </fo:list-item-body>
  </fo:list-item>
</fo:list-block>



Conclusion
==========

This comment contains some requests to XSL-FO spec, and these features have 
already been built into my implementation, as well as my last comments:

"XSL-FO - Initial value of border/padding conditionality"
http://lists.w3.org/Archives/Public/xsl-editors/2000OctDec/0297.html

Therefore, my implementation does not completely conform to the XSL-FO CR.
IMHO, the XSL-FO spec is not complete yet and should be improved.


Regards,

MURAKAMI Shinyu
"Antenna House XSL Formatter" - http://www.antennahouse.com/xslformatter.html

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread