Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Xmlgraphics-fop Wiki" 
for change notification.

The "AutoTableLayout" page has been changed by GregorBerg:
https://wiki.apache.org/xmlgraphics-fop/AutoTableLayout?action=diff&rev1=7&rev2=8

Comment:
more details all over the place, only nested tables are left

  
   * w("abc") = width of the string "abc"
   * LM as abbreviation for !LayoutManager
+  * PGU as abbreviation for !PrimaryGridUnit
  
  == Simple Tables ==
  === Without Breaks ===
@@ -33, +34 @@

  ||a ||ab ||a b c ||
  
  
- The first row is checked and the width of each column is set to the width of 
its first table cell, thus: min/opt/max = w(character). Afterwards, the second 
row is inspected.
+ The first row is checked and the width of each column is set to the width of 
its first table cell, thus: min/opt/max = w(character). During the 
determination of a cell's width, its PGU is inspected in the TableContentLM's 
setLength(PGU) to obtain the minimal (''minIPD'') and maximal (''ipd'') width. 
Afterwards, the second row is inspected.
  
   * column 1: min/opt/max are identical for the second table-cell and, 
therefore, the column width remains the same
   * column 2: since this table cell contains two '''consecutive''' characters, 
its minimum increases to their width. Again, the maximum width is identical and 
this column is set to min/opt/max = w(two characters)
   * column 3: for this table cell, the ''minimum ''value is the width of the 
widest letter since FOP can insert a linebreak after each individual letter. 
The ''maximum ''and ''optimal'' value, however, are w("a b c")
  
- After the table was inspected, each column has a !MinOptMax instance 
representing its viable widths. Since the sum of all max values is less than 
the available space, the opt value (initialized as ''max'') does not need to be 
changed. All columns are rendered using their respective opt/max value
+ After the table was inspected, each column has a !MinOptMax instance 
representing its viable widths. Since the sum of all max values is less than 
the available space, the opt value (initialized as ''max'') does not need to be 
changed. All columns are rendered using their respective opt value (in this 
case, opt==max).
  
  === With Breaks ===
  ||<tablewidth="200px">a ||b ||c ||
@@ -55, +56 @@

    * max = w("a b c d")
    * opt (for now) = w("a b c d")
  
