Пример #1
0
bool Articulation::setProperty(P_ID propertyId, const QVariant& v)
      {
      score()->addRefresh(canvasBoundingRect());
      switch (propertyId) {
            case P_DIRECTION:
                  setDirection(MScore::Direction(v.toInt()));
                  break;
            case P_ARTICULATION_ANCHOR:
                  anchorStyle = PropertyStyle::UNSTYLED;
                  setAnchor(ArticulationAnchor(v.toInt()));
                  break;
            case P_TIME_STRETCH:
                  setTimeStretch(v.toDouble());
                  score()->fixTicks();
                  break;
            default:
                  return Element::setProperty(propertyId, v);
            }
      score()->addRefresh(canvasBoundingRect());

      // layout:
      if (chordRest())
            chordRest()->layoutArticulations();
      else if (parent() && parent()->type() == BAR_LINE)
            static_cast<BarLine*>(parent())->layout();

      score()->addRefresh(canvasBoundingRect());
      score()->setLayoutAll(false);       //DEBUG
      return true;
      }
Пример #2
0
void Articulation::reset()
      {
      if (_direction != MScore::AUTO)
            score()->undoChangeProperty(this, P_DIRECTION, int(MScore::AUTO));
      ArticulationAnchor a = score()->style()->articulationAnchor(articulationType());
      if (_anchor != a)
            score()->undoChangeProperty(this, P_ARTICULATION_ANCHOR, int(a));
      Element::reset();
      if (chordRest())
            chordRest()->layoutArticulations();
      score()->addRefresh(canvasBoundingRect());
      }
Пример #3
0
bool Articulation::setProperty(P_ID propertyId, const QVariant& v)
      {
      score()->addRefresh(canvasBoundingRect());
      switch (propertyId) {
            case P_ID::DIRECTION:
                  setDirection(MScore::Direction(v.toInt()));
                  break;
            case P_ID::ARTICULATION_ANCHOR:
                  anchorStyle = PropertyStyle::UNSTYLED;
                  setAnchor(ArticulationAnchor(v.toInt()));
                  break;
            case P_ID::PLAY:
                  setPlayArticulation(v.toBool());
                  break;
            case P_ID::ORNAMENT_STYLE:
                  setOrnamentStyle(MScore::OrnamentStyle(v.toInt()));
                  break;
            case P_ID::TIME_STRETCH:
                  setTimeStretch(v.toDouble());
                  score()->fixTicks();
                  break;
            case P_ID::USER_OFF:
                  setUserOff(v.toPointF());
                  if (_articulationType == ArticulationType::Tenuto) {
                        // moving a tenuto may move slurs:
                        score()->setLayoutAll(true);
                        }
                  return true;
            default:
                  return Element::setProperty(propertyId, v);
            }

      // layout:
      if (chordRest())
            chordRest()->layoutArticulations();
      else if (parent() && parent()->type() == Element::Type::BAR_LINE)
            static_cast<BarLine*>(parent())->layout();

      score()->addRefresh(canvasBoundingRect());
      score()->setLayoutAll(false);       // DEBUG
      canvasBoundingRectChanged();        // rebuild bsp tree
      return true;
      }
Пример #4
0
Segment* Articulation::segment() const
      {
      ChordRest* cr = chordRest();
      if (!cr)
            return 0;

      Segment* s = 0;
      if (cr->isGrace()) {
            if (cr->parent())
                  s = toSegment(cr->parent()->parent());
            }
      else
            s = toSegment(cr->parent());

      return s;
      }
Пример #5
0
bool Lyrics::isMelisma() const
      {
      // entered as melisma using underscore?
      if (_ticks > 0)
            return true;

      // hyphenated?
      // if so, it is a melisma only if there is no lyric in same verse on next CR
      if (_syllabic == Syllabic::BEGIN || _syllabic == Syllabic::MIDDLE) {
            // find next CR on same track and check for existence of lyric in same verse
            ChordRest* cr = chordRest();
            Segment* s = cr->segment()->next1();
            ChordRest* ncr = s ? s->nextChordRest(cr->track()) : nullptr;
            if (ncr && !ncr->lyrics(_no))
                  return true;
            }

      // default - not a melisma
      return false;
}
Пример #6
0
void FiguredBass::layout()
      {
      if (!styled())
            setTextStyle(TEXT_STYLE_FIGURED_BASS);
      Lyrics::layout();
      qreal lh = lineSpacing() * score()->styleD(ST_figuredBassLineHeight);

      System* sys = measure()->system();
      if (sys == 0) {
            qDebug("lyrics layout: no system!");
            abort();
            }
      const QList<Lyrics*>* ll = &(chordRest()->lyricsList());

      int line = ll->indexOf(this);
      qreal y  = lh * line + point(score()->styleS(ST_figuredBassDistance))
                 + sys->staff(staffIdx())->bbox().height();
      QString s = getText();
      qreal x = symbols[score()->symIdx()][quartheadSym].width(magS()) * .5;
      QFontMetricsF fm(style().font(spatium()));
      for (int i = 0; i < s.size(); ++i) {
            if (s[i].isNumber()) {
                  if (i)
                        x += -fm.width(s.left(i));
                  int startIdx = i;
                  for (; i < s.size(); ++i) {
                        if (!s[i].isNumber())
                              break;
                        }
                  x += -(fm.width(s.mid(startIdx, i - startIdx)) * .5);
                  break;
                  }
            }
      x -= spatium() * .25;  // DEBUG
      setPos(x, y);
      }
