Example #1
0
void AccidentalState::init(const KeySigEvent& keySig, ClefType clef)
      {
      if (keySig.custom()) {
            memset(state, 2, MAX_ACC_STATE);
            for (const KeySym& s : keySig.keySymbols()) {
                  AccidentalVal a = sym2accidentalVal(s.sym);
                  int line = int(s.spos.y() * 2);
                  int idx       = relStep(line, clef) % 7;
                  for (int octave = 0; octave < (11 * 7); octave += 7) {
                        int i = idx + octave ;
                        if (i >= MAX_ACC_STATE)
                              break;
                        state[i] = int(a) + 2;
                        }
                  }
            }
      else {
            init(keySig.key());
            }
      }
Example #2
0
int relStep(int pitch, int tpc, ClefType clef)
      {
      return relStep(absStep(tpc, pitch), clef);
      }
Example #3
0
void Ambitus::layout()
      {
      int         bottomLine, topLine;
      ClefType    clf;
      qreal       headWdt     = headWidth();
      Key         key;
      qreal       lineDist;
      int         numOfLines;
      Segment*    segm        = segment();
      qreal       _spatium    = spatium();
      Staff*      stf         = nullptr;
      if (segm && track() > -1) {
            int tick    = segm->tick();
            stf         = score()->staff(staffIdx());
            lineDist    = stf->lineDistance(tick) * _spatium;
            numOfLines  = stf->lines(tick);
            clf         = stf->clef(tick);
            }
      else {                              // for use in palettes
            lineDist    = _spatium;
            numOfLines  = 3;
            clf         = ClefType::G;
            }

      //
      // NOTEHEADS Y POS
      //
      // if pitch == INVALID_PITCH oor tpc == INALID_TPC, set to some default:
      // for use in palettes and when actual range cannot be calculated (new ambitus or no notes in staff)
      //
      qreal xAccidOffTop    = 0;
      qreal xAccidOffBottom = 0;
      if (stf)
            key = stf->key(segm->tick());
      else
            key = Key::C;

      // top notehead
      if (_topPitch == INVALID_PITCH || _topTpc == Tpc::TPC_INVALID)
            _topPos.setY(0);                          // if uninitialized, set to top staff line
      else {
            topLine  = absStep(_topTpc, _topPitch);
            topLine  = relStep(topLine, clf);
            _topPos.setY(topLine * lineDist * 0.5);
            // compute accidental
            AccidentalType accidType;
            // if (13 <= (tpc - key) <= 19) there is no accidental)
            if (_topTpc - int(key) >= 13 && _topTpc - int(key) <= 19)
                  accidType = AccidentalType::NONE;
            else {
                  AccidentalVal accidVal = AccidentalVal( (_topTpc - Tpc::TPC_MIN) / TPC_DELTA_SEMITONE - 2 );
                  accidType = Accidental::value2subtype(accidVal);
                  if (accidType == AccidentalType::NONE)
                        accidType = AccidentalType::NATURAL;
                  }
            _topAccid.setAccidentalType(accidType);
            if (accidType != AccidentalType::NONE)
                  _topAccid.layout();
            else
                  _topAccid.setbbox(QRect());
            _topAccid.rypos() = _topPos.y();
            }

      // bottom notehead
      if (_bottomPitch == INVALID_PITCH || _bottomTpc == Tpc::TPC_INVALID)
            _bottomPos.setY( (numOfLines-1) * lineDist);          // if uninitialized, set to last staff line
      else {
            bottomLine  = absStep(_bottomTpc, _bottomPitch);
            bottomLine  = relStep(bottomLine, clf);
            _bottomPos.setY(bottomLine * lineDist * 0.5);
            // compute accidental
            AccidentalType accidType;
            if (_bottomTpc - int(key) >= 13 && _bottomTpc - int(key) <= 19)
                  accidType = AccidentalType::NONE;
            else {
                  AccidentalVal accidVal = AccidentalVal( (_bottomTpc - Tpc::TPC_MIN) / TPC_DELTA_SEMITONE - 2 );
                  accidType = Accidental::value2subtype(accidVal);
                  if (accidType == AccidentalType::NONE)
                        accidType = AccidentalType::NATURAL;
                  }
            _bottomAccid.setAccidentalType(accidType);
            if (accidType != AccidentalType::NONE)
                  _bottomAccid.layout();
            else
                  _bottomAccid.setbbox(QRect());
            _bottomAccid.rypos() = _bottomPos.y();
            }

      //
      // NOTEHEAD X POS
      //
      // Note: manages colliding accidentals
      //
      qreal accNoteDist = point(score()->styleS(Sid::accidentalNoteDistance));
      xAccidOffTop      = _topAccid.width() + accNoteDist;
      xAccidOffBottom   = _bottomAccid.width() + accNoteDist;

      // if top accidental extends down more than bottom accidental extends up,
      // AND ambitus is not leaning right, bottom accidental needs to be displaced
      bool collision =
            (_topAccid.ipos().y() + _topAccid.bbox().y() + _topAccid.height()
                   > _bottomAccid.ipos().y() + _bottomAccid.bbox().y() )
            && _dir != MScore::DirectionH::RIGHT;
      if (collision) {
            // displace bottom accidental (also attempting to 'undercut' flats)
            xAccidOffBottom = xAccidOffTop +
                  ((_bottomAccid.accidentalType() == AccidentalType::FLAT
                        || _bottomAccid.accidentalType() == AccidentalType::FLAT2
                        || _bottomAccid.accidentalType() == AccidentalType::NATURAL)
                  ? _bottomAccid.width() * 0.5 : _bottomAccid.width());
            }

      switch (_dir) {
            case MScore::DirectionH::AUTO:               // noteheads one above the other
                  // left align noteheads and right align accidentals 'hanging' on the left
                  _topPos.setX(0.0);
                  _bottomPos.setX(0.0);
                  _topAccid.rxpos()       = - xAccidOffTop;
                  _bottomAccid.rxpos()    = - xAccidOffBottom;
                  break;
            case MScore::DirectionH::LEFT:               // top notehead at the left of bottom notehead
                  // place top notehead at left margin; bottom notehead at right of top head;
                  // top accid. 'hanging' on left of top head and bottom accid. 'hanging' at left of bottom head
                  _topPos.setX(0.0);
                  _bottomPos.setX(headWdt);
                  _topAccid.rxpos() = - xAccidOffTop;
                  _bottomAccid.rxpos() = collision ? - xAccidOffBottom : headWdt - xAccidOffBottom;
                  break;
            case MScore::DirectionH::RIGHT:              // top notehead at the right of bottom notehead
                  // bottom notehead at left margin; top notehead at right of bottomnotehead
                  // top accid. 'hanging' on left of top head and bottom accid. 'hanging' at left of bottom head
                  _bottomPos.setX(0.0);
                  _topPos.setX(headWdt);
                  _bottomAccid.rxpos() = - xAccidOffBottom;
                  _topAccid.rxpos() = headWdt - xAccidOffTop;
                  break;
            }

      // compute line from top note centre to bottom note centre
      QLineF fullLine(_topPos.x() + headWdt*0.5, _topPos.y(),
            _bottomPos.x() + headWdt*0.5, _bottomPos.y());
      // shorten line on each side by offsets
      qreal yDelta = _bottomPos.y() - _topPos.y();
      if (yDelta != 0.0) {
            qreal off = _spatium * LINEOFFSET_DEFAULT;
            QPointF p1 = fullLine.pointAt(off / yDelta);
            QPointF p2 = fullLine.pointAt(1 - (off / yDelta));
            _line = QLineF(p1, p2);
            }
      else
            _line = fullLine;

      QRectF headRect = QRectF(0, -0.5*_spatium, headWdt, 1*_spatium);
      setbbox(headRect.translated(_topPos).united(headRect.translated(_bottomPos))
            .united(_topAccid.bbox().translated(_topAccid.ipos()))
            .united(_bottomAccid.bbox().translated(_bottomAccid.ipos()))
            );
      }