vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature
820 lines (578 loc) • 30.7 kB
HTML
<html>
<head>
<title>tickcontext.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" media="all" href="public/stylesheets/normalize.css" />
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div class="container">
<div class="page">
<div class="header">
<h1>tickcontext.js</h1>
<div class="toc">
<h3>Table of Contents</h3>
<ol>
<li>
<a class="source" href="accidental.html">
accidental.js
</a>
</li>
<li>
<a class="source" href="annotation.html">
annotation.js
</a>
</li>
<li>
<a class="source" href="articulation.html">
articulation.js
</a>
</li>
<li>
<a class="source" href="barnote.html">
barnote.js
</a>
</li>
<li>
<a class="source" href="beam.html">
beam.js
</a>
</li>
<li>
<a class="source" href="bend.html">
bend.js
</a>
</li>
<li>
<a class="source" href="boundingbox.html">
boundingbox.js
</a>
</li>
<li>
<a class="source" href="boundingboxcomputation.html">
boundingboxcomputation.js
</a>
</li>
<li>
<a class="source" href="canvascontext.html">
canvascontext.js
</a>
</li>
<li>
<a class="source" href="clef.html">
clef.js
</a>
</li>
<li>
<a class="source" href="clefnote.html">
clefnote.js
</a>
</li>
<li>
<a class="source" href="crescendo.html">
crescendo.js
</a>
</li>
<li>
<a class="source" href="curve.html">
curve.js
</a>
</li>
<li>
<a class="source" href="dot.html">
dot.js
</a>
</li>
<li>
<a class="source" href="easyscore.html">
easyscore.js
</a>
</li>
<li>
<a class="source" href="element.html">
element.js
</a>
</li>
<li>
<a class="source" href="factory.html">
factory.js
</a>
</li>
<li>
<a class="source" href="formatter.html">
formatter.js
</a>
</li>
<li>
<a class="source" href="fraction.html">
fraction.js
</a>
</li>
<li>
<a class="source" href="frethandfinger.html">
frethandfinger.js
</a>
</li>
<li>
<a class="source" href="ghostnote.html">
ghostnote.js
</a>
</li>
<li>
<a class="source" href="glyph.html">
glyph.js
</a>
</li>
<li>
<a class="source" href="glyphnote.html">
glyphnote.js
</a>
</li>
<li>
<a class="source" href="gracenote.html">
gracenote.js
</a>
</li>
<li>
<a class="source" href="gracenotegroup.html">
gracenotegroup.js
</a>
</li>
<li>
<a class="source" href="gracetabnote.html">
gracetabnote.js
</a>
</li>
<li>
<a class="source" href="index.html">
index.js
</a>
</li>
<li>
<a class="source" href="keymanager.html">
keymanager.js
</a>
</li>
<li>
<a class="source" href="keysignature.html">
keysignature.js
</a>
</li>
<li>
<a class="source" href="keysignote.html">
keysignote.js
</a>
</li>
<li>
<a class="source" href="modifier.html">
modifier.js
</a>
</li>
<li>
<a class="source" href="modifiercontext.html">
modifiercontext.js
</a>
</li>
<li>
<a class="source" href="multimeasurerest.html">
multimeasurerest.js
</a>
</li>
<li>
<a class="source" href="music.html">
music.js
</a>
</li>
<li>
<a class="source" href="note.html">
note.js
</a>
</li>
<li>
<a class="source" href="notehead.html">
notehead.js
</a>
</li>
<li>
<a class="source" href="notesubgroup.html">
notesubgroup.js
</a>
</li>
<li>
<a class="source" href="ornament.html">
ornament.js
</a>
</li>
<li>
<a class="source" href="parser.html">
parser.js
</a>
</li>
<li>
<a class="source" href="pedalmarking.html">
pedalmarking.js
</a>
</li>
<li>
<a class="source" href="raphaelcontext.html">
raphaelcontext.js
</a>
</li>
<li>
<a class="source" href="registry.html">
registry.js
</a>
</li>
<li>
<a class="source" href="renderer.html">
renderer.js
</a>
</li>
<li>
<a class="source" href="repeatnote.html">
repeatnote.js
</a>
</li>
<li>
<a class="source" href="smufl.html">
smufl.js
</a>
</li>
<li>
<a class="source" href="stave.html">
stave.js
</a>
</li>
<li>
<a class="source" href="stavebarline.html">
stavebarline.js
</a>
</li>
<li>
<a class="source" href="staveconnector.html">
staveconnector.js
</a>
</li>
<li>
<a class="source" href="stavehairpin.html">
stavehairpin.js
</a>
</li>
<li>
<a class="source" href="staveline.html">
staveline.js
</a>
</li>
<li>
<a class="source" href="stavemodifier.html">
stavemodifier.js
</a>
</li>
<li>
<a class="source" href="stavenote.html">
stavenote.js
</a>
</li>
<li>
<a class="source" href="staverepetition.html">
staverepetition.js
</a>
</li>
<li>
<a class="source" href="stavesection.html">
stavesection.js
</a>
</li>
<li>
<a class="source" href="stavetempo.html">
stavetempo.js
</a>
</li>
<li>
<a class="source" href="stavetext.html">
stavetext.js
</a>
</li>
<li>
<a class="source" href="stavetie.html">
stavetie.js
</a>
</li>
<li>
<a class="source" href="stavevolta.html">
stavevolta.js
</a>
</li>
<li>
<a class="source" href="stem.html">
stem.js
</a>
</li>
<li>
<a class="source" href="stemmablenote.html">
stemmablenote.js
</a>
</li>
<li>
<a class="source" href="stringnumber.html">
stringnumber.js
</a>
</li>
<li>
<a class="source" href="strokes.html">
strokes.js
</a>
</li>
<li>
<a class="source" href="svgcontext.html">
svgcontext.js
</a>
</li>
<li>
<a class="source" href="system.html">
system.js
</a>
</li>
<li>
<a class="source" href="tables.html">
tables.js
</a>
</li>
<li>
<a class="source" href="tabnote.html">
tabnote.js
</a>
</li>
<li>
<a class="source" href="tabslide.html">
tabslide.js
</a>
</li>
<li>
<a class="source" href="tabstave.html">
tabstave.js
</a>
</li>
<li>
<a class="source" href="tabtie.html">
tabtie.js
</a>
</li>
<li>
<a class="source" href="textbracket.html">
textbracket.js
</a>
</li>
<li>
<a class="source" href="textdynamics.html">
textdynamics.js
</a>
</li>
<li>
<a class="source" href="textnote.html">
textnote.js
</a>
</li>
<li>
<a class="source" href="tickable.html">
tickable.js
</a>
</li>
<li>
<a class="source" href="tickcontext.html">
tickcontext.js
</a>
</li>
<li>
<a class="source" href="timesignature.html">
timesignature.js
</a>
</li>
<li>
<a class="source" href="timesignote.html">
timesignote.js
</a>
</li>
<li>
<a class="source" href="tremolo.html">
tremolo.js
</a>
</li>
<li>
<a class="source" href="tuning.html">
tuning.js
</a>
</li>
<li>
<a class="source" href="tuplet.html">
tuplet.js
</a>
</li>
<li>
<a class="source" href="vex.html">
vex.js
</a>
</li>
<li>
<a class="source" href="vibrato.html">
vibrato.js
</a>
</li>
<li>
<a class="source" href="vibratobracket.html">
vibratobracket.js
</a>
</li>
<li>
<a class="source" href="voice.html">
voice.js
</a>
</li>
<li>
<a class="source" href="voicegroup.html">
voicegroup.js
</a>
</li>
</ol>
</div>
</div>
<p><a href="http://vexflow.com">VexFlow</a> - Copyright (c) Mohit Muthanna 2010.</p>
<h2 id="description">Description</h2>
<p>A formatter for abstract tickable objects, such as notes, chords,
tabs, etc.</p>
<div class='highlight'><pre>
<span class="hljs-keyword">import</span> { Vex } <span class="hljs-keyword">from</span> <span class="hljs-string">'./vex'</span>;
<span class="hljs-keyword">import</span> { Tickable } <span class="hljs-keyword">from</span> <span class="hljs-string">'./tickable'</span>;
<span class="hljs-keyword">import</span> { Fraction } <span class="hljs-keyword">from</span> <span class="hljs-string">'./fraction'</span>;
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TickContext</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Tickable</span> </span>{
<span class="hljs-keyword">static</span> getNextContext(tContext) {
<span class="hljs-keyword">const</span> contexts = tContext.tContexts;
<span class="hljs-keyword">const</span> index = contexts.indexOf(tContext);
<span class="hljs-keyword">return</span> contexts[index + <span class="hljs-number">1</span>];
}
<span class="hljs-keyword">constructor</span>(options) {
<span class="hljs-keyword">super</span>();
<span class="hljs-keyword">this</span>.tickID = options && options.tickID;
<span class="hljs-keyword">this</span>.setAttribute(<span class="hljs-string">'type'</span>, <span class="hljs-string">'TickContext'</span>);
<span class="hljs-keyword">this</span>.currentTick = <span class="hljs-keyword">new</span> Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>);
<span class="hljs-keyword">this</span>.maxTicks = <span class="hljs-keyword">new</span> Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>);
<span class="hljs-keyword">this</span>.maxTickable = <span class="hljs-literal">null</span>; <span class="hljs-comment">// Biggest tickable</span>
<span class="hljs-keyword">this</span>.minTicks = <span class="hljs-literal">null</span>; <span class="hljs-comment">// this can remian null if all tickables have ignore_ticks</span>
<span class="hljs-keyword">this</span>.minTickable = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">this</span>.padding = <span class="hljs-number">1</span>; <span class="hljs-comment">// padding on each side (width += padding * 2)</span>
<span class="hljs-keyword">this</span>.x = <span class="hljs-number">0</span>;
<span class="hljs-keyword">this</span>.xBase = <span class="hljs-number">0</span>; <span class="hljs-comment">// base x position without xOffset</span>
<span class="hljs-keyword">this</span>.xOffset = <span class="hljs-number">0</span>; <span class="hljs-comment">// xBase and xOffset are an alternative way to describe x (x = xB + xO)</span>
<span class="hljs-keyword">this</span>.tickables = []; <span class="hljs-comment">// Notes, tabs, chords, lyrics.</span>
<span class="hljs-keyword">this</span>.tickablesByVoice = {}; <span class="hljs-comment">// Tickables indeced by voice number</span></pre></div>
<p>Formatting metrics</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.notePx = <span class="hljs-number">0</span>; <span class="hljs-comment">// width of widest note in this context</span>
<span class="hljs-keyword">this</span>.glyphPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// width of glyph (note head)</span>
<span class="hljs-keyword">this</span>.leftDisplacedHeadPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// Extra left pixels for displaced notes</span>
<span class="hljs-keyword">this</span>.rightDisplacedHeadPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// Extra right pixels for displaced notes</span>
<span class="hljs-keyword">this</span>.modLeftPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// Left modifier pixels</span>
<span class="hljs-keyword">this</span>.modRightPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// Right modifier pixels</span>
<span class="hljs-keyword">this</span>.totalLeftPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// Total left pixels</span>
<span class="hljs-keyword">this</span>.totalRightPx = <span class="hljs-number">0</span>; <span class="hljs-comment">// Total right pixels</span>
<span class="hljs-keyword">this</span>.tContexts = []; <span class="hljs-comment">// Parent array of tick contexts</span>
}
getTickID() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.tickID; }
getX() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.x; }
setX(x) { <span class="hljs-keyword">this</span>.x = x; <span class="hljs-keyword">this</span>.xBase = x; <span class="hljs-keyword">this</span>.xOffset = <span class="hljs-number">0</span>; <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>; }
getXBase() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.xBase; } <span class="hljs-comment">// use of xBase and xOffset is optional, avoids offset creep</span>
setXBase(xBase) { <span class="hljs-keyword">this</span>.xBase = xBase; <span class="hljs-keyword">this</span>.x = xBase + <span class="hljs-keyword">this</span>.xOffset; }
getXOffset() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.xOffset; }
setXOffset(xOffset) { <span class="hljs-keyword">this</span>.xOffset = xOffset; <span class="hljs-keyword">this</span>.x = <span class="hljs-keyword">this</span>.xBase + xOffset; }
getWidth() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.width + (<span class="hljs-keyword">this</span>.padding * <span class="hljs-number">2</span>); }
setPadding(padding) { <span class="hljs-keyword">this</span>.padding = padding; <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>; }
getMaxTicks() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.maxTicks; }
getMinTicks() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.minTicks; }
getMaxTickable() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.maxTickable; }
getMinTickable() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.minTickable; }
getTickables() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.tickables; }
getTickablesForVoice(voiceIndex) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.tickablesByVoice[voiceIndex]; }
getTickablesByVoice() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.tickablesByVoice; }
getCenterAlignedTickables() {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.tickables.filter(<span class="hljs-function"><span class="hljs-params">tickable</span> =></span> tickable.isCenterAligned());
}</pre></div>
<p>Get widths context, note and left/right modifiers for formatting</p>
<div class='highlight'><pre> getMetrics() {
<span class="hljs-keyword">const</span> { width, glyphPx, notePx, leftDisplacedHeadPx, rightDisplacedHeadPx, modLeftPx, modRightPx, totalLeftPx, totalRightPx } = <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">return</span> {
width, <span class="hljs-comment">// Width of largest tickable in context</span>
glyphPx, <span class="hljs-comment">// Width of largest glyph (note head)</span>
notePx, <span class="hljs-comment">// Width of notehead + stem</span>
leftDisplacedHeadPx, <span class="hljs-comment">// Left modifiers</span>
rightDisplacedHeadPx, <span class="hljs-comment">// Right modifiers</span>
modLeftPx,
modRightPx,
totalLeftPx,
totalRightPx
};
}
getCurrentTick() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.currentTick; }
setCurrentTick(tick) {
<span class="hljs-keyword">this</span>.currentTick = tick;
<span class="hljs-keyword">this</span>.preFormatted = <span class="hljs-literal">false</span>;
}
addTickable(tickable, voiceIndex) {
<span class="hljs-keyword">if</span> (!tickable) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Vex.RERR(<span class="hljs-string">'BadArgument'</span>, <span class="hljs-string">'Invalid tickable added.'</span>);
}
<span class="hljs-keyword">if</span> (!tickable.shouldIgnoreTicks()) {
<span class="hljs-keyword">this</span>.ignore_ticks = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">const</span> ticks = tickable.getTicks();
<span class="hljs-keyword">if</span> (ticks.greaterThan(<span class="hljs-keyword">this</span>.maxTicks)) {
<span class="hljs-keyword">this</span>.maxTicks = ticks.clone();
<span class="hljs-keyword">this</span>.maxTickable = tickable;
}
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.minTicks == <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">this</span>.minTicks = ticks.clone();
<span class="hljs-keyword">this</span>.minTickable = tickable;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ticks.lessThan(<span class="hljs-keyword">this</span>.minTicks)) {
<span class="hljs-keyword">this</span>.minTicks = ticks.clone();
<span class="hljs-keyword">this</span>.minTickable = tickable;
}
}
tickable.setTickContext(<span class="hljs-keyword">this</span>);
<span class="hljs-keyword">this</span>.tickables.push(tickable);
<span class="hljs-keyword">this</span>.tickablesByVoice[voiceIndex] = tickable;
<span class="hljs-keyword">this</span>.preFormatted = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
preFormat() {
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.preFormatted) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-keyword">this</span>.tickables.length; ++i) {
<span class="hljs-keyword">const</span> tickable = <span class="hljs-keyword">this</span>.tickables[i];
tickable.preFormat();
<span class="hljs-keyword">const</span> metrics = tickable.getMetrics();</pre></div>
<p>Maintain max displaced head pixels from all tickables in the context</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.leftDisplacedHeadPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.leftDisplacedHeadPx, metrics.leftDisplacedHeadPx);
<span class="hljs-keyword">this</span>.rightDisplacedHeadPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.rightDisplacedHeadPx, metrics.rightDisplacedHeadPx);</pre></div>
<p>Maintain the widest note for all tickables in the context</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.notePx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.notePx, metrics.notePx);</pre></div>
<p>Maintain the widest note head</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.glyphPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.glyphPx, metrics.glyphWidth);</pre></div>
<p>Total modifier shift</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.modLeftPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.modLeftPx, metrics.modLeftPx);
<span class="hljs-keyword">this</span>.modRightPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.modRightPx, metrics.modRightPx);</pre></div>
<p>Total shift</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.totalLeftPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.totalLeftPx, metrics.modLeftPx + metrics.leftDisplacedHeadPx);
<span class="hljs-keyword">this</span>.totalRightPx = <span class="hljs-built_in">Math</span>.max(<span class="hljs-keyword">this</span>.totalRightPx, metrics.modRightPx + metrics.rightDisplacedHeadPx);</pre></div>
<p>Recalculate the tick context total width</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.width = <span class="hljs-keyword">this</span>.notePx + <span class="hljs-keyword">this</span>.totalLeftPx + <span class="hljs-keyword">this</span>.totalRightPx;
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
postFormat() {
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.postFormatted) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
<span class="hljs-keyword">this</span>.postFormatted = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
}</pre></div>
<div class="fleur">h</div>
</div>
</div>
</body>
</html>