Re: A Javascript test code for modifying ties and slurs with mouse

2019-12-14 Thread Werner LEMBERG


> At this point, here's the complete all-in-one .ly template.  [...]

It would be nice if you could format this to avoid line lengths longer
than 80 characters.  As the non-HTML part of your e-mail shows, the
code becomes very hard to read otherwise.


Werner



Re: A Javascript test code for modifying ties and slurs with mouse

2019-12-14 Thread Étienne Beaulé
I wouldn't worry so much about overriding that define, as svg-end can
only be used at that one spot or the output file would be corrupted.

A patch that included a proper override was provided 9 years but
ignored. I'll get the relevant parts of the patch up-to-date as it is
proving potential.

Thanks for your solution; I was discussing with OP on IRC the
potential ways to bodge the feature, but came up a bit short on both
your suggestions, Aaron. Also I didn't know about those undocumented
features!

Étienne



Re: A Javascript test code for modifying ties and slurs with mouse

2019-12-14 Thread Paolo Prete
At this point, here's the complete all-in-one .ly template. Much cleaner
and without risks to mess the code, for the user. In addition, it has not
to be patched: just open and use the generated .svg file.
Hope it could be included in the snippets repo. Thanks all for your
collaboration!


%%

\version "2.19.45"

JSSVGSlurTuner = #(define-void-function (body) (string?)
   (let* ((mod (resolve-module '(scm framework-svg)))
  (svg-end (module-ref mod 'svg-end #f)))
 (if (procedure? svg-end)
   (module-define! mod 'svg-end (lambda () (string-join
 (list "" (svg-end)) "\n"))

JSSVGSlurTunerScript = #"
pixelsX = document.querySelector('svg').getAttribute('width').replace('mm',
'') * 96 / 25.4
pixelsY =
document.querySelector('svg').getAttribute('height').replace('mm', '') * 96
/ 25.4
scaleX  = document.querySelector('svg').getAttribute('viewBox').split('
')[2] / pixelsX
scaleY  = document.querySelector('svg').getAttribute('viewBox').split('
')[3] / pixelsY

var slurId = 0
var currCp = null

function setCpsOnPath(path, x1, y1, x2, y2, x3, y3, x4, y4) {

path.setAttribute('d', 'M ' + x1 + ',' + y1 + ' ' +
   'C ' + x2 + ',' + y2 + ' ' +
  x3 + ',' + y3 + ' ' +
  x4 + ',' + y4)
}

function initSlur(node) {

//already initialized
if (node.hasAttribute('id'))
return

cpsCounter = 1
lineCounter = 1

for (var child = node.firstChild; child !== null; child =
child.nextSibling) {
if (child.nodeName == 'g') {
for (var child2 = child.firstChild; child2 !== null; child2 =
child2.nextSibling) {
//console.log(child2.nodeName)
if (child2.nodeName == 'circle') {
if (!node.hasAttribute('cp' + cpsCounter + 'x')) {
//TODO Ugly parsering, replace with a proper and
safer one
node.setAttribute('cp' + cpsCounter + 'x',
child2.getAttribute('transform').replace('translate(', '').split(',')[0])
node.setAttribute('cp' + cpsCounter + 'y',
child2.getAttribute('transform').split(',')[1].trim().replace(')', ''))
child2.setAttribute('id', slurId + '_cp_' +
cpsCounter)
child2.setAttribute('onmousedown', 'selectCp(this)')
}
cpsCounter++
}

if (child2.nodeName == 'line') {
child2.setAttribute('id', slurId + '_line_' +
lineCounter)
lineCounter++
}
}
}

//remove 'transform' attribute and set abs coords
if (child.nodeName == 'path') {
if (child.hasAttribute('transform'))
child.removeAttribute('transform')

setCpsOnPath(child, node.getAttribute('cp1x'),
node.getAttribute('cp1y'), node.getAttribute('cp2x'),
node.getAttribute('cp2y'),
 node.getAttribute('cp3x'),
node.getAttribute('cp3y'), node.getAttribute('cp4x'),
node.getAttribute('cp4y'))

child.setAttribute('id', slurId + '_path')
child.setAttribute('fill', 'none')
}
}

node.setAttribute('id', slurId)

coords = document.createElementNS('http://www.w3.org/2000/svg', 'text');
coords.setAttribute('transform', 'translate(' +
node.getAttribute('cp1x') + ',' + node.getAttribute('cp1y') + ')')
coords.setAttribute('font-size', '2')
coords.setAttribute('class', 'lilySlurCoords')
coords.setAttribute('id', slurId + '_coords')
node.appendChild(coords)

slurId++

}

function selectCp(cp) {

if (!cp.hasAttribute('id'))
return

if (!detectLeftButton(event)) {
event.preventDefault()
showCoords(cp.getAttribute('id').split('_')[0])
return
}

cp.setAttribute('color', 'cyan')
currCp = cp

}

function unselectCp() {

if (currCp)
currCp.setAttribute('color', 'rgb(255, 127, 0)')

currCp = null
}

function moveCp() {

if (!currCp)
return

currCp.setAttribute('transform', 'translate(' + event.pageX * scaleX +
',' + event.pageY * scaleY + ')')

//get the associated path
assocSlurId = currCp.getAttribute('id').split('_')[0]
path = document.getElementById(assocSlurId + '_path')

xs = []
ys = []

for (i = 0; i < 4; i++) {
//TODO ugly parser again!
xs[i] = document.getElementById(assocSlurId + '_cp_' + (i +
1)).getAttribute('transform').replace('translate(', '').split(',')[0]
ys[i] = document.getElementById(assocSlurId + '_cp_' + (i +
1)).getAttribute('transform').split(',')[1].trim().replace(')', '')
}

for (i = 0; i < 3; i++) {
document.getElementById(assocSlurId + '_line_' + (i +
1)).setAttribute('transform', 'translate(' + xs[i] + ',' + ys[i] + ')')

Re: A Javascript test code for modifying ties and slurs with mouse

2019-12-14 Thread Paolo Prete
To Stefano and Elaine:

really, it's better to avoid scripting on scripting on scripting, IMHO. SVG
is designed to be lovely coupled with JS, and the output file should be
all-inclusive. Nor HTML is required. Only Lilypond and any SVG viewer
(including browsers).  The override of internal stuff proposed by Aaron
should be the solution for that, taking care to contact the maintainer of
the code, meanwhile. I'm waiting for some feedback.
About the reverse process, I have some ideas, but want to meditate on them
before proposing a solution. I'm not even sure that it's a good idea to
automate the process...

On Sun, Dec 15, 2019 at 12:31 AM Stefano Troncaro 
wrote:

> Hi Paolo, I was also having that concern.
>
> Elaine replied in a new thread with a solution for that, in which instead
> of adding the script to the svg files with lilypond you just use an
> external script. I haven't tested it yet but it seems to me like that'll be
> a cleaner approach, you just include the file with the function to show the
> control points and the layout definitions and that's all you need.
>
> I guess you could make it even cleaner and have the shell script put the
> include statement in the .ly file.
>
> I'd go with that solution for now. Now what I'm curious about is if
> there's a way to automate the process of bringing the modified shapes into
> the lilypond file instead of having to manually paste every one. I have no
> clue on how to achieve that honestly, but that'd be incredible.
>
> HTH,
> Stéfano
>
> El sáb., 14 dic. 2019 a las 20:08, Paolo Prete ()
> escribió:
>
>> Hi Stefano,
>>
>> your suggestion produces the script for every page, but it requires to
>> manually add a property in the \paper scope. Instead, I would like to
>> automatically set this property, and leave the user to set all the score
>> properties (including the paper's one) without messing up the code adding
>> pieces of the template of the script. So to obtain something like (which is
>> much cleaner):
>>
>> \include "JSSVGSlurTuner.ly"
>>
>> {
>>
>>  \addJSSVGSlurTuner
>>
>>  . my score .
>>
>> }
>>
>> Thanks for your help
>> P
>>
>>
>> On Sat, Dec 14, 2019 at 11:13 PM Stefano Troncaro <
>> stefanotronc...@gmail.com> wrote:
>>
>>> Hi Paolo,
>>>
>>> Since Aaron's svg-script function creates an empty \markup, you can use
>>> the properties oddFooterMarkup and evenFooterMarkup of the \paper block to
>>> have your script embedded at the end of every page. Look:
>>>
>>> %%%
>>> \version "2.19.83"
>>>
>>> svg-script = #(define-scheme-function (body) (string?)
>>>(markup #:stencil (ly:make-stencil (list 'embedded-svg
>>>  (string-join (list ">>body "]]>") "\n")) '(0 . 0) '(0 . 0
>>>
>>> script-for-every-page = \svg-script
>>> #"var flat = document.getElementById('flat');
>>>flat.style.color = 'red';
>>>function spin(what, amount) {
>>>  let angle = 0.0;
>>>  return function () {
>>>const bbox = what.getBBox();
>>>const xform = ['rotate(',
>>>  (angle = (angle + amount) % 360.0),
>>>  bbox.x + 0.5 * bbox.width,
>>>  bbox.y + 0.75 * bbox.height, ')'];
>>>what.setAttribute('transform', xform.join(' '));
>>>  }
>>>}
>>>setInterval(spin(flat, 5), 100);"
>>>
>>> \paper {
>>>   oddFooterMarkup = \script-for-every-page
>>>   evenFooterMarkup = \script-for-every-page
>>> }
>>>
>>> { g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2
>>> \pageBreak
>>>   g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }
>>> %%%
>>>
>>> Love what your script is doing so far!
>>>
>>> Hope that helps,
>>> Stefano
>>>
>>> El sáb., 14 dic. 2019 a las 18:39, Paolo Prete ()
>>> escribió:
>>>
 Thanks Aaron, it did the trick.

 However, how can I make it work for multiple pages output?

 On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill 
 wrote:

> On 2019-12-13 5:59 pm, Paolo Pr wrote:
> > First of all, I need to add with Lilypond a   tag to the svg
> > file
> > just before the ending  tag  in the following way:
> >
> > 1)
> > 
> >