Exemple #1
0
Element* Rest::drop(const DropData& data)
      {
      Element* e = data.element;
      switch (e->type()) {
            case ARTICULATION:
                  if (e->subtype() == Articulation_Fermata)
                        score()->addArticulation(this, (Articulation*)e);
                  return 0;
            case ICON:
                  {
                  switch(e->subtype()) {
                        case ICON_SBEAM:
                              score()->undoChangeBeamMode(this, BEAM_BEGIN);
                              break;
                        case ICON_MBEAM:
                              score()->undoChangeBeamMode(this, BEAM_MID);
                              break;
                        case ICON_NBEAM:
                              score()->undoChangeBeamMode(this, BEAM_NO);
                              break;
                        case ICON_BEAM32:
                              score()->undoChangeBeamMode(this, BEAM_BEGIN32);
                              break;
                        case ICON_BEAM64:
                              score()->undoChangeBeamMode(this, BEAM_BEGIN64);
                              break;
                        case ICON_AUTOBEAM:
                              score()->undoChangeBeamMode(this, BEAM_AUTO);
                              break;
                        }
                  }
                  delete e;
                  break;

            case CHORD:
                  {
                  Chord* c      = static_cast<Chord*>(e);
                  Note* n       = c->upNote();
                  Direction dir = c->stemDirection();
                  score()->select(0, SELECT_SINGLE, 0);
                  NoteVal nval;
                  nval.pitch = n->pitch();
                  nval.headGroup = n->headGroup();
                  Fraction d = score()->inputState().duration().fraction();
                  if (!d.isZero()) {
                        Segment* seg = score()->setNoteRest(segment(), track(), nval, d, dir);
                        if (seg) {
                              ChordRest* cr = static_cast<ChordRest*>(seg->element(track()));
                              if (cr)
                                    score()->nextInputPos(cr, true);
                              }
                        }
                  delete e;
                  }
                  break;
            default:
                  return ChordRest::drop(data);
            }
      return 0;
      }
Exemple #2
0
QLineF Arpeggio::dragAnchor() const
      {
      Chord* c = chord();
      if (c)
            return QLineF(pagePos(), c->upNote()->pagePos());
      return QLineF();
      }
Exemple #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));
      }
Exemple #4
0
void TestNote::grace()
      {
      Score* score = readScore(DIR + "grace.mscx");
      score->doLayout();
      Chord* chord = score->firstMeasure()->findChord(0, 0);
      Note* note = chord->upNote();

      // create
      score->setGraceNote(chord, note->pitch(), NoteType::APPOGGIATURA, MScore::division/2);
      Chord* gc = chord->graceNotes().first();
      Note* gn = gc->notes().first();
//      Note* n = static_cast<Note*>(writeReadElement(gn));
//      QCOMPARE(n->noteType(), NoteType::APPOGGIATURA);
//      delete n;

      // tie
      score->startCmd();
      score->select(gn);
      score->cmdAddTie();
      score->endCmd();
//      n = static_cast<Note*>(writeReadElement(gn));
//      QVERIFY(n->tieFor() != 0);
//      delete n;

      // tremolo
      score->startCmd();
      Tremolo* tr = new Tremolo(score);
      tr->setTremoloType(TremoloType::R16);
      tr->setParent(gc);
      tr->setTrack(gc->track());
      score->undoAddElement(tr);
      score->endCmd();
//      Chord* c = static_cast<Chord*>(writeReadElement(gc));
//      QVERIFY(c->tremolo() != 0);
//      delete c;

      // articulation
      score->startCmd();
      Articulation* ar = new Articulation(score);
      ar->setArticulationType(ArticulationType::Sforzatoaccent);
      ar->setParent(gc);
      ar->setTrack(gc->track());
      score->undoAddElement(ar);
      score->endCmd();
//      c = static_cast<Chord*>(writeReadElement(gc));
//      QVERIFY(c->articulations().size() == 1);
//      delete c;

      QVERIFY(saveCompareScore(score, "grace-test.mscx", DIR + "grace-ref.mscx"));

      }
