UNPKG

satie

Version:

A sheet music renderer for the web

234 lines (217 loc) 8.2 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/>. */ /** * @file part of Satie test suite */ import {IRefreshMeasureOpts, refreshMeasure, layoutMeasure, RefreshMode} from "../engine_processors_measure"; import {getApproximateMeasureWidth} from "../engine_processors_layout"; import {expect} from "chai"; import {Type} from "../document"; import {normalizeDivisionsInPlace} from "../engine_divisions"; import {createFakeVoiceSegment, createFakeStaffSegment, fakeFactory} from "./etestutil"; describe("[engine/measureProcessor.ts]", function() { describe("reduce", function() { it("can lay out multiple voices", function() { let segments = [ createFakeStaffSegment(4, 4, 1), // 00001111 createFakeVoiceSegment(2, 6, 1), // 00111111 createFakeVoiceSegment(1, 7, 2) // 01111111 ]; segments[0].owner = 1; segments[0].part = "P1"; segments[1].owner = 1; segments[1].part = "P1"; segments[2].owner = 2; segments[2].part = "P1"; normalizeDivisionsInPlace(fakeFactory, segments); // test without alignment let opts: IRefreshMeasureOpts = { document: { __fakeDocument: true } as any, preview: false, print: null, fixup: null, lineBarOnLine: 0, lineCount: 1, lineIndex: 0, lineShortest: 1, lineTotalBarsOnLine: 1, header: null, measure: { idx: 0, uuid: 777, number: "1", parts: {}, version: 0, }, measureX: 100, segments: segments, noAlign: true, factory: fakeFactory, mode: RefreshMode.RefreshLayout, attributes: {"P1": []}, singleLineMode: false, }; let layout = refreshMeasure(opts).elements; expect(layout[0].length).to.equal(2); expect(layout[0][0].x).to.equal(100, "without merging"); // Occurs after division 1 or 2, so add the end of the measure expect(layout[0][1].x).to.equal(190, "without merging"); expect(layout[2].length).to.equal(2); expect(layout[2][0].x).to.equal(110, "without merging"); // + 10 for staff expect(layout[2][1].x).to.equal(120, "without merging"); expect(layout[1].length).to.equal(2); expect(layout[1][0].x).to.equal(110, "without merging"); expect(layout[1][1].x).to.equal(130, "without merging"); // Now test opts.noAlign = false; layout = refreshMeasure(opts).elements; layout[1].map(l => delete (<any>l).key); expect(layout[1]).to.deep.equal( [ { division: 0, x: 100, model: null, renderClass: Type.Attributes }, { boundingBoxes: [], division: 0, expandPolicy: "after", x: 110, part: "P1", model: segments[1][0], // from first voice. renderClass: Type.Chord }, { division: 1, expandPolicy: "after", x: 120, model: null, renderClass: Type.Chord }, { boundingBoxes: [], expandPolicy: "after", division: 2, x: 130, part: "P1", model: segments[1][1], renderClass: Type.Chord }, { division: 4, x: 190, model: null, renderClass: Type.Attributes }, ] ); }); }); describe("layoutMeasure", function() { it("lays out a case with multiple voices", function() { let staffSegments = [ null, createFakeStaffSegment(4, 4, 1) ]; let voiceSegments = [ null, createFakeVoiceSegment(2, 6, 1), createFakeVoiceSegment(1, 7, 2) ]; let layout = layoutMeasure({ document: { __fakeDocument: true } as any, preview: false, print: null, fixup: null, header: <any> { partList: [ { _class: "ScorePart", id: "P1" } ] }, measure: { idx: 0, number: "1", version: 0, parts: { "P1": { voices: voiceSegments, staves: staffSegments } }, uuid: 248, width: NaN }, x: 100, lineBarOnLine: 0, lineTotalBarsOnLine: 0, lineShortest: 42, lineCount: 1, lineIndex: 0, factory: fakeFactory, attributes: {"P1": []}, singleLineMode: false, }); // We've tested this exact case in ISegment.layout$, so we can be // a bit soft here. expect(layout.paddingBottom).to.deep.equal([, 0]); expect(layout.paddingTop).to.deep.equal([, 0]); expect(layout.elements[0].length).to.equal(5); expect(layout.elements[0][4].x).to.equal(190); expect(layout.elements[0][0].x).to.equal(100); expect(layout.width).to.equal(100); }); }); describe("approximateWidth", function() { it("approximates mid-line width", function() { let staffSegments = [ null, createFakeStaffSegment(4, 4, 1) ]; let voiceSegments = [ null, createFakeVoiceSegment(2, 6, 1), createFakeVoiceSegment(1, 7, 2) ]; let width = getApproximateMeasureWidth({ idx: 0, number: "1", version: 0, parts: { "P1": { voices: voiceSegments, staves: staffSegments } }, uuid: 1248, width: NaN }, 42); // 100 - 10 for attribute 1. See createFakeStaffSegment expect(width).to.equal(90); }); }); });