Skip to content

Commit

Permalink
Merge pull request #807 from mscuthbert/stem_length
Browse files Browse the repository at this point in the history
Stem length to middle line
  • Loading branch information
0xfe authored Sep 1, 2020
2 parents f264d0c + 65bed62 commit c07516f
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 136 deletions.
54 changes: 50 additions & 4 deletions src/stavenote.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class StaveNote extends StemmableNote {
let minL = props[props.length - 1].line;
const stemDirection = notes[i].getStemDirection();
const stemMax = notes[i].getStemLength() / 10;
const stemMin = notes[i].getStemMinumumLength() / 10;
const stemMin = notes[i].getStemMinimumLength() / 10;

let maxL;
if (notes[i].isRest()) {
Expand Down Expand Up @@ -439,6 +439,10 @@ export class StaveNote extends StemmableNote {

// Automatically sets the stem direction based on the keys in the note
autoStem() {
this.setStemDirection(this.calculateOptimalStemDirection());
}

calculateOptimalStemDirection() {
// Figure out optimal stem direction based on given notes
this.minLine = this.keyProps[0].line;
this.maxLine = this.keyProps[this.keyProps.length - 1].line;
Expand All @@ -447,7 +451,7 @@ export class StaveNote extends StemmableNote {
const decider = (this.minLine + this.maxLine) / 2;
const stemDirection = decider < MIDDLE_LINE ? Stem.UP : Stem.DOWN;

this.setStemDirection(stemDirection);
return stemDirection;
}

// Calculates and stores the properties for each key in the note
Expand Down Expand Up @@ -561,8 +565,8 @@ export class StaveNote extends StemmableNote {
return new BoundingBox(x, minY, w, maxY - minY);
}

// Gets the line number of the top or bottom note in the chord.
// If `isTopNote` is `true` then get the top note
// Gets the line number of the bottom note in the chord.
// If `isTopNote` is `true` then get the top note's line number instead
getLineNumber(isTopNote) {
if (!this.keyProps.length) {
throw new Vex.RERR(
Expand Down Expand Up @@ -1106,6 +1110,48 @@ export class StaveNote extends StemmableNote {
this.context.closeGroup();
}


/**
* Override stemmablenote stem extension to adjust for distance from middle line.
*/
getStemExtension() {
const super_stem_extension = super.getStemExtension();
if (!this.glyph.stem) {
return super_stem_extension;
}

const stem_direction = this.getStemDirection();
if (stem_direction !== this.calculateOptimalStemDirection()) {
return super_stem_extension; // no adjustment for manually set stem direction.
}
let mid_line_distance;
const MIDDLE_LINE = 3;
if (stem_direction === Stem.UP) {
// Note that the use of maxLine here instead of minLine might
// seem counterintuitive, but in the case of (say) treble clef
// chord(F2, E4) stem up, we do not want to extend the stem because
// of F2, when a normal octave-length stem above E4 is fine.
//
// maxLine and minLine are set in calculateOptimalStemDirection() so
// will be known.
mid_line_distance = MIDDLE_LINE - this.maxLine;
} else {
mid_line_distance = this.minLine - MIDDLE_LINE;
}

// how many lines more than an octave is the relevant notehead?
const lines_over_octave_from_mid_line = mid_line_distance - 3.5;
if (lines_over_octave_from_mid_line <= 0) {
return super_stem_extension;
}
const stave = this.getStave();
let spacing_between_lines = 10;
if (stave != null) {
spacing_between_lines = stave.getSpacingBetweenLines();
}
return super_stem_extension + (lines_over_octave_from_mid_line * spacing_between_lines);
}

// Draws all the `StaveNote` parts. This is the main drawing method.
draw() {
if (!this.context) {
Expand Down
12 changes: 9 additions & 3 deletions src/stem.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,16 @@ export class Stem extends Element {

// Gets the entire height for the stem
getHeight() {
const y_offset = (this.stem_direction === Stem.UP) ? this.stem_up_y_offset : this.stem_down_y_offset; // eslint-disable-line max-len
return ((this.y_bottom - this.y_top) * this.stem_direction) +
((Stem.HEIGHT - y_offset + this.stem_extension) * this.stem_direction);
const y_offset = (this.stem_direction === Stem.UP)
? this.stem_up_y_offset
: this.stem_down_y_offset;
const unsigned_height = (
(this.y_bottom - this.y_top)
+ (Stem.HEIGHT - y_offset + this.stem_extension)
); // parentheses just for grouping.
return unsigned_height * this.stem_direction;
}

getBoundingBox() {
throw new Vex.RERR('NotImplemented', 'getBoundingBox() not implemented.');
}
Expand Down
12 changes: 6 additions & 6 deletions src/stemmablenote.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class StemmableNote extends Note {
this.setAttribute('type', 'StemmableNote');

this.stem = null;
this.stemExtensionOverride = null;
this.stem_extension_override = null;
this.beam = null;
}

Expand Down Expand Up @@ -70,7 +70,7 @@ export class StemmableNote extends Note {
}

// Get the minimum length of stem
getStemMinumumLength() {
getStemMinimumLength() {
const frac = Flow.durationToFraction(this.duration);
let length = frac.value() <= 1 ? 0 : 20;
// if note is flagged, cannot shorten beam
Expand Down Expand Up @@ -153,12 +153,12 @@ export class StemmableNote extends Note {
getStemExtension() {
const glyph = this.getGlyph();

if (this.stemExtensionOverride != null) {
return this.stemExtensionOverride;
if (this.stem_extension_override != null) {
return this.stem_extension_override;
}

if (glyph) {
return this.getStemDirection() === 1
return this.getStemDirection() === Stem.UP
? glyph.stem_up_extension
: glyph.stem_down_extension;
}
Expand All @@ -168,7 +168,7 @@ export class StemmableNote extends Note {

// Set the stem length to a specific. Will override the default length.
setStemLength(height) {
this.stemExtensionOverride = (height - Stem.HEIGHT);
this.stem_extension_override = (height - Stem.HEIGHT);
return this;
}

Expand Down
Loading

0 comments on commit c07516f

Please sign in to comment.