Module: Idml::Render::Renderers::KeepPolicy
- Defined in:
- lib/idml/render/renderers/keep_policy.rb
Overview
Paragraph deferral policy (keep options + forced breaks): decides whether a paragraph moves wholly to the next frame/column instead of being split. Honors StartParagraph forced breaks, KeepAllLinesTogether, the KeepFirstLines / KeepLastLines partial windows (measured-line-count approximation), and KeepWithNext. Pure predicates over the paragraph chain state and frame geometry — no canvas, no emission (MECE: TextFrameRenderer owns flow and emission; FrameMetrics owns frame positioning).
Constant Summary collapse
- BREAK_MODES =
%w[ NextPage NextColumn NextFrame NextOddPage NextEvenPage ].freeze
Class Method Summary collapse
- .first_window_break?(paragraph, lines_fit) ⇒ Boolean
-
.keep_all_lines_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) ⇒ Boolean
KeepAllLinesTogether: defer when the paragraph cannot fully fit the remaining space.
-
.keep_windows_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) ⇒ Boolean
Partial keep windows, approximated by measured line counts: KeepFirstLines defers when fewer than N lines fit; KeepLastLines defers when the overflow tail for the next frame would strand fewer than N lines.
-
.keep_with_next_break?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit) ⇒ Boolean
KeepWithNext: this paragraph defers when the next paragraph is forced to the next frame, or when the next paragraph's first line would not fit after this one.
- .keepable_pair?(paragraph, next_paragraph) ⇒ Boolean
- .last_window_break?(paragraph, lines_fit, height, leading) ⇒ Boolean
- .paragraph_block_height(paragraph, layout_frame, font) ⇒ Object
-
.paragraph_break?(paragraph) ⇒ Boolean
True when the paragraph requests a forced break to the next frame/column (StartParagraph).
-
.paragraph_deferred?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit, placed_any) ⇒ Boolean
True when the paragraph should move wholly to the next frame: a StartParagraph forced break, or a keep rule that the remaining space violates (never for the frame's first paragraph, so progress is always made).
Class Method Details
.first_window_break?(paragraph, lines_fit) ⇒ Boolean
69 70 71 72 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 69 def first_window_break?(paragraph, lines_fit) paragraph.keep_first_lines && lines_fit < paragraph.keep_first_lines end |
.keep_all_lines_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) ⇒ Boolean
KeepAllLinesTogether: defer when the paragraph cannot fully fit the remaining space.
43 44 45 46 47 48 49 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 43 def keep_all_lines_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) return false unless paragraph.keep_all_lines_together height = paragraph_block_height(paragraph, layout_frame, font) (cursor_y - height) < bottom_limit end |
.keep_windows_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) ⇒ Boolean
Partial keep windows, approximated by measured line counts: KeepFirstLines defers when fewer than N lines fit; KeepLastLines defers when the overflow tail for the next frame would strand fewer than N lines.
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 55 def keep_windows_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) return false unless paragraph.keep_first_lines || paragraph.keep_last_lines height = paragraph_block_height(paragraph, layout_frame, font) return false if (cursor_y - height) >= bottom_limit leading = FrameMetrics.leading_for(paragraph) lines_fit = [((cursor_y - bottom_limit) / leading).floor, 0].max first_window_break?(paragraph, lines_fit) || last_window_break?(paragraph, lines_fit, height, leading) end |
.keep_with_next_break?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit) ⇒ Boolean
KeepWithNext: this paragraph defers when the next paragraph is forced to the next frame, or when the next paragraph's first line would not fit after this one.
85 86 87 88 89 90 91 92 93 94 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 85 def keep_with_next_break?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit) return false unless keepable_pair?(paragraph, next_paragraph) return true if paragraph_break?(next_paragraph) height = paragraph_block_height(paragraph, layout_frame, font) (cursor_y - height - FrameMetrics.leading_for(next_paragraph)) < bottom_limit end |
.keepable_pair?(paragraph, next_paragraph) ⇒ Boolean
96 97 98 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 96 def keepable_pair?(paragraph, next_paragraph) !paragraph.keep_with_next.nil? && !next_paragraph.nil? end |
.last_window_break?(paragraph, lines_fit, height, leading) ⇒ Boolean
74 75 76 77 78 79 80 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 74 def last_window_break?(paragraph, lines_fit, height, leading) return false unless paragraph.keep_last_lines total_lines = [(height / leading).ceil, 1].max lines_fit.positive? && (total_lines - lines_fit) < paragraph.keep_last_lines end |
.paragraph_block_height(paragraph, layout_frame, font) ⇒ Object
107 108 109 110 111 112 113 114 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 107 def paragraph_block_height(paragraph, layout_frame, font) wrap_width = TextEngine::VerticalLayout.wrap_width( layout_frame, paragraph.right_indent || 0 ) TextEngine::Measurement.paragraph_height( paragraph, font, wrap_width ) end |
.paragraph_break?(paragraph) ⇒ Boolean
True when the paragraph requests a forced break to the next frame/column (StartParagraph). All break flavors act at frame/column granularity.
103 104 105 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 103 def paragraph_break?(paragraph) BREAK_MODES.include?(paragraph.start_paragraph) end |
.paragraph_deferred?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit, placed_any) ⇒ Boolean
True when the paragraph should move wholly to the next frame: a StartParagraph forced break, or a keep rule that the remaining space violates (never for the frame's first paragraph, so progress is always made).
26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/idml/render/renderers/keep_policy.rb', line 26 def paragraph_deferred?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit, placed_any) return true if paragraph_break?(paragraph) && placed_any return false unless placed_any return true if keep_with_next_break?(paragraph, next_paragraph, layout_frame, font, cursor_y, bottom_limit) keep_all_lines_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) || keep_windows_break?(paragraph, layout_frame, font, cursor_y, bottom_limit) end |