Skip to content

Commit 4dfd05f

Browse files
committed
Don’t iterate over all lines when trying to report footnotes
It can be awfully long, and we only need to know if we have enough lines to please the "widows" property.
1 parent 0688797 commit 4dfd05f

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

weasyprint/layout/block.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ def _out_of_flow_layout(context, box, index, child, new_children,
301301
return stop, resume_at, new_child, out_of_flow_resume_at
302302

303303

304-
def _break_line(context, box, line, new_children, next_lines, page_is_empty, index,
304+
def _break_line(context, box, line, new_children, needed, page_is_empty, index,
305305
skip_stack, resume_at, absolute_boxes, fixed_boxes):
306306
"""Break line where allowed by orphans and widows.
307307
@@ -316,7 +316,6 @@ def _break_line(context, box, line, new_children, next_lines, page_is_empty, ind
316316
return True, False, resume_at
317317
# How many lines we need on the next page to satisfy widows
318318
# -1 for the current line.
319-
needed = max(box.style['widows'] - 1 - next_lines, 0)
320319
if needed > over_orphans and not page_is_empty:
321320
# Total number of lines < orphans + widows
322321
remove_placeholders(context, line.children, absolute_boxes, fixed_boxes)
@@ -377,15 +376,21 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
377376
# If we couldn’t break the line before but can break now, first try to
378377
# report footnotes and see if we don’t overflow.
379378
could_break_before = can_break_now = True
380-
next_lines = len(tuple(lines_iterator))
379+
needed = box.style['widows'] - 1
380+
for _ in lines_iterator:
381+
needed -= 1
382+
# Don’t iterate over all lines as it can be long.
383+
if needed == -1:
384+
break
381385
if len(new_children) + 1 < box.style['orphans']:
382386
can_break_now = False
383-
elif next_lines < box.style['widows']:
387+
elif needed >= 0:
384388
can_break_now = False
385389
if len(new_children) < box.style['orphans']:
386390
could_break_before = False
387-
elif next_lines + 1 < box.style['widows']:
391+
elif needed > 0:
388392
could_break_before = False
393+
needed = max(0, needed)
389394
report = not context.in_column and can_break_now and not could_break_before
390395
reported_footnotes = 0
391396
while report and context.current_page_footnotes:
@@ -397,9 +402,8 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
397402
break
398403
else:
399404
abort, stop, resume_at = _break_line(
400-
context, box, line, new_children, next_lines,
401-
page_is_empty, index, skip_stack, resume_at, absolute_boxes,
402-
fixed_boxes)
405+
context, box, line, new_children, needed, page_is_empty, index,
406+
skip_stack, resume_at, absolute_boxes, fixed_boxes)
403407

404408
# Revert reported footnotes, as they’ve been reported starting from the last
405409
# one.
@@ -414,8 +418,7 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
414418
# "When an unforced page break occurs here, both the adjoining
415419
# ‘margin-top’ and ‘margin-bottom’ are set to zero."
416420
# See issue #115.
417-
elif page_is_empty and context.overflows_page(
418-
bottom_space, new_position_y):
421+
elif page_is_empty and context.overflows_page(bottom_space, new_position_y):
419422
# Remove the top border when a page is empty and the box is
420423
# too high to be drawn in one page
421424
new_position_y -= box.margin_top
@@ -433,8 +436,7 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
433436
overflow = (
434437
overflow or
435438
context.reported_footnotes or
436-
context.overflows_page(
437-
bottom_space, new_position_y + offset_y))
439+
context.overflows_page(bottom_space, new_position_y + offset_y))
438440
if overflow:
439441
context.report_footnote(footnote)
440442
# If we've put other content on this page, then we may want
@@ -443,11 +445,15 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
443445
# even try.
444446
if new_children or not page_is_empty:
445447
if footnote.style['footnote_policy'] == 'line':
446-
next_lines = len(tuple(lines_iterator))
448+
if needed := box.style['widows'] - 1:
449+
for _ in lines_iterator:
450+
needed -= 1
451+
# Don’t iterate over all lines as it can be long.
452+
if needed == 0:
453+
break
447454
abort, stop, resume_at = _break_line(
448-
context, box, line, new_children,
449-
next_lines, page_is_empty, index,
450-
skip_stack, resume_at, absolute_boxes,
455+
context, box, line, new_children, needed, page_is_empty,
456+
index, skip_stack, resume_at, absolute_boxes,
451457
fixed_boxes)
452458
break_linebox = True
453459
break

0 commit comments

Comments
 (0)