예제 #1
0
파일: utils.cpp 프로젝트: CFrei/MuseScore
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;
      }
예제 #2
0
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;
      }
예제 #3
0
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));
      }
예제 #4
0
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));
      }
예제 #5
0
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();
      }
예제 #6
0
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;
      }
예제 #7
0
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;
      }
예제 #8
0
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);
      }
예제 #9
0
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));
      }
예제 #10
0
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));
      }