@@ -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