App-Music-ChordPro

 view release on metacpan or  search on metacpan

lib/ChordPro/res/abc/abc2svg/jianpu-1.js  view on Meta::CPAN

// jianpu.js - module to output jiănpŭ (简谱) music sheets
//
// Copyright (C) 2020-2025 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 "%%jianpu" appears in a ABC source.
//
// Parameters (none)
//	%%jianpu 1

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

abc2svg.jianpu = {

  k_tb: [ "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F",
	  "C",
	  "G", "D", "A", "E", "B", "F#", "C#" ],
  cde2fcg: new Int8Array([0, 2, 4, -1, 1, 3, 5]),
  cgd2cde: new Int8Array([0, -4, -1, -5, -2, -6, -3,
			  0, -4, -1, -5, -2, -6, -3, 0]),
  acc2: new Int8Array([-2, -1, 3, 1, 2]),
  acc_tb: ["\ue264", "\ue260", , "\ue262", "\ue263", "\ue261"],

// don't calculate the beams
  calc_beam: function(of, bm, s1) {
	if (!s1.p_v.jianpu)
		return of(bm, s1)
//	return 0
  }, // calc_beam()

// adjust some symbols before the generation
  output_music: function(of) {
    var	p_v, v,
	C = abc2svg.C,
	abc = this,
	cur_sy = abc.get_cur_sy(),
	voice_tb = abc.get_voice_tb()

	// handle the overlay voices
	function ov_def(v) {
	    var	s1, tim,
		s = p_v.sym

		while (s) {
			s1 = s.ts_prev
			if (!s.invis
			 && s.dur
			 && s1.v != v
			 && s1.st == s.st	// overlay start
			 && s1.time == s.time) {
				while (1) {	// go back to the previous bar
					if (!s1.prev
					 || s1.prev.bar_type)
						break
					s1 = s1.prev
				}
				//add deco '{' on s1
				while (!s1.bar_type) {
					s1.dy = 14
					s1.notes[0].pit = 30
					if (s1.type == C.REST)
						s1.combine = -1
					s1 = s1.next
				}
				// add deco '}' on s1

				while (1) {
					s.dy = -14
					s.notes[0].pit = 20
					if (!s.next
					 || s.next.bar_type
					 || s.next.time >= s1.time)
						break
					s = s.next
				}
			}
			s = s.next
		}
	} // ov_def()

	// output the key and time signatures
	function set_head() {
	    var	v, p_v, mt, s2, sk, s,
		tsfirst = abc.get_tsfirst()

		// search a jianpu voice
		for (v = 0; v < voice_tb.length; v++) {
			p_v = voice_tb[v]
			if (p_v.jianpu)
				break
		}
		if (v >= voice_tb.length)
				return

		mt = p_v.meter.a_meter[0]
		sk = p_v.key
		s2 = p_v.sym
		s = {
			type: C.BLOCK,
			subtype: "text",
			time: s2.time,
			dur: 0,
			v: 0,
			p_v: p_v,
			st: 0,
			fmt: s2.fmt,
			seqst: true,
			text: (sk.k_mode + 1) + "=" +
				(abc2svg.jianpu.k_tb[sk.k_sf + 7 +

lib/ChordPro/res/abc/abc2svg/jianpu-1.js  view on Meta::CPAN

			out_svg('<path class="stroke" \
d="m' + (l / 2 - 3).toFixed(1)+' '+y.toFixed(1))
			if (s.gr_shift) {
				out_svg('m0 0c0 10 0 10 -10 10')
			} else {
				out_svg('m0 0c0 10 0 10 10 10')
			}
			out_svg('"/>\n')
		}
		out_svg('</g>\n')
		abc.stv_g().g--
	} // draw_dgr()

	function out_mus(x, y, p) {
		out_svg('<text x="')
		out_sxsy(x, '" y="', y)
		out_svg('">' + p + '</text>\n')
	} // out_mus()

	function out_txt(x, y, p) {
		out_svg('<text class="fj" x="')
		out_sxsy(x, '" y="', y)
		out_svg('">' + p + '</text>\n')
	} // out_txt()

	function draw_hd(s, x, y) {
	    var	m, note, ym

		for (m = 0; m <= s.nhd; m++) {
			note = s.notes[m]
			out_txt(x - 3.5, y + 8, "01234567-"[note.jn])
			if (note.acc)
				out_mus(x - 12, y + 12,
					abc2svg.jianpu.acc_tb[note.acc + 2])
			if (note.jo > 2) {
				out_mus(x - 1, y + 22, dot)
				if (note.jo > 3) {
					y += 3
					out_mus(x - 1, y + 22, dot)
				}
			} else if (note.jo < 2) {
				ym = y + 4
				if (m == 0 && s.nflags > 0)
					ym -= 2.5 * s.nflags
				out_mus(x - 1, ym, dot)
				if (note.jo < 1) {
					ym -= 3
					out_mus(x - 1, ym, dot)
				}
			}
			y += 20
		}
	} // draw_hd()

	function draw_note(s) {
	    var	sc = 1,
		x = s.x,
		y = staff_tb[s.st].y

		if (s.dy)
			y += s.dy			// voice overlay

		if (s.grace) {
			out_svg('<g transform="translate(')
			out_sxsy(x, ',', y + 15)	// (font height)
			out_svg(') scale(.5)">\n')
			abc.stv_g().g++			// in container
			x = 0
			y = 0
			sc = .5
		}

		draw_hd(s, x, y)

		if (s.nflags >= 0 && s.dots)
			out_mus(x + 8 * sc, y + 13 * sc, dot)
		if (s.grace) {
			out_svg('</g>\n')
			abc.stv_g().g--
		}
		anno_a.push(s)
	} // draw_note()

	// -- draw_symbols --
	for (s = p_voice.sym; s; s = s.next) {
		if (s.invis)
			continue
		switch (s.type) {
		case C.METER:
			abc.draw_meter(s)
			break
		case C.NOTE:
		case C.REST:
			draw_note(s)
			break
		case C.GRACE:
			for (g = s.extra; g; g = g.next)
				draw_note(g)
			break
		}
	}

	// draw the (pseudo) beams
	for (s = p_voice.sym; s; s = s.next) {
		if (s.invis)
			continue
		switch (s.type) {
		case C.NOTE:
		case C.REST:
			nl = s.nflags
			if (nl <= 0)
				continue
			y = staff_tb[s.st].y
			s2 = s
			while (1) {
				if (s.nflags > nl)
					nl = s.nflags
				if (s.beam_end)
					break
				if (s.type == C.GRACE)
					draw_dgr(s)



( run in 1.999 second using v1.01-cache-2.11-cpan-aadc1410aed )