Exemple #5
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));
      }
Exemple #6
0
Element* Rest::drop(const DropData& data)
      {
      Element* e = data.element;
      switch (e->type()) {
            case ElementType::ARTICULATION:
                  {
                  Articulation* a = static_cast<Articulation*>(e);
                  if (a->articulationType() != ArticulationType::Fermata
                     || !score()->addArticulation(this, a)) {
                        delete e;
                        e = 0;
                        }
                  }
                  return e;

            case ElementType::CHORD:
                  {
                  Chord* c      = static_cast<Chord*>(e);
                  Note* n       = c->upNote();
                  Direction dir = c->stemDirection();
                  // score()->select(0, SelectType::SINGLE, 0);
                  NoteVal nval;
                  nval.pitch = n->pitch();
                  nval.headGroup = n->headGroup();
                  Fraction d = score()->inputState().duration().fraction();
                  if (!d.isZero()) {
                        Segment* seg = score()->setNoteRest(segment(), track(), nval, d, dir);
                        if (seg) {
                              ChordRest* cr = static_cast<ChordRest*>(seg->element(track()));
                              if (cr)
                                    score()->nextInputPos(cr, true);
                              }
                        }
                  delete e;
                  }
                  break;
            case ElementType::REPEAT_MEASURE:
                  delete e;
                  if (durationType().type() == TDuration::DurationType::V_MEASURE) {
                        measure()->cmdInsertRepeatMeasure(staffIdx());
                        }
                  break;
            default:
                  return ChordRest::drop(data);
            }
      return 0;
      }
Exemple #7
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();
      }
Exemple #8
0
Element* Rest::drop(const DropData& data)
      {
      Element* e = data.element;
      switch (e->type()) {
            case ARTICULATION:
                  {
                  Articulation* a = static_cast<Articulation*>(e);
                  if (a->articulationType() != Articulation_Fermata
                     || !score()->addArticulation(this, a)) {
                        delete e;
                        e = 0;
                        }
                  }
                  return e;

            case CHORD:
                  {
                  Chord* c      = static_cast<Chord*>(e);
                  Note* n       = c->upNote();
                  MScore::Direction dir = c->stemDirection();
                  // score()->select(0, SELECT_SINGLE, 0);
                  NoteVal nval;
                  nval.pitch = n->pitch();
                  nval.headGroup = n->headGroup();
                  Fraction d = score()->inputState().duration().fraction();
                  if (!d.isZero()) {
                        Segment* seg = score()->setNoteRest(segment(), track(), nval, d, dir);
                        if (seg) {
                              ChordRest* cr = static_cast<ChordRest*>(seg->element(track()));
                              if (cr)
                                    score()->nextInputPos(cr, true);
                              }
                        }
                  delete e;
                  }
                  break;
            default:
                  return ChordRest::drop(data);
            }
      return 0;
      }
Exemple #9
0
void Stem::layout()
      {
      qreal l = _len + _userLen;
      if (up())
            l = -l;
      Staff* st = staff();
      qreal lw5  = point(score()->styleS(ST_stemWidth)) * .5;
      QPointF p1(0.0, 0.0);
      QPointF p2(0.0, l);
      if (st) {
            // if TAB, use simplified positioning
            if (st->isTabStaff()) {
                  p1.rx() = -lw5;
                  p2.rx() = -lw5;
                  }
            // for any other staff type, use standard positioning
            else if (chord()) {
                  // adjust P1 for note head
                  Chord* c = chord();
                  if (c->up()) {
                        Note* n   = c->downNote();
                        p1 = symbols[score()->symIdx()][n->noteHead()].attach(n->magS());
                        p1.rx() = -lw5;
                        p2.rx() = -lw5;
                        }
                  else {
                        Note* n = c->upNote();
                        p1 = -symbols[score()->symIdx()][n->noteHead()].attach(n->magS());
                        p1.rx() = lw5;
                        p2.rx() = lw5;
                        }
                  }
            }
      line.setP1(p1);
      line.setP2(p2);

      // compute bounding rectangle
      QRectF r(line.p1(), line.p2());
      setbbox(r.normalized().adjusted(-lw5, -lw5, lw5, lw5));
      }
