UNPKG

satie

Version:

A sheet music renderer for the web

159 lines (138 loc) 5.29 kB
/** * @source: https://github.com/jnetterf/satie/ * * @license * (C) Josh Netterfield <joshua@nettek.ca> 2015. * Part of the Satie music engraver <https://github.com/jnetterf/satie>. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /** * @file Renders a tuplet outside of a beam. Unbeamed tuplets are created * by the beam postprocessor, since they share many similaraties. */ // Note that we use notehadBlack regardless of the notehead. // This keeps spacing consistent, even in beam groups with rests. import {AboveBelow} from "musicxml-interfaces"; import {createFactory, Component, DOM, PropTypes} from "react"; import {first, last} from "lodash"; import {bravura, getFontOffset} from "./private_smufl"; import TupletNumberView from "./implChord_tupletNumberView"; import {IBeamLayout} from "./implChord_beamLayout"; const $TupletNumberView = createFactory(TupletNumberView); export interface IProps { key?: string | number; stroke: string; stemWidth: number; layout: IBeamLayout; } export default class UnbeamedTuplet extends Component<IProps, void> { static contextTypes = { originY: PropTypes.number.isRequired } as any; context: { originY: number; }; render(): any { let {stroke, layout} = this.props; let {tuplet, x} = layout; let {placement} = tuplet; let yOffset = placement === AboveBelow.Above ? 8 : -8; let isSingleNote = x.length === 1; let x1 = this._getX1(); let x2 = this._getX2(); let y1 = this._getY1(1); let y2 = this._getY2(1); let y1Low = this._getY1(0); let y2Low = this._getY2(0); let y1Near = placement === AboveBelow.Below ? y1 : y1Low; let y1Far = placement === AboveBelow.Below ? y1Low : y1; let y2Near = placement === AboveBelow.Below ? y2 : y2Low; let y2Far = placement === AboveBelow.Below ? y2Low : y2; return DOM.g(null, !isSingleNote && DOM.polygon({ fill: stroke, key: "p1", points: x1 + "," + y1Low + " " + x2 + "," + y2Low + " " + x2 + "," + y2 + " " + x1 + "," + y1, stroke: stroke, strokeWidth: 0 }), !isSingleNote && DOM.line({ fill: stroke, key: "p2", stroke, strokeWidth: bravura.engravingDefaults.tupletBracketThickness * 10, x1: x1 + 0.5, x2: x1 + 0.5, y1: y1Near, y2: y1Far + yOffset }), !isSingleNote && DOM.line({ fill: this.props.stroke, key: "p3", stroke, strokeWidth: bravura.engravingDefaults.tupletBracketThickness * 10, x1: x2 - 0.5, x2: x2 - 0.5, y1: y2Near, y2: y2Far + yOffset }), $TupletNumberView({tuplet, x1, x2, y1, y2}) ); } /** * Offset because the note-head has a non-zero width. */ getLineXOffset() { return this.direction() * -this.props.stemWidth / 2; } /** * 1 if the notes go up, * -1 if the notes go down. */ direction() { return this.props.layout.tuplet.placement === AboveBelow.Above ? 1 : -1; } private _withXOffset(x: number) { return x + getFontOffset("noteheadBlack", this.direction())[0] * 10 + this.getLineXOffset(); } private _getX1() { let {x} = this.props.layout; return this._withXOffset(first(x)) - 4; } private _getX2() { let {x} = this.props.layout; return this._withXOffset(last(x)) + 4; } private _getY1(incl: number) { let {originY} = this.context; let {layout} = this.props; let {y1} = layout; return originY - y1 - this.direction() * getFontOffset("noteheadBlack", this.direction())[1] * 10 - (incl || 0) * (bravura.engravingDefaults.tupletBracketThickness * 10); } private _getY2(incl: number) { let {originY} = this.context; let {layout} = this.props; let {y2} = layout; return originY - y2 - this.direction() * getFontOffset("noteheadBlack", this.direction())[1] * 10 - (incl || 0) * (bravura.engravingDefaults.tupletBracketThickness * 10); } };