- Again, each column has a !MinOptMax instance representing its viable widths. 
In this case, however, the sum of max values is greater than the available 
space. The available space has to redistributed among the columns (cf. 
!ColumnSetup's redistribute()).
+ Again, each column has a !MinOptMax instance representing its viable widths. 
In this case, however, the sum of max values is greater than the available 
space (checked in computeOptimalColumnWidthsForAutoLayout()). The available 
space has to redistributed among the columns (cf. !ColumnSetup's 
redistribute()).
  
  Out of a list of all columns, FOP removes those which cannot be shrinked. At 
first, FOP excludes any columns containing only consecutive letters (i.e. min 
== max, in the example the first two columns) and columns which have a static 
width. Then, the remaining columns are set to math.max(column's min value, 
column's max value * shrink factor) - thus, they are either shrinked as far as 
possible or set to their min value. Opt values are assigned to these columns 
(iteratively) until the sum of their opt values is <= the available space.
  
@@ -64, +65 @@

  '''Note: '''Columns with a static width (e.g. "2cm") are never resized.
  
  === Not Enough Space ===
- In case the sum of all min values is greater than the available space, a 
warning ('columnsInAutoTableTooWide') is produced. FOP sets all columns to 
their respective min value and will most probably produce an overflow.
+ In case the sum of all min values is greater than the available space, a 
warning is displayed ('columnsInAutoTableTooWide', produced in 
computeOptimalColumnWidthsForAutoLayout()). FOP sets all columns to their 
respective min value and will most probably produce an overflow.
  
  == Cells Spanning Rows and Columns ==
  While tables containing table cells employing row-span values are not a 
problem (''please have a look at'' 
[[https://issues.apache.org/jira/browse/FOP-2451|FOP-2451]] ''for a related 
patch''), col-span table cells have to be taken into account.
  
  FOP produces a !PrimaryGridUnit (PGU) for each table cell. If this table cell 
happens to span y rows and x columns, the corresponding x*y-1 !GridUnits are 
created to fill the model of the table with placeholders. Since FOP inspects a 
table from left to right (using a !TableRowIterator) and from top to bottom 
(using a lot of them), the PGU is always encountered first during the FOP's 
column width determination. Spanned rows do not have an impact on the column's 
width since (after the content of the PGU was already processed) they do not 
carry additional content. For spanned columns, on the other hand, the following 
three cases exist.
  
- === Balanced Expansion/Reduction ===
+ === Balanced Expansion ===
- ||<tablewidth="auto">a ||b ||c ||
+ ||<tablewidth="auto"width="15px">a ||b ||c ||
  ||||<style="text-align:center">abc abc abc ||a b c ||
  
  
- In case a table cell spans several columns, its !MinOptMax determination is 
different. In the above example, the first row leads to columns with !MinOptMax 
values of w(a), w(b), and w(c), respectively. In the second row, FOP encounters 
a cell which has a min of w("abc") and a max of w("abc abc abc"), all of which 
are greater than the max widths of the spanned columns (=w(a) + w(b) + 
indentations between these spanned columns). Since the spanned columns are 
supposed to display the content of the spanning table cell as well, their 
potential widths need to be adapted. This is done when the corresponding PGU is 
processed in !TableContentLM's setBaseLength().
+ In case a table cell spans several columns, its !MinOptMax determination is 
different. In the above example, the first row leads to columns with !MinOptMax 
values of 15 points (static column), w(b), and w(c), respectively.
  
-  * calculate sum of the min and max
-  * TODO: algorithm for expanding columns until their combined width suffices 
for cells spanning these columns (+ reduction)
+ In the second row, FOP encounters a cell which has a min of w("abc") and a 
max of w("abc abc abc"), all of which are greater than the max widths of the 
spanned columns (=w(a) + w(b) + indentations between these spanned columns). 
Since the spanned columns are supposed to display the content of the spanning 
table cell as well, their potential widths need to be adapted. This is done 
when the corresponding PGU is processed in TableContentLM's setBaseLength(PGU).
+ 
+ First of all, the minimal spanned width (minSpanWidth := ''sum of min widths 
of all spanned columns'') and the optimal spanned width (availableSpanWidth := 
''sum of opt widths of all spanned columns'') are calculated. Based on the 
dimension of the PGU's content, FOP already knows the spanning table cell's 
minimal width (''minIPD := w("abc")'') and its optimal width (''ipd := w("abc 
abc abc")'').
+ 
+ FOP determines that the spanned columns need to be widened since their 
minimal width (''isNotSufficientForMinIPD := minSpanWidth < minIPD'') and 
optimal width (''isNotSufficientForIPD := availableSpanWidth < ipd'') are 
insufficient. From the spanned columns (a and b in the example), FOP selects 
those which are not static (only b) and, thus, can be widened. If no column can 
be found, a warning is displayed.
+ 
+ If the minimum width is unavailable, all selected table columns' minimal 
width values (and their opt/max values) are increased (each gets a proportional 
cut of the missing space, cf. increaseMinimumWidthOfSpannedColumns()) to avoid 
an overflow.
+ 
+ The space gained through this increase is counted towards the ''sum of opt 
widths of all spanned columns''. If'' ''this optimal width is still 
insufficient, the opt/max widths of the selected columns is increased even more 
(increaseOptimalWidthOfSpannedColumns()).
+ 
+ In the example, column b would be the only column to widen - it would end up 
with an optimal width of w("abc abc abc") - (w("a") + Indentations). Of course, 
these are only the optimal values. If the table's optimal width would be too 
big, the columns would be reduced as far as possible as described before. In 
this case, the spanned columns (only column b) would provide their new minimal 
width (w("abc") - (w("a") + Indentations)). Thus, the described injection of 
new min, opt and max widths ensures that the width of table cells spanning 
multiple columns is always distributed as equally as possible among the columns 
which are spanned. Also, this distribution approach works quite robust - a 
column may be spanned by an arbitrary number of cells in almost any 
configuration imaginable. One exception is described in the sections "Worst 
Case".
+ 
+ An example illustrating a complex case can be found in issue 
[[https://issues.apache.org/jira/browse/FOP-2450|FOP-2450]] 
(resize-all-but-static-spanned-columns.xml/pdf).
  
  === Special Case: requiresSecondRun ===
+ There is a special case for the distribution approach described above (at 
least in the current implementation of the patch - it may and should be fixed 
for increased performance). The approach described above extends columns which 
already have a !MinOptMax instance assigned to them. This is not possible if 
the very first row of a table contains a table cell spanning multiple rows (see 
table in this section) - at this point, the necessary data structures are not 
initialized. Therefore, the current implementation explicitly checks for this 
case (TableContentLM's iterateOverTableRows(): ''is there PGU which spans 
multiple columns in the first row?''), skips this PGU, and sets a flag 
(''requiresSecondDeterminationRun = true;'') informing the table's TableLM to 
start the determination again (twice the effort for this case!). '''Potential 
improvement:''' ''instead of revisiting the whole table, simply go back to the 
first row (if it fulfills the special case) and recalculate this row only 
before finishing the determination. ''
- '''TODO:''' special case if the very first row contains a table cell spanning 
multiple columns.
- 
  ||||<tablewidth="auto"style="text-align:center">abc abc abc ||a b c ||
  ||a ||b ||c ||
  
  
- '''Potential improvement:''' instead of starting over, simply go back to the 
first row and recalculate *only this row* before finishing the determination.
+ 
  
  === Worst Case ===
+ In a complex table, table cells spanning over multiple columns may overlap 
not only one, but constantly over one or more columns - HTML tables ignore this 
case, so here is an ASCII example:
- In this case, FOP encounters a column for which no !PrimaryGridUnit can be 
found, except for the one in the first row. This case is ignored in HTML tables 
- column b is simply ignored...
- ||||<tablewidth="auto"style="text-align:center">ab (rowspan=2) ||c ||
- ||a ||||<style="text-align:center">bc (rowspan=2) ||
  
- 
- 
- 
- text
+ {{{
+ =============
+ | abcde | c |
+ =============
+ | a | abcde |
+ =============
+   ^a  ^b  ^c
+ }}}
+ In this case, FOP has to cope with a column (''b'') for which no 
!PrimaryGridUnit can be found. Since the width determination of table cells is 
based on PGUs, no exact determination is possible. In its current 
implementation, the patch seems to favor such columns over any other column if 
spanned columns have to be widened, which can lead to imbalanced expansions.
  
  == Nested Tables ==
  So far, all scenarios only described the handling of isolated tables. 
However, nested tables are also quite common and, depending on their kind, 
require a specific treatment.
  
  === Auto Table in Fixed Table ===
- This case is quite trivial: FOP knows the exact dimensions of the surrounding 
table cell (which either has a static width of is exactly one table-column 
unit) and, thus, can determine the optimal column widths for the available 
space.
+ This case is quite trivial: FOP knows the exact dimensions of the surrounding 
table cell (which either has a static width or requires exactly one 
table-column unit) and, thus, can determine the optimal widths for the nested 
table's columns based on the available space.
  
  === Fixed Table in Auto Table ===
- If an auto table's table cell contains a fixed table, things get a little bit 
complicated.
+ If an auto table's table cell contains a fixed table, things get a little bit 
more complicated.
  
  The surrounding auto table needs to know the min and max widths of its 
columns, i.e. of each individual table cell. Only then will it be able to 
determine its optimal column width which, in turn, is required to inform the 
nested table how much space is has available. Luckily, the determination of the 
minimal the nested table's TableLM can determine the minimal width 
independently. So, when the nested TableLM's getMinimumIPD() is invoked, it 
returns the following result as its minimal required width for a complete table 
(cf. getMinimumIPDforFixedLayout()):
  
   * sum of all static columns + number of dynamic columns * (highest minimal 
value of all dynamic columns)
  
- '''TODO''''': max width via ''getNextKnuthElements ''in !TableCellLM -- table 
cell demands more space when its childLMs request more space than it allocated 
for them (#226) ''
+ '''TODO''''': max width via ''getNextKnuthElements ''in TableCellLM -- table 
cell demands more space when its childLMs request more space than it allocated 
for them (#226) ''
  
  === Auto Table in Auto Table ===
  Again, the surrounding table needs to know the required space for the 
contained one while the contained table needs to know how much is available.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to