Esempio n. 1
0
void TextLineBaseSegment::layout()
      {
      npoints      = 0;
      TextLineBase* tl = textLineBase();
      qreal _spatium = spatium();

      if (!tl->diagonal())
            _userOff2.setY(0);

      switch (spannerSegmentType()) {
            case SpannerSegmentType::SINGLE:
            case SpannerSegmentType::BEGIN:
                  _text->setXmlText(tl->beginText());
                  _text->setFamily(tl->beginFontFamily());
                  _text->setSize(tl->beginFontSize());
                  _text->setOffset(tl->beginTextOffset());
                  _text->setAlign(tl->beginTextAlign());
                  break;
            case SpannerSegmentType::MIDDLE:
            case SpannerSegmentType::END:
                  _text->setXmlText(tl->continueText());
                  _text->setFamily(tl->continueFontFamily());
                  _text->setSize(tl->continueFontSize());
                  _text->setOffset(tl->continueTextOffset());
                  _text->setAlign(tl->continueTextAlign());
                  break;
            }
      _text->setTrack(track());
      _text->layout();

      if ((isSingleType() || isEndType())) {
            _endText->setXmlText(tl->endText());
            _endText->setFamily(tl->endFontFamily());
            _endText->setSize(tl->endFontSize());
            _endText->setOffset(tl->endTextOffset());
            _endText->setAlign(tl->endTextAlign());
            _endText->setTrack(track());
            _endText->layout();
            }
      else {
            _endText->setXmlText("");
            }

      QPointF pp1;
      QPointF pp2(pos2());

      // diagonal line with no text - just use the basic rectangle for line (ignore hooks)
      if (_text->empty() && _endText->empty() && pp2.y() != 0) {
            npoints = 2;
            points[0] = pp1;
            points[1] = pp2;
            setbbox(QRectF(pp1, pp2).normalized());
            return;
            }

      // line has text or is not diagonal - calculate reasonable bbox

      qreal x1 = qMin(0.0, pp2.x());
      qreal x2 = qMax(0.0, pp2.x());
      qreal y0 = point(-textLineBase()->lineWidth());
      qreal y1 = qMin(0.0, pp2.y()) + y0;
      qreal y2 = qMax(0.0, pp2.y()) - y0;

      qreal l = 0.0;
      if (!_text->empty()) {
            qreal textlineTextDistance = _spatium * .5;
            if (((isSingleType() || isBeginType()) && (tl->beginTextPlace() == PlaceText::LEFT)) || ((isMiddleType() || isEndType()) && (tl->continueTextPlace() == PlaceText::LEFT)))
                  l = _text->pos().x() + _text->bbox().width() + textlineTextDistance;
            qreal h = _text->height();
            if (textLineBase()->beginTextPlace() == PlaceText::ABOVE)
                  y1 = qMin(y1, -h);
            else if (textLineBase()->beginTextPlace() == PlaceText::BELOW)
                  y2 = qMax(y2, h);
            else {
                  y1 = qMin(y1, -h * .5);
                  y2 = qMax(y2, h * .5);
                  }
            x2 = qMax(x2, _text->width());
            }

      if (textLineBase()->endHookType() != HookType::NONE) {
            qreal h = pp2.y() + point(textLineBase()->endHookHeight());
            if (h > y2)
                  y2 = h;
            else if (h < y1)
                  y1 = h;
            }

      if (textLineBase()->beginHookType() != HookType::NONE) {
            qreal h = point(textLineBase()->beginHookHeight());
            if (h > y2)
                  y2 = h;
            else if (h < y1)
                  y1 = h;
            }
      bbox().setRect(x1, y1, x2 - x1, y2 - y1);
      if (!_text->empty())
            bbox() |= _text->bbox().translated(_text->pos());  // DEBUG
      // set end text position and extend bbox
      if (!_endText->empty()) {
            _endText->setPos(bbox().right(), 0);
            bbox() |= _endText->bbox().translated(_endText->pos());
            }

      if (!(tl->lineVisible() || score()->showInvisible()))
            return;

      if (tl->lineVisible() || !score()->printing()) {
            QPointF pp1(l, 0.0);

            qreal beginHookWidth;
            qreal endHookWidth;

            if (tl->beginHookType() == HookType::HOOK_45) {
                  beginHookWidth = fabs(tl->beginHookHeight().val() * _spatium * .4);
                  pp1.rx() += beginHookWidth;
                  }
            else
                  beginHookWidth = 0;

            if (tl->endHookType() == HookType::HOOK_45) {
                  endHookWidth = fabs(tl->endHookHeight().val() * _spatium * .4);
                  pp2.rx() -= endHookWidth;
                  }
            else
                  endHookWidth = 0;

            // don't draw backwards lines (or hooks) if text is longer than nominal line length
            bool backwards = !_text->empty() && pp1.x() > pp2.x() && !tl->diagonal();

            if ((tl->beginHookType() != HookType::NONE) && (isSingleType() || isBeginType())) {
                  qreal hh = tl->beginHookHeight().val() * _spatium;
                  points[npoints] = QPointF(pp1.x() - beginHookWidth, pp1.y() + hh);
                  ++npoints;
                  points[npoints] = pp1;
                  }
            if (!backwards) {
                  points[npoints] = pp1;
                  ++npoints;
                  points[npoints] = pp2;
                  // painter->drawLine(QLineF(pp1.x(), pp1.y(), pp2.x(), pp2.y()));

                  if ((tl->endHookType() != HookType::NONE) && (isSingleType() || isEndType())) {
                        ++npoints;
                        qreal hh = tl->endHookHeight().val() * _spatium;
                        // painter->drawLine(QLineF(pp2.x(), pp2.y(), pp2.x() + endHookWidth, pp2.y() + hh));
                        points[npoints] = QPointF(pp2.x() + endHookWidth, pp2.y() + hh);
                        }
                  }
            }
      }