Exemple #10
0
void Slur::slurPos(SlurPos* sp)
      {
      qreal _spatium = spatium();
      Element* e1 = startElement();
      Element* e2 = endElement();

      if (e2 == 0) {
            sp->p1 = e1->pagePos();
            sp->p1.rx() += e1->width();
            sp->p2 = sp->p1;
            sp->p2.rx() += 5 * _spatium;
            sp->system1 = static_cast<ChordRest*>(e1)->measure()->system();
            sp->system2 = sp->system1;
            return;
            }

      if ((e1->type() != CHORD) || (e2->type() != CHORD)) {
            sp->p1 = e1->pagePos();
            sp->p2 = e2->pagePos();
            sp->p1.rx() += e1->width();
            sp->p2.rx() += e2->width();
            sp->system1 = static_cast<ChordRest*>(e1)->measure()->system();
            sp->system2 = static_cast<ChordRest*>(e2)->measure()->system();
            return;
            }
      Chord* sc   = static_cast<Chord*>(e1);
      Chord* ec   = static_cast<Chord*>(e2);
      Note* note1 = _up ? sc->upNote() : sc->downNote();
      Note* note2 = _up ? ec->upNote() : ec->downNote();

      sp->system1 = sc->measure()->system();
      sp->system2 = ec->measure()->system();
      sp->p1      = sc->pagePos() - sp->system1->pagePos();
      sp->p2      = ec->pagePos() - sp->system2->pagePos();

      qreal xo, yo;

      Stem* stem1 = sc->stem();
      Stem* stem2 = ec->stem();

      enum SlurAnchor {
            SA_NONE, SA_STEM
            };
      SlurAnchor sa1 = SA_NONE;
      SlurAnchor sa2 = SA_NONE;
      if ((sc->up() == ec->up()) && !sc->beam() && !ec->beam() && (_up == sc->up())) {
            if (stem1)
                  sa1 = SA_STEM;
            if (stem2)
                  sa2 = SA_STEM;
            }

      qreal __up = _up ? -1.0 : 1.0;
      qreal hw   = note1->headWidth();
      switch (sa1) {
            case SA_STEM:
                  sp->p1 += sc->stemPosBeam() - sc->pagePos() + sc->stem()->p2();
                  sp->p1 += QPointF(0.35 * _spatium, 0.25 * _spatium);
                  break;
            case SA_NONE:
                  break;
            }
      switch(sa2) {
            case SA_STEM:
                  sp->p2 += ec->stemPosBeam() - ec->pagePos() + ec->stem()->p2();
                  sp->p2 += QPointF(-0.35 * _spatium, 0.25 * _spatium);
                  break;
            case SA_NONE:
                  break;
            }

      //
      // default position:
      //    horizontal: middle of note head
      //    vertical:   _spatium * .4 above/below note head
      //
      //------p1
      bool stemPos = false;   // p1 starts at chord stem side
      yo = note1->pos().y() + _spatium * .9 * __up;
      xo = hw * .5;

      if (stem1) {
            Beam* beam1 = sc->beam();
            if (beam1 && (beam1->elements().back() != sc) && (sc->up() == _up)) {
                  qreal sh = stem1->height() + _spatium;
                  yo       = sc->downNote()->pos().y() + sh * __up;
                  xo       = stem1->pos().x();
                  stemPos  = true;
                  }
            else {
                  if (sc->up() && _up)
                        xo = hw + _spatium * .3;
                  //
                  // handle case: stem up   - stem down
                  //              stem down - stem up
                  //
                  if ((sc->up() != ec->up()) && (sc->up() == _up)) {
                        Note* n1  = sc->up() ? sc->downNote() : sc->upNote();
                        Note* n2  = ec->up() ? ec->downNote() : ec->upNote();
                        qreal yd  = n2->pos().y() - n1->pos().y();

                        yd *= .5;

                        qreal sh = stem1->height();    // limit y move
                        if (yd > 0.0) {
                              if (yd > sh)
                                    yd = sh;
                              }
                        else {
                              if (yd < - sh)
                                    yd = -sh;
                              }
                        stemPos = true;
                        if ((_up && (yd < -_spatium)) || (!_up && (yd > _spatium)))
                              yo += yd;
                        }
                  else if (sc->up() != _up)
                        yo = fixArticulations(yo, sc, __up);
                  }
            }

      if (sa1 == SA_NONE)
            sp->p1 += QPointF(xo, yo);

      //------p2
      xo = hw * .5;
      yo = note2->pos().y() + _spatium * .9 * __up;

      if (stem2) {
            Beam* beam2 = ec->beam();
            if ((stemPos && (sc->up() == ec->up()))
               || (beam2
                 && (!beam2->elements().isEmpty())
                 && (beam2->elements().front() != ec)
                 && (ec->up() == _up)
                 && (sc->noteType() == NOTE_NORMAL)
                 )
                  ) {
                  qreal sh = stem2->height() + _spatium;
                  if (_up)
                        yo = ec->downNote()->pos().y() - sh;
                  else
                        yo = ec->upNote()->pos().y() + sh;
                  xo = stem2->pos().x();
                  }
            else if (!ec->up() && !_up)
                  xo = -_spatium * .3 + note2->x();
            //
            // handle case: stem up   - stem down
            //              stem down - stem up
            //
            if ((sc->up() != ec->up()) && (ec->up() == _up)) {
                  Note* n1 = sc->up() ? sc->downNote() : sc->upNote();
                  Note* n2 = ec->up() ? ec->downNote() : ec->upNote();
                  qreal yd = n2->pos().y() - n1->pos().y();

                  yd *= .5;

                  qreal mh = stem2->height();    // limit y move
                  if (yd > 0.0) {
                        if (yd > mh)
                              yd = mh;
                        }
                  else {
                        if (yd < - mh)
                              yd = -mh;
                        }

                  if ((_up && (yd > _spatium)) || (!_up && (yd < -_spatium)))
                        yo -= yd;
                  }
            else if (ec->up() != _up)
                  yo = fixArticulations(yo, ec, __up);
            }

      if (sa2 == SA_NONE)
            sp->p2 += QPointF(xo, yo);
      }
