Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDF page break threshold for Slugs & Character Names #16

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion screenplain/export/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
top_margin = 1 * inch
bottom_margin = page_height - top_margin - frame_height

# If the current page has below this many pixels remaining,
# break before starting a new scene / dialogue
pixels_threshold_page_break = 100

character_width = 1.0 / 10 * inch

default_style = ParagraphStyle(
Expand Down Expand Up @@ -142,7 +146,14 @@ def add_paragraph(story, para, style):
story.append(Paragraph(line.to_html(), style))


def add_slug(story, para, style):
protect_page_break(story)
for line in para.lines:
story.append(Paragraph(line.to_html(), style))


def add_dialog(story, dialog):
protect_page_break(story)
story.append(Paragraph(dialog.character.to_html(), character_style))
for parenthetical, line in dialog.blocks:
if parenthetical:
Expand All @@ -157,6 +168,10 @@ def add_dual_dialog(story, dual):
add_dialog(story, dual.right)


def protect_page_break(story):
story.append(platypus.CondPageBreak(pixels_threshold_page_break))


def get_title_page_story(screenplay):
"""Get Platypus flowables for the title page

Expand Down Expand Up @@ -236,7 +251,7 @@ def to_pdf(screenplay, output_filename, template_constructor=DocTemplate):
centered_action_style if para.centered else action_style
)
elif isinstance(para, Slug):
add_paragraph(story, para, slug_style)
add_slug(story, para, slug_style)
elif isinstance(para, Transition):
add_paragraph(story, para, transition_style)
elif isinstance(para, types.PageBreak):
Expand Down
58 changes: 58 additions & 0 deletions tests/files/awkward-page-breaks.fountain
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
INT. SOMEWHERE - DAY

Stuff happens.

So much stuff happens, that this scene takes up exactly one page.

And when we export this as a PDF with 55 "lines per page" and 61 "characters per line" (unless we protect against it) the next scene heading will end up being orphaned at the bottom of this page, with nothing below it. The contents of the next scene will appear on the following page, without any heading.

ALPHA
Bravo.

CHARLIE
Delta.

ECHO
Foxtrot.

GOLF
Hotel.

INDIA
Juliet.

KILO
Lima.

MIKE
November.

OSCAR
Papa.

QUEBEC
Romeo.

SIERRA
Tango.

UMBRELLA
Victor.

Whiskey X-ray. Yankee Zulu. Whiskey X-ray. Yankee Zulu.Whiskey X-ray. Yankee Zulu.Whiskey X-ray. Yankee Zulu.Whiskey X-ray. Yankee Zulu.Whiskey X-ray.

INT. SOMEWHERE ELSE, TO BE CERTAIN - NIGHT

Exported as a PDF with 55 "lines per page" and 61 "characters per line", this scene will appear at the top of a page, with no heading above it.

ALPHA
Bravo.

CHARLIE
Delta.

ECHO
Foxtrot.

GOLF
Hotel.
24 changes: 24 additions & 0 deletions tests/pdf_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2011 Martin Vilcans
# Licensed under the MIT license:
# http://www.opensource.org/licenses/mit-license.php

from testcompat import TestCase
from StringIO import StringIO

from screenplain.export.pdf import to_pdf
from screenplain.richstring import plain, bold, italic


class OutputTests(TestCase):

def setUp(self):
self.out = StringIO()
# TODO: figure out how to test PDF export

def test_scene_heading_page_break_threshold(self):
self.assertEqual(1, 1)
# TODO: test PDF export should not break heading from scene

def test_character_name_page_break_threshold(self):
self.assertEqual(1, 1)
# TODO: test PDF export should not break character name from dialog