Note* searchTieNote114(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->staff()->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; while ((seg = seg->next1(Segment::SegChordRest))) { for (int track = strack; track < etrack; ++track) { Chord* c = static_cast<Chord*>(seg->element(track)); if (c == 0 || (c->type() != Element::CHORD) || (c->track() != chord->track())) continue; int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
Note* Score::upAlt(Element* element) { Element* re = 0; if (element->type() == Element::REST) { if (_is.track() <= 0) return 0; _is.setTrack(_is.track() - 1); re = searchNote(static_cast<Rest*>(element)->tick(), _is.track()); } else if (element->type() == Element::NOTE) { // find segment Chord* chord = static_cast<Note*>(element)->chord(); Segment* segment = chord->segment(); // collect all notes for this segment in noteList: QList<Note*> rnl; int tracks = nstaves() * VOICES; for (int track = 0; track < tracks; ++track) { Element* el = segment->element(track); if (!el || el->type() != Element::CHORD) continue; rnl.append(static_cast<Chord*>(el)->notes()); qSort(rnl.begin(), rnl.end(), noteLessThan); int idx = rnl.indexOf(static_cast<Note*>(element)); if (idx < rnl.size()-1) ++idx; re = rnl.value(idx); } } if (re == 0) return 0; if (re->type() == Element::CHORD) re = ((Chord*)re)->notes().front(); return (Note*)re; }
void Glissando::layout() { Chord* chord = static_cast<Chord*>(parent()); if (chord == 0) { return; } Note* anchor2 = chord->upNote(); Segment* s = chord->segment(); s = s->prev1(); while (s) { if ((s->subtype() & (Segment::SegChordRestGrace)) && s->element(track())) break; s = s->prev1(); } if (s == 0) { qDebug("no segment for first note of glissando found\n"); return; } ChordRest* cr = static_cast<ChordRest*>(s->element(track())); if (cr == 0 || cr->type() != CHORD) { qDebug("no first note for glissando found, track %d\n", track()); return; } Note* anchor1 = static_cast<Chord*>(cr)->upNote(); setPos(0.0, 0.0); QPointF cp1 = anchor1->pagePos(); QPointF cp2 = anchor2->pagePos(); // construct line from notehead to notehead qreal x1 = (anchor1->headWidth()) - (cp2.x() - cp1.x()); qreal y1 = anchor1->pos().y(); qreal x2 = anchor2->pos().x(); qreal y2 = anchor2->pos().y(); // on TAB's, adjust lower end point from string line height to base of note height (= ca. half line spacing) if (chord->staff()->isTabStaff()) { qreal yOff = chord->staff()->lineDistance() * 0.5 * spatium(); if (anchor1->pitch() > anchor2->pitch()) // descending glissando: y2 += yOff; // move ending point to base of note else // ascending glissando: y1 += yOff; // move starting point to base of note } QLineF fullLine(x1, y1, x2, y2); // shorten line on each side by offsets qreal xo = spatium() * .5; qreal yo = xo; // spatium() * .5; QPointF p1 = fullLine.pointAt(xo / fullLine.length()); QPointF p2 = fullLine.pointAt(1 - (yo / fullLine.length())); line = QLineF(p1, p2); qreal lw = spatium() * .15 * .5; QRectF r = QRectF(line.p1(), line.p2()).normalized(); setbbox(r.adjusted(-lw, -lw, lw, lw)); }
void Glissando::layout() { Chord* chord = static_cast<Chord*>(parent()); if (chord == 0) { return; } Note* anchor2 = chord->upNote(); Segment* s = chord->segment(); s = s->prev1(); while (s) { if ((s->subtype() == SegChordRest || s->subtype() == SegGrace) && s->element(track())) break; s = s->prev1(); } if (s == 0) { qDebug("no segment for first note of glissando found\n"); return; } ChordRest* cr = static_cast<ChordRest*>(s->element(track())); if (cr == 0 || cr->type() != CHORD) { qDebug("no first note for glissando found, track %d\n", track()); return; } Note* anchor1 = static_cast<Chord*>(cr)->upNote(); setPos(0.0, 0.0); QPointF cp1 = anchor1->pagePos(); QPointF cp2 = anchor2->pagePos(); // construct line from notehead to notehead qreal x1 = (anchor1->headWidth()) - (cp2.x() - cp1.x()); qreal y1 = anchor1->pos().y(); qreal x2 = anchor2->pos().x(); qreal y2 = anchor2->pos().y(); QLineF fullLine(x1, y1, x2, y2); // shorten line on each side by offsets qreal xo = spatium() * .5; qreal yo = xo; // spatium() * .5; QPointF p1 = fullLine.pointAt(xo / fullLine.length()); QPointF p2 = fullLine.pointAt(1 - (yo / fullLine.length())); line = QLineF(p1, p2); qreal lw = spatium() * .15 * .5; QRectF r = QRectF(line.p1(), line.p2()).normalized(); setbbox(r.adjusted(-lw, -lw, lw, lw)); }
QPointF Arpeggio::gripAnchor(int n) const { Chord* c = chord(); if (c == 0) return QPointF(); if (n == 0) return c->upNote()->pagePos(); else if (n == 1) { Note* dnote = c->downNote(); int btrack = track() + (_span - 1) * VOICES; ChordRest* bchord = static_cast<ChordRest*>(c->segment()->element(btrack)); if (bchord && bchord->type() == CHORD) dnote = static_cast<Chord*>(bchord)->downNote(); return dnote->pagePos(); } return QPointF(); }
Note* searchTieNote(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->staff()->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; if (chord->isGraceBefore()) { chord = static_cast<Chord*>(chord->parent()); note2 = chord->findNote(note->pitch()); return note2; } QList<Chord*> gna; if (chord->getGraceNotesAfter(&gna)) { chord = gna[0]; note2 = chord->findNote(note->pitch()); return note2; } while ((seg = seg->next1(Segment::Type::ChordRest))) { for (int track = strack; track < etrack; ++track) { Chord* c = static_cast<Chord*>(seg->element(track)); if (c == 0 || c->type() != Element::Type::CHORD) continue; int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
Note* searchTieNote(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; if (chord->isGraceBefore()) { // grace before // try to tie to note in parent chord chord = toChord(chord->parent()); note2 = chord->findNote(note->pitch()); if (note2) return note2; } else if (chord->isGraceAfter()) { // grace after // we will try to tie to note in next normal chord, below // meanwhile, set chord to parent chord so the endTick calculation will make sense chord = toChord(chord->parent()); } else { // normal chord // try to tie to grace note after if present QVector<Chord*> gna = chord->graceNotesAfter(); if (!gna.empty()) { Chord* gc = gna[0]; note2 = gc->findNote(note->pitch()); if (note2) return note2; } } // at this point, chord is a regular chord, not a grace chord // and we are looking for a note in the *next* chord (grace or regular) // calculate end of current note duration // but err on the safe side in case there is roundoff in tick count int endTick = chord->tick() + chord->actualTicks() - 1; while ((seg = seg->next1(Segment::Type::ChordRest))) { // skip ahead to end of current note duration as calculated above // but just in case, stop if we find element in current track if (seg->tick() < endTick && !seg->element(chord->track())) continue; for (int track = strack; track < etrack; ++track) { Element* e = seg->element(track); if (e == 0 || !e->isChord()) continue; Chord* c = toChord(e); // if there are grace notes before, try to tie to first one QVector<Chord*> gnb = c->graceNotesBefore(); if (!gnb.empty()) { Chord* gc = gnb[0]; Note* gn2 = gc->findNote(note->pitch()); if (gn2) return gn2; } int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
void Fingering::layout() { if (parent()) { Fraction tick = parent()->tick(); const Staff* st = staff(); if (st && st->isTabStaff(tick) && !st->staffType(tick)->showTabFingering()) { setbbox(QRectF()); return; } } TextBase::layout(); rypos() = 0.0; // handle placement below if (autoplace() && note()) { Note* n = note(); Chord* chord = n->chord(); bool voices = chord->measure()->hasVoices(chord->staffIdx()); bool tight = voices && chord->notes().size() == 1 && !chord->beam() && tid() != Tid::STRING_NUMBER; qreal headWidth = n->bboxRightPos(); // update offset after drag qreal rebase = 0.0; if (offsetChanged() != OffsetChange::NONE) rebase = rebaseOffset(); // temporarily exclude self from chord shape setAutoplace(false); if (layoutType() == ElementType::CHORD) { Stem* stem = chord->stem(); Segment* s = chord->segment(); Measure* m = s->measure(); qreal sp = spatium(); qreal md = minDistance().val() * sp; SysStaff* ss = m->system()->staff(chord->vStaffIdx()); Staff* vStaff = chord->staff(); // TODO: use current height at tick if (n->mirror()) rxpos() -= n->ipos().x(); rxpos() += headWidth * .5; if (placeAbove()) { if (tight) { if (chord->stem()) rxpos() -= 0.8 * sp; rypos() -= 1.5 * sp; } else { QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos()); SkylineLine sk(false); sk.add(r.x(), r.bottom(), r.width()); qreal d = sk.minDistance(ss->skyline().north()); qreal yd = 0.0; if (d > 0.0 && isStyled(Pid::MIN_DISTANCE)) yd -= d + height() * .25; // force extra space above staff & chord (but not other fingerings) qreal top; if (chord->up() && chord->beam() && stem) { top = stem->y() + stem->bbox().top(); } else { Note* un = chord->upNote(); top = qMin(0.0, un->y() + un->bbox().top()); } top -= md; qreal diff = (bbox().bottom() + ipos().y() + yd + n->y()) - top; if (diff > 0.0) yd -= diff; if (offsetChanged() != OffsetChange::NONE) { // user moved element within the skyline // we may need to adjust minDistance, yd, and/or offset bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height(); rebaseMinDistance(md, yd, sp, rebase, inStaff); } rypos() += yd; } } else { if (tight) { if (chord->stem()) rxpos() += 0.8 * sp; rypos() += 1.5 * sp; } else { QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos()); SkylineLine sk(true); sk.add(r.x(), r.top(), r.width()); qreal d = ss->skyline().south().minDistance(sk); qreal yd = 0.0; if (d > 0.0 && isStyled(Pid::MIN_DISTANCE)) yd += d + height() * .25; // force extra space below staff & chord (but not other fingerings) qreal bottom; if (!chord->up() && chord->beam() && stem) { bottom = stem->y() + stem->bbox().bottom(); } else { Note* dn = chord->downNote(); bottom = qMax(vStaff->height(), dn->y() + dn->bbox().bottom()); } bottom += md; qreal diff = bottom - (bbox().top() + ipos().y() + yd + n->y()); if (diff > 0.0) yd += diff; if (offsetChanged() != OffsetChange::NONE) { // user moved element within the skyline // we may need to adjust minDistance, yd, and/or offset bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height(); rebaseMinDistance(md, yd, sp, rebase, inStaff); } rypos() += yd; } } } else if (tid() == Tid::LH_GUITAR_FINGERING) { // place to left of note qreal left = n->shape().left(); if (left - n->x() > 0.0) rxpos() -= left; else rxpos() -= n->x(); } // for other fingering styles, do not autoplace // restore autoplace setAutoplace(true); } else if (offsetChanged() != OffsetChange::NONE) { // rebase horizontally too, as autoplace may have adjusted it rebaseOffset(false); } setOffsetChanged(false); }
void Glissando::layout() { Chord* chord = static_cast<Chord*>(parent()); if (chord == 0) return; Note* anchor2 = chord->upNote(); Segment* s = chord->segment(); s = s->prev1(); while (s) { if ((s->segmentType() & (Segment::SegChordRest)) && s->element(track())) break; s = s->prev1(); } if (s == 0) { qDebug("no segment for first note of glissando found\n"); return; } ChordRest* cr = static_cast<ChordRest*>(s->element(track())); if (cr == 0 || cr->type() != CHORD) { qDebug("no first note for glissando found, track %d", track()); return; } qreal _spatium = spatium(); Note* anchor1 = static_cast<Chord*>(cr)->upNote(); setPos(0.0, 0.0); adjustReadPos(); QPointF cp1 = anchor1->pagePos(); QPointF cp2 = anchor2->pagePos(); // line starting point int dots = static_cast<Chord*>(cr)->dots(); LedgerLine * ledLin = static_cast<Chord*>(cr)->ledgerLines(); // if dots, from right of last dot (assume a standard dot with of 1/4 sp) // if no dots, from right of ledger line, if any; from right of note head, if no ledger line qreal x1 = (dots ? anchor1->dot(dots-1)->pos().x() + anchor1->dot(dots-1)->width() : (ledLin ? ledLin->pos().x() + ledLin->width() : anchor1->headWidth()) ) - (cp2.x() - cp1.x()); // make relative to end note qreal y1 = anchor1->pos().y(); // line end point: left of note head qreal x2 = anchor2->pos().x(); qreal y2 = anchor2->pos().y(); // angle glissando between notes with the same pitch letter if (anchor1->line() == anchor2->line()) { int upDown = anchor2->pitch() - anchor1->pitch(); if (upDown != 0) upDown /= abs(upDown); y1 += _spatium * 0.25 * upDown; y2 -= _spatium * 0.25 * upDown; } // on TAB's, adjust lower end point from string line height to base of note height (= ca. half line spacing) if (chord->staff()->isTabStaff()) { qreal yOff = chord->staff()->lineDistance() * 0.3 * _spatium; if (anchor1->pitch() > anchor2->pitch()) { // descending glissando: y2 += yOff; y1 -= yOff; } // move ending point to base of note else { // ascending glissando: y1 += yOff; // move starting point to base of note y2 -= yOff; } } // shorten line to avoid end note ledger line ledLin=anchor2->chord()->ledgerLines(); if (ledLin) x2 = ledLin->pos().x(); // shorten line so it doesn't go through end note accidental or arpeggio if (Accidental* a = anchor2->accidental()) { x2 = a->pos().x() + a->userOff().x(); } if (Arpeggio* a = chord->arpeggio()) { x2 = a->pos().x() + a->userOff().x(); } QLineF fullLine(x1, y1, x2, y2); // shorten line on each side by offsets qreal xo = _spatium * .5; qreal yo = xo; // spatium() * .5; QPointF p1 = fullLine.pointAt(xo / fullLine.length()); QPointF p2 = fullLine.pointAt(1 - (yo / fullLine.length())); line = QLineF(p1, p2); qreal lw = _spatium * .15 * .5; QRectF r = QRectF(line.p1(), line.p2()).normalized(); setbbox(r.adjusted(-lw, -lw, lw, lw)); }
void Glissando::layout() { Chord* chord = static_cast<Chord*>(parent()); if (chord == 0) return; Note* anchor2 = chord->upNote(); Segment* s2 = chord->segment(); Segment* s1 = s2->prev1(); while (s1) { if ((s1->segmentType() & (Segment::Type::ChordRest)) && s1->element(track())) break; s1 = s1->prev1(); } if (s1 == 0) { qDebug("no segment for first note of glissando found"); return; } ChordRest* cr = static_cast<ChordRest*>(s1->element(track())); if (cr == 0 || cr->type() != Element::Type::CHORD) { qDebug("no first note for glissando found, track %d", track()); return; } qreal _spatium = spatium(); Note* anchor1 = static_cast<Chord*>(cr)->upNote(); setPos(0.0, 0.0); adjustReadPos(); // since line will be drawn relative to end note, // calculate offsets for start note coordinates relative to end note qreal x1off = 0.0; qreal y1off = 0.0; QPointF cp1 = anchor1->pagePos(); QPointF cp2 = anchor2->pagePos(); // layout of glissandi happens before we have staff positions within the system // so these "page" positions are not accurate across different staves // cheap partial fix for cross-staff glissandi: adjust vertical position according to difference in staffMove int moveDiff = anchor2->chord()->staffMove() - anchor1->chord()->staffMove(); if (moveDiff) y1off = moveDiff * 4.0 * _spatium; // now calculate offsets if (s1->system() == s2->system()) { // normal case - start and end note in same system x1off = cp2.x() - cp1.x(); if (!moveDiff) y1off = cp2.y() - cp1.y(); } else { // cheap partial fix for cross system glissandi: just draw a short line into end note // TODO: draw line coming out of start note on previous system x1off = 4.0 * _spatium; if (!moveDiff) y1off = anchor2->pos().y() - anchor1->pos().y(); } // line starting point int dots = static_cast<Chord*>(cr)->dots(); LedgerLine * ledLin = static_cast<Chord*>(cr)->ledgerLines(); // if dots, from right of last dot (assume a standard dot with of 1/4 sp) // if no dots, from right of ledger line, if any; from right of note head, if no ledger line qreal x1 = (dots && anchor1->dot(dots-1) ? anchor1->dot(dots-1)->pos().x() + anchor1->dot(dots-1)->width() : (ledLin ? ledLin->pos().x() + ledLin->width() : anchor1->headWidth()) ) - x1off; // make relative to end note qreal y1 = anchor2->y() - y1off; // line end point: left of note head qreal x2 = anchor2->pos().x(); qreal y2 = anchor2->pos().y(); // angle glissando between notes with the same pitch letter if (anchor1->line() == anchor2->line()) { int upDown = anchor2->pitch() - anchor1->pitch(); if (upDown != 0) upDown /= abs(upDown); y1 += _spatium * 0.25 * upDown; y2 -= _spatium * 0.25 * upDown; } // on TAB's, adjust lower end point from string line height to base of note height (= ca. half line spacing) if (chord->staff()->isTabStaff()) { qreal yOff = chord->staff()->lineDistance() * 0.3 * _spatium; if (anchor1->pitch() > anchor2->pitch()) { // descending glissando: y2 += yOff; y1 -= yOff; } // move ending point to base of note else { // ascending glissando: y1 += yOff; // move starting point to base of note y2 -= yOff; } } // shorten line to avoid end note ledger line ledLin = anchor2->chord()->ledgerLines(); if (ledLin) x2 = ledLin->pos().x(); // shorten line so it doesn't go through end note accidental or arpeggio if (Accidental* a = anchor2->accidental()) { x2 = a->pos().x() + a->userOff().x(); } if (Arpeggio* a = chord->arpeggio()) { x2 = a->pos().x() + a->userOff().x(); } QLineF fullLine(x1, y1, x2, y2); // shorten line on each side by offsets qreal xo = _spatium * .5; qreal yo = xo; // spatium() * .5; QPointF p1 = fullLine.pointAt(xo / fullLine.length()); QPointF p2 = fullLine.pointAt(1 - (yo / fullLine.length())); line = QLineF(p1, p2); qreal lw = _spatium * .15 * .5; QRectF r = QRectF(line.p1(), line.p2()).normalized(); setbbox(r.adjusted(-lw, -lw, lw, lw)); }