On Jul 20, 2007, at 10:52, Luca Furini wrote:

Andreas L. Delmelle wrote:

That's one detail I was still unsure about. Only if the other factors remain identical, the algorithm would prefer a break at penalty 50 over one at penalty 100... but if the value of the penalty is only of marginal influence as you suggest, then this would indeed not be enough.

I made some quick computation to see how the demerits change according to the penalty value and the adjustment ratio (see the table in the attached pdf).

It seems that the penalty value is highly relevant as long as the adjustment ratio varies between -1 and 1 (i.e. we are choosing among breaks that are quite good), but rapidly becomes less and less important as the adjustment ratio grows.

For example, in order to let the algorithm prefer a break with ratio 2 (and no penalty value) to a different one with ratio 1.5, the penalty value for the second penalty should be at least 500; and no penalty value can make the algorithm prefer a break with ratio = 3 to another one with ratio = 2.5 (as we use 1000 as "infinite penalty").

Interesting figures.

Makes me wonder if we could actually involve the keep value in the demerits computation somehow, maybe use it to level out the influence of the plain adjustment ratio (that is purely based on the difference between content-width and line-width, and the combined stretch/shrink of the glues).

In very rough terms, the logic behind it would be:
if a given break #1 has a plain adjustment ratio of 3 and a governing keep of "auto", and the next break #2, regardless of its adjustment ratio, would violate a keep-constraint with a higher value, => apply a 'correction factor' to the demerits of break #1 so that the influence of the plain adjustment ratio is significantly reduced, and it will be considered a "good break" in spite of its being "way too short".

If the effective demerit computation of break #2 takes into account the fact that that break itself would violate a keep (other than "auto"), its demerits would in turn be artificially increased, so if eventually presented with a choice, the algorithm would prefer the first break over the second.

No idea if this would be feasible in practice though...

double effectiveRatio = (adjustmentRatio * keepRatio);

where keepRatio is a double value based on the keep-values, that would either leave the adjustmentRatio as is (= 1), or increase/ reduce the influence of the plain value.

In the example I posted earlier:
<fo:block>
   Some text with "auto" keep-constraint
   <fo:inline keep-together.within-line="100">
   Some text with a keep.within-line constraint of "100"
     <fo:inline keep-together.within-line="500">
       keep.within-line="500"
     </fo:inline>
   Some more text in the first nested inline
   </fo:inline>
   More text after the first nested inline.
</fo:block>
The "acceptable" set of breaks may turn out to give a result like (with '|' = the end-boundary of the line)
Some text with "auto" keep-constraint"         |(1)
Some text with a keep.within-line constraint of|(2)
"100" keep.within-line="500"                   |(3)
Some more text in the first nested inline      |(4)
More text after the first nested inline        |(5)

Only the third and the fourth line I'm still unsure about. May the content in the fourth line be broken itself?

I'm quite unsure about the third line too, as the outer keep constraint affects also the space between the inner inline and "Some more text ..." so break #3 is violating the keep and even creating a very short line.

I would probably expect something like

  Some text with "auto" keep-constraint"         |(1)
  Some text with a keep.within-line constraint of|(2)
  "100" keep.within-line="500" Some more text in |(3)
  the first nested inline More text after the    |(4)
  first nested inline                            |(5)

where the inner keep with higher force is fully satisfied, and the outer one is violated twice (breaks #2 and #3).

Right! The keep of 100 has to be violated twice anyway, so this is indeed a better result than what I suggested.

But maybe the algorithm could still prefer

  Some text with "auto" keep-constraint" Some    |(1)
  text with a keep.within-line constraint of     |(2)
  "100" keep.within-line="500" Some more text in |(3)
  the first nested inline More text after the    |(4)
  first nested inline                            |(5)

where the outer keep is violated thrice (breaks #1, #2 and #3).

Yep, and this is what should be avoided, if I interpret the definitions correctly. If there is a possible layout that causes only two violations, that is the better one.

So, maybe my sketched strategy would respect the keep priority (the inner keep will never be violated by a lower force one) but does not find the minimal set of violations. Or, at least, not if "minimal" means just fewer violations; if it could be interpreted as "fewer violations producing a good-looking result" it could be ok.

One last quick note concerning nesting: what if the inner inline had a *lower* force? feasible breaks in it should be first given a high penalty (to see if we can put everything together) and then a lower one (so the penalties should hold a nested chain of force values)?

Hmm... Indeed, easy enough if the parent inline has a keep of "always"

<fo:block>
  a
  <fo:inline keep-together.within-line="always">
  ...
    <fo:inline keep-together.within-line="100">
    ...
    </fo:inline>
  ...
  </fo:inline>
  ...

Here breaks in the inner inline never have to be considered. According to the consensus regarding the interpretation of "always" as absolutely forbidding breaks, the outer inline can never be broken (hence my suggestion to treat it as a single, unbreakable box in that case)
In the absolute worst case the above /should/ lead to:
- a very small first line containing only the block's initial 'a' (very, very high adjustment ratio) - overflow or clipping the content of the inline at the second line's ending


Slightly more complicated, and I can't say for certain what needs to happen here:

<fo:block>
  a
  <fo:inline keep-together.within-line="500">
  ...
    <fo:inline keep-together.within-line="100">
    ...
    </fo:inline>
  ...
  </fo:inline>
  ...

One might argue that by violating the inner keep, we would also violate the outer keep, and as such it makes no difference where the violation occurs... On the other hand, I wonder whether the use-case for such combinations would not precisely be to indicate to the formatter: "If violating a keep is unavoidable, then this is where it should preferably happen..."


Cheers

Andreas

Reply via email to