UNPKG

satie

Version:

A sheet music renderer for the web

278 lines (277 loc) 11.4 kB
/** * This file is part of Satie music engraver <https://github.com/jnetterf/satie>. * Copyright (C) Joshua Netterfield <joshua.ca> 2015 - present. * * Satie 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. * * Satie 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 Satie. If not, see <http://www.gnu.org/licenses/>. */ "use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var musicxml_interfaces_1 = require("musicxml-interfaces"); var react_1 = require("react"); var lodash_1 = require("lodash"); var invariant = require("invariant"); var private_views_bezier_1 = require("./private_views_bezier"); var private_views_glyph_1 = require("./private_views_glyph"); var private_smufl_1 = require("./private_smufl"); var implChord_articulationView_1 = require("./implChord_articulationView"); var $Bezier = react_1.createFactory(private_views_bezier_1.default); var $Glyph = react_1.createFactory(private_views_glyph_1.default); var $Articulation = react_1.createFactory(implChord_articulationView_1.default); /** * Notations are things that are attached to notes. */ var NotationView = (function (_super) { __extends(NotationView, _super); function NotationView() { return _super !== null && _super.apply(this, arguments) || this; } NotationView.prototype.render = function () { var _this = this; var model = this.props.spec; var nlayout = this.props.layout; var notehead = nlayout ? nlayout.model.noteheadGlyph[0] : "noteheadBlack"; var bbox = private_smufl_1.bboxes[notehead]; var noteheadCenter = 10 * (bbox[0] - bbox[2]) / 2; var originX = nlayout ? nlayout.model[0].defaultX + noteheadCenter : 0; var children = []; lodash_1.forEach(model.accidentalMarks, function (accidentalMark) { // TODO }); lodash_1.forEach(model.arpeggiates, function (arpeggiate) { // TODO }); lodash_1.forEach(model.articulations, function (articulation, idx) { children.push($Articulation({ articulation: articulation, key: "art" + idx, defaultX: nlayout ? nlayout.model[0].defaultX : 0, })); }); lodash_1.forEach(model.dynamics, function (dynamic) { // TODO }); lodash_1.forEach(model.fermatas, function (fermata, idx) { var direction = (fermata.type === musicxml_interfaces_1.UprightInverted.Inverted) ? "Below" : "Above"; var shape; switch (fermata.shape) { case musicxml_interfaces_1.NormalAngledSquare.Angled: shape = "fermataShort"; break; case musicxml_interfaces_1.NormalAngledSquare.Square: shape = "fermataLong"; break; case musicxml_interfaces_1.NormalAngledSquare.Normal: default: shape = "fermata"; break; } children.push($Glyph({ fill: "black", glyphName: "" + shape + direction, key: "fer" + idx, x: originX + fermata.defaultX + (fermata.relativeX || 0), y: (_this.context.originY || 0) - fermata.defaultY - (fermata.relativeY || 0) })); }); lodash_1.forEach(model.glissandos, function (glissando) { // TODO }); lodash_1.forEach(model.nonArpeggiates, function (nonArpeggiate) { // TODO }); lodash_1.forEach(model.ornaments, function (ornament) { // TODO }); lodash_1.forEach(model.slides, function (slide) { // TODO }); lodash_1.forEach(model.slurs, function (slur) { // TODO }); lodash_1.forEach(model.technicals, function (technical) { if (technical.tripleTongue) { } if (technical.toe) { } if (technical.hole) { } if (technical.hammerOn) { } if (technical.upBow) { var t = technical.upBow; children.push($Glyph({ fill: t.color || "black", glyphName: "stringsUpBow" + (t.placement === musicxml_interfaces_1.AboveBelow.Below ? "Reversed" : ""), key: "techUpBow", x: originX + t.defaultX + (t.relativeX || 0), y: (_this.context.originY || 0) - t.defaultY - (t.relativeY || 0), })); } if (technical.downBow) { var t = technical.downBow; children.push($Glyph({ fill: t.color || "black", glyphName: "stringsDownBow" + (t.placement === musicxml_interfaces_1.AboveBelow.Below ? "Reversed" : ""), key: "techDownBow", x: originX + t.defaultX + (t.relativeX || 0), y: (_this.context.originY || 0) - t.defaultY - (t.relativeY || 0), })); } if (technical.fret) { } if (technical.tap) { } if (technical.pullOff) { } if (technical.handbell) { } if (technical.bend) { } if (technical.thumbPosition) { } if (technical.stopped) { var t = technical.stopped; children.push($Glyph({ fill: t.color || "black", glyphName: "pluckedLeftHandPizzicato", key: "techStopped", x: originX + t.defaultX + (t.relativeX || 0), y: (_this.context.originY || 0) - t.defaultY - (t.relativeY || 0), })); } if (technical.pluck) { } if (technical.doubleTongue) { } if (technical.string) { } if (technical.openString) { var t = technical.openString; children.push($Glyph({ fill: t.color || "black", glyphName: "stringsHarmonic", key: "techOpenString", x: originX + t.defaultX + (t.relativeX || 0), y: (_this.context.originY || 0) - t.defaultY - (t.relativeY || 0), })); } if (technical.fingernails) { } if (technical.arrow) { } if (technical.harmonic) { } if (technical.heel) { } if (technical.otherTechnical) { } if (technical.snapPizzicato) { var t = technical.snapPizzicato; children.push($Glyph({ fill: t.color || "black", glyphName: "pluckedSnapPizzicato" + (t.placement === musicxml_interfaces_1.AboveBelow.Below ? "Below" : "Above"), key: "techSnapPizzicato", x: originX + t.defaultX + (t.relativeX || 0), y: (_this.context.originY || 0) - t.defaultY - (t.relativeY || 0), })); } if (technical.fingering) { } }); lodash_1.forEach(model.tieds, function (tied) { var tieTo = tied.satieTieTo; if (!tieTo) { return; } var bbox2 = private_smufl_1.bboxes[notehead]; var noteheadCenter2 = 10 * (bbox2[0] - bbox2[2]) / 2; var offset2 = noteheadCenter2 - noteheadCenter - 4; var defaultY = (_this.context.originY || 0) - (_this.props.defaultY || 0); var stem1 = _this.props.layout.satieStem; var stem2 = tieTo.satieStem; var dir = -1; if (stem1 && stem2 && stem1.direction === stem2.direction) { dir = -stem1.direction; } else if (stem1) { dir = -stem1.direction; } else if (stem2) { dir = -stem2.direction; } // This is the correct style only if space permits. See B.B. page 62. var x2 = originX - _this.props.layout.overrideX + tieTo.x + offset2; var x1 = originX; var y2 = defaultY - (dir === -1 ? -10 : 10); var y1 = defaultY - (dir === -1 ? -10 : 10); var x2mx1 = x2 - x1; var x1mx2 = -x2mx1; var relw = 3.2; // How "curved" it is var y1my2 = y1 - y2; var absw = -dir * 8.321228 / Math.max(1, (Math.abs(y1my2))); if ((y1my2 > 0 ? -1 : 1) * dir === 1) { absw = absw * 2; } invariant(!isNaN(x2), "Invalid x2 %s", x2); invariant(!isNaN(x1), "Invalid x1 %s", x1); invariant(!isNaN(y2), "Invalid y2 %s", y2); invariant(!isNaN(y1), "Invalid y1 %s", y1); invariant(!isNaN(dir), "Invalid dir %s", dir); invariant(!isNaN(x2mx1), "Invalid x2mx1 %s", x2mx1); invariant(!isNaN(x1mx2), "Invalid x1mx2 %s", x1mx2); invariant(!isNaN(relw), "Invalid relw %s", relw); invariant(!isNaN(y1my2), "Invalid y1my2 %s", y1my2); invariant(!isNaN(absw), "Invalid absw %s", absw); children.push($Bezier({ fill: "#000000", stroke: "#000000", strokeWidth: 1.2, x1: x2, x2: 0.28278198 / 1.23897534 * x1mx2 + x2, x3: 0.9561935 / 1.23897534 * x1mx2 + x2, x4: x1, x5: 0.28278198 / 1.23897534 * x2mx1 + x1, x6: 0.95619358 / 1.23897534 * x2mx1 + x1, y1: y2, y2: ((dir === -1 ? y1my2 : 0) + absw) + y2, y3: ((dir === -1 ? y1my2 : 0) + absw) + y2, y4: y1, y5: ((dir === -1 ? 0 : -y1my2) + absw + relw) + y1, y6: ((dir === -1 ? 0 : -y1my2) + absw + relw) + y1 })); }); lodash_1.forEach(model.tuplets, function (tuplet) { // TODO }); switch (children.length) { case 0: return null; case 1: return children[0]; default: return react_1.DOM.g(null, children); } }; return NotationView; }(react_1.Component)); NotationView.contextTypes = { originY: react_1.PropTypes.number, }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = NotationView; ;