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