Esempio n. 2
0
void HairpinSegment::layout()
      {
      Dynamic* sd = 0;
      Dynamic* ed = 0;
      qreal _spatium = spatium();

      if (autoplace()) {
            setUserOff(QPointF());
            setUserOff2(QPointF());
            }
      if (isSingleType() || isBeginType()) {
            sd = lookupDynamic(hairpin()->startElement());
            if (sd) {
                  if (autoplace()) {
                        qreal dx        = sd->bbox().right() + sd->pos().x()
                                             + sd->segment()->pos().x() + sd->measure()->pos().x();
                        // hardcoded distance between Dynamic and Hairpin: 0.5sp
                        qreal dist      = dx - pos().x() + score()->styleP(StyleIdx::autoplaceHairpinDynamicsDistance);
                        rUserXoffset()  = dist;
                        rUserXoffset2() = -dist;
                        }
                  else
                        sd->doAutoplace();
                  }
            }
      if (isSingleType() || isEndType()) {
            ed = lookupDynamic(hairpin()->endElement());
            if (ed) {
                  if (autoplace()) {
                        rUserXoffset2() -= ed->bbox().width();
                        qreal dx         = ed->bbox().left() + ed->pos().x()
                                           + ed->segment()->pos().x() + ed->measure()->pos().x();
                        // hardcoded distance between Hairpin and Dynamic: 0.5sp
                        ed->rUserXoffset() = pos2().x() + pos().x() - dx + score()->styleP(StyleIdx::autoplaceHairpinDynamicsDistance);
                        }
                  else
                        ed->doAutoplace();
                  }
            }

      Hairpin::Type type = hairpin()->hairpinType();
      if (type == Hairpin::Type::DECRESC_LINE || type == Hairpin::Type::CRESC_LINE) {
            twoLines = false;
            TextLineSegment::layout();
            drawCircledTip = false;
            if (parent())
                  rypos() += score()->styleP(StyleIdx::hairpinY);
            }
      else {
            delete _text;
            delete _endText;
            _text    = 0;
            _endText = 0;

            QTransform t;
            qreal h1 = hairpin()->hairpinHeight().val()     * spatium() * .5;
            qreal h2 = hairpin()->hairpinContHeight().val() * spatium() * .5;

            qreal len;
            qreal x = pos2().x();
            if (x < _spatium)             // minimum size of hairpin
                  x = _spatium;
            qreal y = pos2().y();
            len     = sqrt(x * x + y * y);
            t.rotateRadians(asin(y/len));

            drawCircledTip   =  hairpin()->hairpinCircledTip();
            circledTipRadius = drawCircledTip ? 0.6 * _spatium * .5 : 0.0;

            QLine l1, l2;
            twoLines  = true;

            switch (type) {
                  case Hairpin::Type::CRESC_HAIRPIN: {
                        switch (spannerSegmentType()) {
                              case SpannerSegmentType::SINGLE:
                              case SpannerSegmentType::BEGIN:
                                    l1.setLine(circledTipRadius * 2.0, 0.0, len, h1);
                                    l2.setLine(circledTipRadius * 2.0, 0.0, len, -h1);
                                    circledTip.setX(circledTipRadius );
                                    circledTip.setY(0.0);
                                    break;

                              case SpannerSegmentType::MIDDLE:
                              case SpannerSegmentType::END:
                                    drawCircledTip = false;
                                    l1.setLine(.0,  h2, len, h1);
                                    l2.setLine(.0, -h2, len, -h1);
                                    break;
                              }
                        }
                        break;
                  case Hairpin::Type::DECRESC_HAIRPIN: {
                        switch(spannerSegmentType()) {
                              case SpannerSegmentType::SINGLE:
                              case SpannerSegmentType::END:
                                    l1.setLine(0.0,  h1, len - circledTipRadius * 2, 0.0);
                                    l2.setLine(0.0, -h1, len - circledTipRadius * 2, 0.0);
                                    circledTip.setX(len - circledTipRadius);
                                    circledTip.setY(0.0);
                                    break;
                              case SpannerSegmentType::BEGIN:
                              case SpannerSegmentType::MIDDLE:
                                    drawCircledTip = false;
                                    l1.setLine(.0,  h1, len, + h2);
                                    l2.setLine(.0, -h1, len, - h2);
                                    break;
                              }
                        }
                        break;
                  default:
                        break;
                  }

            // Do Coord rotation
            l1 = t.map(l1);
            l2 = t.map(l2);
            if (drawCircledTip )
                  circledTip = t.map(circledTip);

            points[0] = l1.p1();
            points[1] = l1.p2();
            points[2] = l2.p1();
            points[3] = l2.p2();
            npoints   = 4;

            QRectF r = QRectF(l1.p1(), l1.p2()).normalized() | QRectF(l2.p1(), l2.p2()).normalized();
            qreal w  = score()->styleP(StyleIdx::hairpinLineWidth);
            setbbox(r.adjusted(-w*.5, -w*.5, w, w));
            if (parent())
                  rypos() += score()->styleP(StyleIdx::hairpinY);
            }
      if (autoplace() && parent()) {
            qreal minDistance = spatium() * .7;
            Shape s1 = shape().translated(pos());
            qreal d  = system()->bottomDistance(staffIdx(), s1);

            qreal ymax = pos().y();
            if (d > -minDistance)
                  ymax += d + minDistance;

            qreal sdy;
            if (sd) {
                  sdy = -sd->bbox().top() * .4;
                  sd->doAutoplace();
                  if (sd->pos().y() - sdy > ymax)
                        ymax = sd->pos().y() - sdy;
                  }
            qreal edy;
            if (ed) {
                  edy = -ed->bbox().top() * .4;
                  ed->doAutoplace();
                  if (ed->pos().y() - edy > ymax)
                        ymax = ed->pos().y() - edy;
                  }
            rUserYoffset() = ymax - pos().y();
            if (sd)
                  moveDynamic(sd, ymax - sd->ipos().y() + sdy);
            if (ed)
                  moveDynamic(ed, ymax - ed->ipos().y() + edy);
            }
      else
            adjustReadPos();
      }
