songleaf.render¶
Render a song onto one dense page, with the lyrics as large as will fit.
A SheetLayout is one way of laying a song out: where the chords go
(chords), which lines share a row (packing), how many columns, and
whether sections, repeated lines and chord functions are shading-ed.
render_sheet() draws any layout, and render_dense_a4() is the v1
layout. A layout can be named by a spec that joins the options of
LAYOUT_OPTIONS with + (layout_named()), and
make_renderer() turns a spec into the (song, output) -> dict function
that the renderer= seam of songleaf.tools.sheet() takes.
Every layout finds the largest lyric font size at which the whole song fits on
one page (fit_font_size()), then draws it:
consecutive lines of a paragraph share a row, separated by a light
/: as many as fit (packing="greedy"), or breaking where the lyrics break ("structured": between couplets and quatrains, not inside a rhyming pair or a repeat; seesongleaf.packing). A blank line or a new section starts a new row, and a line too long for its column wraps at a space (inside a word only when a single word is wider than the column);chords="over": chords ride on their lyric row, smaller and in a lighter colour, overlapping the letters instead of taking a line of their own. A chord starts over the syllable it lands on, and atiming="before"chord ends there.DenseStyle.chord_risesets how deep they overlap: the tops of the letters by default, the words themselves with theoverlapoption;chords="inline": chords sit in the lyric line itself, in a lighter colour, right before the syllable they land on. A chord that sounds before its syllable is preceded by a small marker (DenseStyle.before_marker);columns=2: the rows flow down two columns, under a full-width heading;shading: chorus-like sections get a light warm band and pre-chorus or bridge sections a light cool one, lines sung earlier in the song are set in dark grey, and chords are coloured by their function in the key estimated from the chords (songleaf.harmony): the tonic darker, the key’s other chords in the usual blue, chords outside the key in a warm accent;section labels are small grey prefixes (
V1,Ch) on a section’s first row;only a song that cannot fit at
min_font_sizespills onto more pages.
Text is set in DejaVu Sans, a TrueType font bundled in songleaf/data/fonts
(Bitstream Vera licence, which allows embedding and redistribution; the licence
text is beside the files) and embedded in each PDF. It covers Latin Extended
(Turkish ş ğ ı), Greek, Cyrillic and more, where reportlab’s built-in Helvetica
stops at its single-byte cp1252 encoding (songleaf#9). If a bundled file cannot
be loaded, the matching Helvetica is used instead, with a warning. Emoji are
not covered by either.
>>> short_label("Verse 1"), short_label("Pre-Chorus"), short_label("Coda")
('V1', 'Pre', 'Coda')
>>> layout = layout_named("inline+two-column")
>>> layout.chords, layout.columns, layout.packing
('inline', 2, 'greedy')
Module Attributes
Page margin in points (5 mm), about the least a printer leaves blank anyway. |
|
Where the bundled TrueType fonts live (with their licence). |
|
name -> (file in |
|
The chord placements a |
|
The line packers a |
|
What each option of a layout spec changes, from the v1 layout ( |
Functions
|
The largest lyric font size at which |
|
The layout of a spec: options of |
|
The one spelling of a layout spec, for names: |
|
A |
|
|
|
Render |
|
Render |
|
|
|
A compact section label: |
|
The reportlab font name to set |
Classes
|
Where a piece's chords go relative to its lyrics: the strategy behind |
|
Typography of the dense layouts. |
|
Chords in the lyric line, right before their syllable; a chord-only line is a row of chords. |
Chords above their syllables, smaller and lighter, overlapping the lyric row by |
|
|
One way to lay a song out on a page. |
- songleaf.render.BUNDLED_FONTS: dict[str, tuple[str, str]] = {'DejaVuSans': ('DejaVuSans.ttf', 'Helvetica'), 'DejaVuSans-Bold': ('DejaVuSans-Bold.ttf', 'Helvetica-Bold')}¶
name -> (file in
FONTS_DIR, standard font used when that file cannot be loaded). Any other name is passed to reportlab as is: one of its standard fonts, or a TTF the caller registered withpdfmetrics.- Type:
Fonts songleaf ships
- songleaf.render.CHORD_PLACEMENTS: dict[str, ChordPlacement] = {'inline': InlineChords(snap_to_syllables=True), 'over': OverChords()}¶
The chord placements a
SheetLayoutcan name.
- class songleaf.render.ChordPlacement(*args, **kwargs)[source]¶
Bases:
ProtocolWhere a piece’s chords go relative to its lyrics: the strategy behind
SheetLayout.chords.- extent(piece, size, style)[source]¶
The width the piece takes, chords included (its label excluded).
- Return type:
- songleaf.render.DFLT_MARGIN = 14.0¶
Page margin in points (5 mm), about the least a printer leaves blank anyway.
- class songleaf.render.DenseStyle(lyric_font='DejaVuSans', chord_font='DejaVuSans-Bold', label_font='DejaVuSans-Bold', title_font='DejaVuSans-Bold', lyric_color='#000000', chord_color='#3b73c4', label_color='#8c8c8c', separator_color='#a6a6a6', title_color='#595959', chord_scale=0.62, label_scale=0.5, title_scale=0.6, chord_rise=0.56, chord_halo='', chord_halo_width=0.16, ascent=0.72, descent=0.21, row_gap=0.06, paragraph_gap=0.3, separator=' / ', chord_gap=0.3, bare_chord_gap=0.9, label_gap=0.4, inline_chord_scale=0.7, inline_chord_rise=0.2, inline_chord_pad=0.15, before_marker='‹', column_gap=0.8, column_rule_color='#d9d9d9', chorus_shade='#f3efe4', bridge_shade='#e8eef6', band_pad=0.12, repeat_color='#4d4d4d', tonic_chord_color='#1c4a91', outside_chord_color='#c0602a', staff_space=0.4, snippet_color='#333333')[source]¶
Bases:
objectTypography of the dense layouts. Lengths are fractions of the lyric font size.
- songleaf.render.FONTS_DIR = PosixPath('/home/runner/work/songleaf/songleaf/songleaf/data/fonts')¶
Where the bundled TrueType fonts live (with their licence).
- class songleaf.render.InlineChords(*, snap_to_syllables=True)[source]¶
Bases:
objectChords in the lyric line, right before their syllable; a chord-only line is a row of chords.
- Parameters:
snap_to_syllables (
bool) – Show a chord that lands inside a word at the word’s or the syllable’s start (see_syllable_start()); the song’s annotations are not changed.
- songleaf.render.LAYOUT_OPTIONS: dict[str, dict] = {'dense': {}, 'guitar': {'diagrams': 'guitar'}, 'inline': {'chords': 'inline'}, 'overlap': {'chords': 'over', 'style': {'chord_halo': '#ffffff', 'chord_rise': 0.42}}, 'packed': {'packing': 'structured'}, 'piano': {'diagrams': 'piano'}, 'score': {'score': True}, 'shaded': {'shading': True}, 'two-column': {'columns': 2}}¶
What each option of a layout spec changes, from the v1 layout (
dense).
- class songleaf.render.OverChords[source]¶
Bases:
objectChords above their syllables, smaller and lighter, overlapping the lyric row by
chord_rise.
- songleaf.render.PACKERS: dict[str, Callable] = {'greedy': <function pack_greedy>, 'structured': <function pack_structured>}¶
The line packers a
SheetLayoutcan name (seesongleaf.packing).
- class songleaf.render.SheetLayout(chords='over', packing='greedy', columns=1, shading=False, diagrams=None, style=DenseStyle(), score=False)[source]¶
Bases:
objectOne way to lay a song out on a page.
- Parameters:
chords (
str|ChordPlacement) – Where chords go:"over"(overlapping the lyric row) or"inline"(in the line, before their syllable), or anyChordPlacement.packing (
str|Callable) – Which lines share a row:"greedy"or"structured", or any packer with the signature ofsongleaf.packing.pack_greedy().columns (
int) – Columns per page.shading (
bool) – Shade sections, repeated lines and chord functions.diagrams (
str|None) –"piano"or"guitar"draws the song’s chords as a strip of diagrams at the foot of the first page (songleaf.diagrams); the lyrics shrink to make room.None: no diagrams.score (
bool) – Draw the song’s score snippet, if its provider has one, above the line it belongs to (songleaf.snippets); the lyrics shrink to make room.style (
DenseStyle) – Typography and colours.
- property placement: ChordPlacement¶
The chord placement strategy.
- songleaf.render.fit_font_size(song, *, page_size='A4', margin=14.0, style=None, layout=None, min_font_size=6.0, max_font_size=72.0, precision=0.05, snippets=None)[source]¶
The largest lyric font size at which
songfits one page inlayout(default: v1’s).style, if given, replaces the layout’s style. Returnsmin_font_sizeif even that does not fit (the song then needs more pages).snippetsis the score-snippet provider of ascorelayout (defaultsongleaf.snippets.default_provider()’s).- Return type:
- songleaf.render.layout_named(spec, *, style=None)[source]¶
The layout of a spec: options of
LAYOUT_OPTIONSjoined by+("inline+two-column").Options apply in order, over the v1 layout and
style(defaultDenseStyle).- Return type:
- songleaf.render.layout_spec(spec)[source]¶
The one spelling of a layout spec, for names:
"Dense"->"dense".>>> layout_spec("2col + INLINE"), layout_spec("dense+"), layout_spec("inline+2col+inline") ('two-column+inline', 'dense', 'two-column+inline')
- Return type:
- songleaf.render.make_renderer(layout='dense', **render_options)[source]¶
A
(song, output) -> dictrenderer forlayout, the shapesheet’srenderer=takes.render_optionsare passed torender_sheet()(page_size,margin, …). A bad spec fails here, not at render time.>>> make_renderer("packed+shaded").keywords["layout"].packing 'structured'
- Return type:
- songleaf.render.on_paper(color, alpha=1.0, *, paper='#ffffff')[source]¶
colorat opacityalphaoverpaper, as one opaque colour: what ink at that opacity shows.>>> on_paper("#000000", 0.5), on_paper("#3b73c4"), on_paper("#ff0000", 0) ('#808080', '#3b73c4', '#ffffff')
- Return type:
- songleaf.render.render_dense_a4(song, output, *, page_size='A4', margin=14.0, style=None, min_font_size=6.0, max_font_size=72.0)[source]¶
Render
songin the v1 layout as a PDF tooutput(a path or a binary file object).The same as
render_sheet()withlayout="dense". Returns{"path", "font_size", "pages", "rows"};pathisNonewhenoutputis a file object.- Return type:
- songleaf.render.render_sheet(song, output, *, layout='dense', page_size='A4', margin=14.0, min_font_size=6.0, max_font_size=72.0, scale=1.0, snippets=None)[source]¶
Render
songinlayout(aSheetLayoutor a spec) as a PDF tooutput.The lyric font size is the largest that fits the song on one page, times
scale:1fills the page,0.8leaves room,1.2is larger type that runs onto a second page. It never goes pastmax_font_size.snippetsprovides ascorelayout’s snippet:song -> ScoreSnippet | None(defaultsongleaf.snippets.default_provider()’s).outputis a path or a binary file object. Returns{"path", "font_size", "pages", "rows"};pathisNonewhenoutputis a file object.- Return type:
- songleaf.render.section_family(label)[source]¶
"chorus"for a chorus or refrain,"bridge"for a pre-chorus or bridge, else"".>>> section_family("Pre-Chorus"), section_family("Refrão 2"), section_family("Verse") ('bridge', 'chorus', '')
- Return type:
- songleaf.render.short_label(label)[source]¶
A compact section label:
"Verse 1"->"V1","Chorus x2"->"Ch x2".- Return type:
- songleaf.render.usable_font(name)[source]¶
The reportlab font name to set
namein, registering a bundled TTF once.A name in
BUNDLED_FONTSis registered fromFONTS_DIRon first use; if its file cannot be loaded, the paired standard font is returned and a warning says so. Any other name is returned unchanged.- Return type: