Fix#586.
For some reason I don't really understand, stripping trailing spaces that would
make the line too long can't be optimized when the space is at the end of the
block. Returning None instead of the index of the last letter should be
possible, but it breaks the rendering when the first letter of the next line
box starts with a character that doesn't allow line breaks after spaces (many
punctuation characters for example) and that doesn't allow line wrap.
This change shouldn't be harmful, as the removed code lines were just cleaning
the resume_at value without changing the logic of line breaking. I suppose that
there's a bug somewhere else.
This forces to use a copy when changes are needed. Internal mutable structures
have also been changed into immutable ones (i.e. lists have been turned into
tuples).
This change is a really useful first step to greatly optimize memory and time
needed to render large documents, as allows us to cache style dicts more
safely. It's been already done in StyleDict.inherit_from, with a ~5-10% memory
benefice.
The hack had been added to remove extra line breaks caused by floating point
errors when the shrink-to-fit width was coming from Pango and had a slightly
higher value when re-calculated in split_first_line.
The same problem appears when we split a line contaning inline-blocks (instead
of letters in the previous case), as the shrink-to-fit width may also inderctly
come from Pango and hit the same re-calculation floating point errors.
This commit moves the hack at a higher level, increasing the max width before
calling split_first_line when the line contains letters (same result as
before), but also before splitting lines containing inline-blocks.
Fix#467.
Traceback (most recent call last):
[...]
File "/app/env/lib/python3.5/site-packages/weasyprint/layout/inlines.py", line 718, in split_text_box
'Expected nothing or a preserved line break' % (between,))
AssertionError: Got '1,' between two lines. Expected nothing or a preserved line break
The Assertion Error can be triggered with following minimal test case
(Adobe's Source Sans Pro font must be installed):
<style type="text/css">
p {
font-family: 'Source Sans Pro';
font-size: 24pt;
width: 275pt;
overflow-wrap: break-word;
}
</style>
<p>W1D1,W1D7,W2D14,W3D21,W4D28</p>
With the Adobe Source Sans Font the pango line wrapping algorithm
sometimes produces sporadic results. The wrapping seems to be dependent
on the following text, so that a short text doesn't "fit" on a line, but
does if it is followed by more text. This can be worked around in the
split_first_line() function by computing the resume offset at a later
point, so it is in sync with the actual wrapping behaviour.
See https://bugzilla.gnome.org/show_bug.cgi?id=777093.
As Pango keeps the extra trailing spaces when it splits lines, we try to
add the next word of the second line to the first line without its
trailing spaces and see if it fits. If it doesn't, we have to update
resume_at as we have split the first line at a position that may be
different from what Pango did earlier.
Fix#389.