Esempio n. 3
0
void LyricsLineSegment::layout()
      {
      bool        endOfSystem       = false;
      bool        isEndMelisma      = lyricsLine()->lyrics()->ticks() > 0;
      Lyrics*     lyr               = 0;
      Lyrics*     nextLyr           = 0;
      qreal       fromX             = 0;
      qreal       toX               = 0;             // start and end point of intra-lyrics room
      qreal       sp                = spatium();
      System*     sys;

      if (lyricsLine()->ticks() <= 0) {   // if no span,
            _numOfDashes = 0;             // nothing to draw
            return;                       // and do nothing
            }

      // HORIZONTAL POSITION
      // A) if line precedes a syllable, advance line end to right before the next syllable text
      // if not a melisma and there is a next syllable;
      if (!isEndMelisma && lyricsLine()->nextLyrics() && isSingleEndType()) {
            lyr         = nextLyr = lyricsLine()->nextLyrics();
            sys         = lyr->segment()->system();
            endOfSystem = (sys != system());
            // if next lyrics is on a different system, this line segment is at the end of its system:
            // do not adjust for next lyrics position
            if (!endOfSystem) {
                  qreal lyrX        = lyr->bbox().x();
                  qreal lyrXp       = lyr->pagePos().x();
                  qreal sysXp       = sys->pagePos().x();
                  toX               = lyrXp - sysXp + lyrX;       // syst.rel. X pos.
                  qreal offsetX     = toX - pos().x() - pos2().x() - score()->styleP(Sid::lyricsDashPad);
                  //                    delta from current end pos.| ending padding
                  rxpos2()          += offsetX;
                  }
            }
      // B) if line follows a syllable, advance line start to after the syllable text
      lyr  = lyricsLine()->lyrics();
      sys  = lyr->segment()->system();
      if (sys && isSingleBeginType()) {
            qreal lyrX        = lyr->bbox().x();
            qreal lyrXp       = lyr->pagePos().x();
            qreal lyrW        = lyr->bbox().width();
            qreal sysXp       = sys->pagePos().x();
            fromX             = lyrXp - sysXp + lyrX + lyrW;
            //               syst.rel. X pos. | lyr.advance
            qreal offsetX     = fromX - pos().x();
            offsetX           += score()->styleP(isEndMelisma ? Sid::lyricsMelismaPad : Sid::lyricsDashPad);

            //               delta from curr.pos. | add initial padding
            rxpos()           += offsetX;
            rxpos2()          -= offsetX;
            }

      // VERTICAL POSITION: at the base line of the syllable text
      if (!isEndType())
            rypos() = lyr->ipos().y();
      else {
            // use Y position of *next* syllable if there is one on same system
            Lyrics* nextLyr = searchNextLyrics(lyr->segment(), lyr->staffIdx(), lyr->no(), lyr->placement());
            if (nextLyr && nextLyr->segment()->system() == system())
                  rypos() = nextLyr->y();
            else
                  rypos() = lyr->y();
            }

      // MELISMA vs. DASHES
      if (isEndMelisma) {                 // melisma
            _numOfDashes = 1;
            rypos()      -= lyricsLine()->lineWidth() * .5; // let the line 'sit on' the base line
            qreal offsetX = score()->styleP(Sid::minNoteDistance) * mag();
            // if final segment, extend slightly after the chord, otherwise shorten it
            rxpos2() += (isBeginType() || isEndType()) ? -offsetX : +offsetX;
            }
      else {                              // dash(es)
            // set conventional dash Y pos
            rypos() -= MScore::pixelRatio * lyr->fontMetrics().xHeight() * score()->styleD(Sid::lyricsDashYposRatio);
            _dashLength = score()->styleP(Sid::lyricsDashMaxLength) * mag();  // and dash length
            qreal len         = pos2().x();
            qreal minDashLen  = score()->styleS(Sid::lyricsDashMinLength).val() * sp;
            qreal maxDashDist = score()->styleS(Sid::lyricsDashMaxDistance).val() * sp;
            if (len < minDashLen) {                                           // if no room for a dash
                  // if at end of system or dash is forced
                  if (endOfSystem || score()->styleB(Sid::lyricsDashForce)) {
                        rxpos2()          = minDashLen;                       //     draw minimal dash
                        _numOfDashes      = 1;
                        _dashLength       = minDashLen;
                        }
                  else                                                        //   if within system or dash not forced
                        _numOfDashes = 0;                                     //     draw no dash
                  }
            else if (len < (maxDashDist * 2.0)) {                           // if no room for two dashes
                  _numOfDashes = 1;                                           //    draw one dash
                  if (_dashLength > len)                                      // if no room for a full dash
                        _dashLength = len;                                    //    shorten it
                  }
            else
                  _numOfDashes = len / (maxDashDist);                         // draw several dashes

            // adjust next lyrics horiz. position if too little a space forced to skip the dash
            if (_numOfDashes == 0 && nextLyr != nullptr && len > 0)
                  nextLyr->rxpos() -= (toX - fromX);
            }

      // set bounding box
      QRectF r = QRectF(0.0, 0.0, pos2().x(), pos2().y()).normalized();
      qreal lw = lyricsLine()->lineWidth() * .5;
      setbbox(r.adjusted(-lw, -lw, lw, lw));
      }