Пример #7
0
Segment* Articulation::segment() const
      {
      ChordRest* cr = chordRest();
      return static_cast<Segment*>(cr ? cr->parent() : 0);
      }
Пример #8
0
void Lyrics::layout1()
      {
      setPos(textStyle().offset(spatium()));
      Text::layout1();
      if (!parent()) // palette & clone trick
          return;

      ChordRest* cr = chordRest();
      const QList<Lyrics*>* ll = &(cr->lyricsList());

      qreal lh = lineSpacing() * score()->styleD(StyleIdx::lyricsLineHeight);
      int line = ll->indexOf(this);
      qreal y  = lh * line + point(score()->styleS(StyleIdx::lyricsDistance));
      qreal x  = 0.0;

      //
      // parse leading verse number and/or punctuation, so we can factor it into layout separately
      // TODO: provide a way to disable this
      //
      bool hasNumber = false; // _verseNumber;
      qreal adjust = 0.0;
      QString s = plainText(true);
      // find:
      // 1) string of numbers and non-word characters at start of syllable
      // 2) at least one other character (indicating start of actual lyric)
      QRegularExpression leadingPattern("(^[\\d\\W]+)([^\\d\\W]+)");
      QRegularExpressionMatch leadingMatch = leadingPattern.match(s);
      if (leadingMatch.hasMatch()) {
            // leading string
            QString s1 = leadingMatch.captured(1);
            // actual lyric
            //QString s2 = leadingMatch.captured(2);
            Text leading(*this);
            leading.setPlainText(s1);
            leading.layout1();
            adjust = leading.width();
            if (!s1.isEmpty() && s1[0].isDigit())
                  hasNumber = true;
            }

      if (textStyle().align() & AlignmentFlags::HCENTER) {
            //
            // center under notehead, not origin
            // however, lyrics that are melismas or have verse numbers will be forced to left alignment
            // TODO: provide a way to disable the automatic left alignment
            //
            qreal maxWidth;
            if (cr->type() == Element::Type::CHORD)
                  maxWidth = static_cast<Chord*>(cr)->maxHeadWidth();
            else
                  maxWidth = cr->width();       // TODO: exclude ledger line for multivoice rest?
            qreal nominalWidth = symWidth(SymId::noteheadBlack);
            if (!isMelisma() && !hasNumber)     // center under notehead
                  x +=  nominalWidth * .5 - cr->x() - adjust * 0.5;
            else                                // force left alignment
                  x += (width() + nominalWidth - maxWidth) * .5 - cr->x() - adjust;
            }
      else {
            // even for left aligned syllables, ignore leading verse numbers and/or punctuation
            x -= adjust;
            }

      rxpos() += x;
      rypos() += y;

      if (_ticks > 0 || _syllabic == Syllabic::BEGIN || _syllabic == Syllabic::MIDDLE) {
            if (_separator == nullptr) {
                  _separator = new LyricsLine(score());
                  _separator->setTick(cr->tick());
                  score()->addUnmanagedSpanner(_separator);
                  }
            _separator->setParent(this);
            _separator->setTick(cr->tick());
            _separator->setTrack(track());
            _separator->setTrack2(track());
#if defined(USE_FONT_DASH_METRIC)
            // if font parameters different from font cached values, compute new dash values from font metrics
            if (textStyle().family() != g_fontFamily && textStyle().size() != g_fontSize) {
                  QFontMetricsF     fm    = textStyle().fontMetrics(spatium());
                  QRectF            r     = fm.tightBoundingRect("\u2013");   // U+2013 EN DASH
                  g_cachedDashY           = _dashY          = r.y() + (r.height() * HALF);
                  g_cachedDashLength      = _dashLength     = r.width();
   #if defined(USE_FONT_DASH_TICKNESS)
                  g_cachedDashThickness   = _dashThickness  = r.height();
   #endif
                  g_fontFamily            = textStyle().family();
                  g_fontSize              = textStyle().size();
                  }
            // if same font, use cached values
            else {
                  _dashY                  = g_cachedDashY;
                  _dashLength             = g_cachedDashLength;
   #if defined(USE_FONT_DASH_TICKNESS)
                  _dashThickness          = g_cachedDashThickness;
   #endif
                  }
#endif
            }
      else
            if (_separator != nullptr) {
                  _separator->unchain();
                  delete _separator;
                  _separator = nullptr;
                  }
      }