void tst_QQuickTextMetrics::functionsWithArguments()
{
    QFETCH(QString, text);
    QFETCH(Qt::TextElideMode, mode);
    QFETCH(qreal, width);

    QQuickTextMetrics metrics;
    // Ensures that the values actually change.
    metrics.setText(text + "extra");
    metrics.setElideWidth(width + 1);
    switch (mode) {
        case Qt::ElideNone: metrics.setElide(Qt::ElideMiddle); break;
        case Qt::ElideLeft: metrics.setElide(Qt::ElideRight); break;
        case Qt::ElideMiddle: metrics.setElide(Qt::ElideNone); break;
        case Qt::ElideRight: metrics.setElide(Qt::ElideLeft); break;
    }

    QSignalSpy textSpy(&metrics, SIGNAL(textChanged()));
    QSignalSpy metricsSpy(&metrics, SIGNAL(metricsChanged()));
    metrics.setText(text);
    QCOMPARE(textSpy.count(), 1);
    QCOMPARE(metricsSpy.count(), 1);

    QSignalSpy elideSpy(&metrics, SIGNAL(elideChanged()));
    metrics.setElide(mode);
    QCOMPARE(elideSpy.count(), 1);
    QCOMPARE(metricsSpy.count(), 2);

    QSignalSpy elideWidthSpy(&metrics, SIGNAL(elideWidthChanged()));
    metrics.setElideWidth(width);
    QCOMPARE(elideWidthSpy.count(), 1);
    QCOMPARE(metricsSpy.count(), 3);

    QFontMetricsF expected = QFontMetricsF(QFont());

    QCOMPARE(metrics.elidedText(), expected.elidedText(text, mode, width, 0));
    QCOMPARE(metrics.advanceWidth(), expected.width(text));
    QCOMPARE(metrics.boundingRect(), expected.boundingRect(text));
    QCOMPARE(metrics.width(), expected.boundingRect(text).width());
    QCOMPARE(metrics.height(), expected.boundingRect(text).height());
    QCOMPARE(metrics.tightBoundingRect(), expected.tightBoundingRect(text));
}
Esempio n. 2
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;
                  }
      }