from __future__ import annotations import generator.engraving.types import generator.model def column(index, event, anchors, fonts, style): if not index.staff.get('tablature') or not anchors: return [] x = min(a.x for a in anchors) sources = (event.value['id'],) if not event.value['pitches']: anchor = anchors[0] return [fonts.glyph('noteheadSlashHorizontalEnds', x, -2 * style.tab_space, style.space, 'tab_slash', sources)] if anchor.fragment.kind == 'slash' else [] result = [] for anchor in anchors: tone = index.tones[anchor.source][1] tab = tone['tablature'] y = -(6 - tab['string']) * style.tab_space result.append(fonts.text(str(tab['fret']), x, y + 4, style.tab_font_size, 'tab', (event.value['id'], tone['id']))) return result def staff(index, items, start, end, left, right, fonts, style): notation = [p for p in items if not p.role.startswith('tab')] numbers = [p for p in items if p.role.startswith('tab')] if not index.staff.get('tablature'): return items offset = generator.engraving.types.bounds(notation).bottom + style.tab_gap + 5 * style.tab_space numbers = [p.moved(0, offset) for p in numbers] drawing = list(numbers) drawing.append(fonts.text('TAB', 0, offset - 2 * style.tab_space, style.tab_font_size, 'tab_label', ())) for string in range(1, 7): y = offset - (6 - string) * style.tab_space cuts = sorted((max(0, p.box.left - 2), min(right, p.box.right + 2)) for p in numbers if p.box.top <= y <= p.box.bottom) cursor = 0 for a, b in cuts + [(right, right)]: if a > cursor: drawing.append(generator.engraving.types.line('tab_staff', (), ((cursor, y), (a, y)), style.space * 0.13)) cursor = max(cursor, b) for bar in (p for p in notation if p.role == 'barline'): drawing.append(generator.engraving.types.line('tab_barline', bar.sources, tuple((x, offset + y * 5 * style.tab_space / (4 * style.space)) for x, y in bar.points), bar.thickness)) by_source = {source: p for p in numbers if p.role == 'tab' for source in p.sources[1:]} def tie(identifier, tone, x1, x2): y = offset - (6 - tone['tablature']['string']) * style.tab_space + 6 if x2 > x1: drawing.append(generator.engraving.types.curve('tab_tie', (identifier,), ((x1, y), (x1 + (x2 - x1) / 3, y + 5), (x2 - (x2 - x1) / 3, y + 5), (x2, y)))) for identifier, (event, tone) in index.tones.items(): first = by_source.get(identifier) finish = event.start + generator.model.fraction(tone['duration']) if first and event.start < start < finish: tie(identifier, tone, left, first.box.left - 2) if first and finish > end: tie(identifier, tone, first.box.right + 2, right) elif target := tone.get('tie_to'): destination = index.tones[target][0].start if event.start >= end or destination < start: continue last = by_source.get(target) if first or last: tie(identifier, tone, first.box.right + 2 if first else left, last.box.left - 2 if last else right) return notation + drawing