1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-10-04 07:57:52 +03:00

Fix line break when breaks occur between a nbsp and an inline block

This commit:

- fixes the trailing space detection, by handling all trailing spacing
  characters that could be ignored by Pango’s line break algorithm;
- tries harder to break waiting children when a line break occurs in an
  inline block that can’t be separated from the previous one.

Fix #1562.
This commit is contained in:
Guillaume Ayoub 2022-02-08 12:16:10 +01:00
parent e4a35cbf88
commit 562a2499a1
2 changed files with 75 additions and 46 deletions

View File

@ -72,6 +72,26 @@ def test_line_breaking_rtl():
'ايبسوم دولا')
@assert_no_logs
def test_line_breaking_nbsp():
# Test regression: https://github.com/Kozea/WeasyPrint/issues/1561
page, = render_pages('''
<style>
@font-face {src: url(weasyprint.otf); font-family: weasyprint}
body { font-family: weasyprint; width: 7.5em }
</style>
<body>a <span>b</span> c d&nbsp;<span>ef
''')
html, = page.children
body, = html.children
line_1, line_2 = body.children
assert line_1.children[0].text == 'a '
assert line_1.children[1].children[0].text == 'b'
assert line_1.children[2].text == ' c'
assert line_2.children[0].text == 'd\xa0'
assert line_2.children[1].children[0].text == 'ef'
@assert_no_logs
def test_text_dimension():
string = 'This is a text for test. This is a test for text.py'

View File

@ -609,16 +609,25 @@ def _break_waiting_children(context, box, max_x, bottom_space,
waiting_children_copy = waiting_children.copy()
while waiting_children_copy:
child_index, child = waiting_children_copy.pop()
if child.is_in_normal_flow() and can_break_inside(child):
if not child.is_in_normal_flow() or not can_break_inside(child):
continue
# Break the waiting child at its last possible breaking point.
# TODO: The dirty solution chosen here is to decrease the
# actual size by 1 and render the waiting child again with this
# constraint. We may find a better way.
max_x = child.position_x + child.margin_width() - 1
while max_x > child.position_x:
new_child, child_resume_at, _, _, _, _ = split_inline_level(
context, child, child.position_x, max_x, bottom_space,
None, box, absolute_boxes, fixed_boxes, line_placeholders,
waiting_floats, line_children)
if child_resume_at:
break
max_x -= 1
else:
# No line break found
continue
children.extend(waiting_children_copy)
if new_child is None:
@ -785,10 +794,10 @@ def split_inline_box(context, box, position_x, max_x, bottom_space, skip_stack,
else:
if isinstance(box, boxes.LineBox):
line_children.append((index, new_child))
# TODO: we should try to find a better condition here.
trailing_whitespace = (
isinstance(new_child, boxes.TextBox) and
not new_child.text.strip())
new_child.text and
unicodedata.category(new_child.text[-1]) == 'Zs')
new_position_x = new_child.position_x + new_child.margin_width()
if new_position_x > max_x and not trailing_whitespace: