Esempio n. 1
0
void Lyrics::layout()
      {
      // setPos(_textStyle.offset(spatium()));
      layout1();
      QPointF rp(readPos());
      if (!rp.isNull()) {
            if (score()->mscVersion() <= 114) {
                  rp.ry() += lineSpacing() + 2;
                  rp.rx() += bbox().width() * .5;
                  }
            setUserOff(rp - ipos());
            setReadPos(QPointF());
            }
      }
Esempio n. 2
0
void RehearsalMark::layout()
      {
      if (autoplace())
            setUserOff(QPointF());
      qreal y;
      if (placeAbove())
            y = score()->styleP(StyleIdx::rehearsalMarkPosAbove);
      else {
            qreal sh = staff() ? staff()->height() : 0;
            y = score()->styleP(StyleIdx::rehearsalMarkPosBelow) + sh + lineSpacing();
            }
      setPos(QPointF(0.0, y));
      Text::layout1();

      Segment* s = segment();
      if (s) {
            if (!s->rtick()) {
                  // first CR of measure, decide whether to align to barline
                  if (!s->prev() && align() & Align::CENTER) {
                        // measure with no clef / keysig / timesig
                        rxpos() -= s->x();
                        }
                  else if (align() & Align::RIGHT) {
                        // measure with clef / keysig / timesig, rehearsal mark right aligned
                        // align left edge of rehearsal to barline if that is further to left
                        qreal leftX = bbox().x();
                        qreal barlineX = -s->x();
                        rxpos() += qMin(leftX, barlineX) + width();
                        }
                  }
            if (autoplace()) {
                  int firstStaffIdx = s->measure()->system()->firstVisibleStaff();
                  qreal minDistance = score()->styleP(StyleIdx::rehearsalMarkMinDistance);
                  Shape s1 = s->measure()->staffShape(firstStaffIdx);
                  Shape s2 = shape().translated(s->pos() + pos());
                  if (placeAbove()) {
                        qreal d = s2.minVerticalDistance(s1);
                        if (d > -minDistance)
                              rUserYoffset() = -d - minDistance;
                        }
                  else {
                        qreal d = s1.minVerticalDistance(s2);
                        if (d > -minDistance)
                              rUserYoffset() = d + minDistance;
                        }
                  }
            }
      }
Esempio n. 3
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);
      }
Esempio n. 4
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;
                  }
      }