abc2svg
ambitus.js at tip
Not logged in

File modules/ambitus.js from the latest check-in


// ambitus.js - module to insert an ambitus at start of a voice
//
// Copyright (C) 2018-2023 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg.  If not, see <http://www.gnu.org/licenses/>.
//
// This module is loaded when "%%ambitus" appears in a ABC source.
//
// Parameters
//	%%ambitus 1

if (typeof abc2svg == "undefined")
    var	abc2svg = {}

abc2svg.ambitus = {
    do_ambitus: function() {
    var	C = abc2svg.C,
	s, v, p_v, min, max,
	voice_tb = this.get_voice_tb()

	for (v = 0; v < voice_tb.length; v++) {
		p_v = voice_tb[v];
		if (p_v.second)
			continue
		min = 100;
		max = -100

		// search the top and bottom pitches
		for (s = p_v.sym; s; s = s.next) {
			if (s.type != C.NOTE)
				continue
			if (s.notes[s.nhd].pit > max)
				max = s.notes[s.nhd].pit
			if (s.notes[0].pit < min)
				min = s.notes[0].pit
		}
		if (min == 100)
			continue			// no note

		s = p_v.clef;
		s.stem = 1;
		s.head = C.FULL;
		s.stemless = true;
		s.nhd = 1;
		s.notes = [{
				dur: C.BLEN / 4,
				pit: min,
				shhd: 0
			},{
				dur: C.BLEN / 4,
				pit: max,
				shhd: 0
			}]
	}
    }, // do_ambitus()

    draw_symbols: function(of, p_voice) {
    var	staff_tb = this.get_staff_tb(),
	s = p_voice.sym

	if (s.clef_type != undefined && s.nhd > 0) {
		s.x -= 26;
		this.set_scale(s);
		this.draw_note(s)
		if (s.notes[1].pit - s.notes[0].pit > 4) {
			this.xypath(s.x, 3 * (s.notes[1].pit - 18) + staff_tb[s.st].y);
			this.out_svg('v' +
				((s.notes[1].pit - s.notes[0].pit) * 3).toFixed(1) +
				'" stroke-width=".6"/>\n');
		}
		s.x += 26;
		s.nhd = 0
		p_voice.clef.nhd = 0
	}
	of(p_voice)
    }, // draw_symbols()

    set_pitch: function(of, last_s) {
	of(last_s)
	if (!last_s && this.cfmt().ambitus)
		abc2svg.ambitus.do_ambitus.call(this)
    },

    set_fmt: function(of, cmd, param) {
	if (cmd == "ambitus") {
		this.cfmt().ambitus = param
		return
	}
	of(cmd, param)
    },

    set_glue: function(of, w) {
    var	v, s,
	voice_tb = this.get_voice_tb()

	of(w)
	if (this.cfmt().ambitus) {
		for (v = 0; v < voice_tb.length; v++) {
			s = voice_tb[v].sym
			while (!s.time && !s.clef_type)
				s = s.next
			if (s && s.nhd) {	// draw the helper lines if any
				s.x -= 26
				this.draw_hl(s)
				s.ymn = 3 * (s.notes[0].pit - 18) - 2
				s.ymx = 3 * (s.notes[1].pit - 18) + 2
				s.x += 26
			}
		}
	}
    }, // set_glue()

    set_width: function(of, s) {
	if (s.clef_type != undefined && s.nhd > 0) {
		s.wl = 40;
		s.wr = 12
	} else {
		of(s)
	}
    },

    set_hooks: function(abc) {
	abc.draw_symbols = abc2svg.ambitus.draw_symbols.bind(abc, abc.draw_symbols);
	abc.set_pitch = abc2svg.ambitus.set_pitch.bind(abc, abc.set_pitch);
	abc.set_format = abc2svg.ambitus.set_fmt.bind(abc, abc.set_format);
	abc.set_sym_glue = abc2svg.ambitus.set_glue.bind(abc, abc.set_sym_glue)
	abc.set_width = abc2svg.ambitus.set_width.bind(abc, abc.set_width)
    }
} // ambitus

if (!abc2svg.mhooks)
	abc2svg.mhooks = {}
abc2svg.mhooks.ambitus = abc2svg.ambitus.set_hooks