Exemple #11
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);
      }
Exemple #12
0
Note* Glissando::guessFinalNote(Chord* chord)
      {
      switch (chord->noteType()) {
//            case NoteType::INVALID:
//                  return nullptr;
            // for grace notes before, return top note of parent chord
            // TODO : if the grace-before is not the LAST ONE, this still returns the main note
            //    which is probably not correct; however a glissando between two grace notes
            //    probably makes little sense.
            case NoteType::ACCIACCATURA:
            case NoteType::APPOGGIATURA:
            case NoteType::GRACE4:
            case NoteType::GRACE16:
            case NoteType::GRACE32:
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        return static_cast<Chord*>(chord->parent())->upNote();
                  else                          // no parent or parent is not a chord?
                        return nullptr;
            // for grace notes after, next chord is next chord of parent chord
            // TODO : same note as case above!
            case NoteType::GRACE8_AFTER:
            case NoteType::GRACE16_AFTER:
            case NoteType::GRACE32_AFTER:
                  // move unto parent chord and proceed to standard case
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        chord = static_cast<Chord*>(chord->parent());
                  else
                        return nullptr;
                  break;
            case NoteType::NORMAL:
                  {
                  // if chord has grace notes after, the first one is the next note
                  QVector<Chord*>graces = chord->graceNotesAfter();
                  if (graces.size() > 0)
                        return graces.first()->upNote();
                  }
                  break;
            default:
                  break;
            }

      // standard case (NORMAL or grace after chord)

      // if parent not a segment, can't locate a target note
      if (chord->parent()->type() != Element::Type::SEGMENT)
            return nullptr;

      // look for first ChordRest segment after initial note is elapsed
      Segment*    segm        = chord->score()->tick2rightSegment(chord->tick() + chord->actualTicks());
      int         chordTrack  = chord->track();
      Part*       part        = chord->part();
      while (segm) {
            // if next segment is a ChordRest segment
            if (segm->segmentType() == Segment::Type::ChordRest) {
                  Chord* target = nullptr;

                  // look for a Chord in the same track
                  if (segm->element(chordTrack) && segm->element(chordTrack)->type() == Element::Type::CHORD)
                        target = static_cast<Chord*>(segm->element(chordTrack));
                  else              // if no same track, look for other chords in the same instrument
                        for (Element* currChord : segm->elist())
                              if (currChord != nullptr && currChord->type() == Element::Type::CHORD
                                          && static_cast<Chord*>(currChord)->part() == part) {
                                    target = static_cast<Chord*>(currChord);
                                    break;
                                    }

                  // if we found a target next chord
                  if (target) {
                        // if chord has grace notes before, the first one is the next note
                        QVector<Chord*>graces = target->graceNotesBefore();
                        if (graces.size() > 0)
                              return graces.first()->upNote();
                        return target->upNote();      // if no grace before, return top note
                        }
                  }
            segm = segm->next1();
            }
      qDebug("no second note for glissando found");
      return nullptr;
      }
Exemple #13
0
Note* Glissando::guessInitialNote(Chord* chord)
      {
      switch (chord->noteType()) {
//            case NoteType::INVALID:
//                  return nullptr;
            // for grace notes before, previous chord is previous chord of parent chord
            case NoteType::ACCIACCATURA:
            case NoteType::APPOGGIATURA:
            case NoteType::GRACE4:
            case NoteType::GRACE16:
            case NoteType::GRACE32:
                  // move unto parent chord and proceed to standard case
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        chord = static_cast<Chord*>(chord->parent());
                  else
                        return nullptr;
                  break;
            // for grace notes after, return top note of parent chord
            case NoteType::GRACE8_AFTER:
            case NoteType::GRACE16_AFTER:
            case NoteType::GRACE32_AFTER:
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        return static_cast<Chord*>(chord->parent())->upNote();
                  else                          // no parent or parent is not a chord?
                        return nullptr;
            case NoteType::NORMAL:
                  {
                  // if chord has grace notes before, the last one is the previous note
                  QVector<Chord*>graces = chord->graceNotesBefore();
                  if (graces.size() > 0)
                        return graces.last()->upNote();
                  }
                  break;                        // else process to standard case
            default:
                  break;
            }

      // standard case (NORMAL or grace before chord)

      // if parent not a segment, can't locate a target note
      if (chord->parent()->type() != Element::Type::SEGMENT)
            return nullptr;

      int         chordTrack  = chord->track();
      Segment*    segm        = chord->segment();
      Part*       part        = chord->part();
      if (segm != nullptr)
            segm = segm->prev1();
      while (segm) {
            // if previous segment is a ChordRest segment
            if (segm->segmentType() == Segment::Type::ChordRest) {
                  Chord* target = nullptr;
                  // look for a Chord in the same track
                  if (segm->element(chordTrack) && segm->element(chordTrack)->type() == Element::Type::CHORD)
                        target = static_cast<Chord*>(segm->element(chordTrack));
                  else              // if no same track, look for other chords in the same instrument
                        for (Element* currChord : segm->elist())
                              if (currChord != nullptr && currChord->type() == Element::Type::CHORD
                                          && static_cast<Chord*>(currChord)->part() == part) {
                                    target = static_cast<Chord*>(currChord);
                                    break;
                                    }
                  // if we found a target previous chord
                  if (target) {
                        // if chord has grace notes after, the last one is the previous note
                        QVector<Chord*>graces = target->graceNotesAfter();
                        if (graces.size() > 0)
                              return graces.last()->upNote();
                        return target->upNote();      // if no grace after, return top note
                        }
                  }
            segm = segm->prev1();
            }
      qDebug("no first note for glissando found");
      return nullptr;
      }
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));
      }
Exemple #15
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));
      }