Beispiel #1
1
void Text::layout1()
      {
      if (styled() && !_editMode)
            SimpleText::layout();
      else {
            _doc->setDefaultFont(textStyle().font(spatium()));
            qreal w = -1.0;
            QPointF o(textStyle().offset(spatium()));

            if (parent() && layoutToParentWidth()) {
                  Element* e = parent();
                  w = e->width();
                  if (e->type() == HBOX || e->type() == VBOX || e->type() == TBOX) {
                        Box* b = static_cast<Box*>(e);
                        w -= ((b->leftMargin() + b->rightMargin()) * MScore::DPMM);
                        }
                  }

            QTextOption to = _doc->defaultTextOption();
            to.setUseDesignMetrics(true);
            to.setWrapMode(w <= 0.0 ? QTextOption::NoWrap : QTextOption::WrapAtWordBoundaryOrAnywhere);
            _doc->setDefaultTextOption(to);

            if (w <= 0.0)
                  w = _doc->idealWidth();
            _doc->setTextWidth(w);

            QSizeF size(_doc->size());

            if (align() & ALIGN_BOTTOM)
                  o.ry() -= size.height();
            else if (align() & ALIGN_VCENTER)
                  o.ry() -= (size.height() * .5);
            else if (align() & ALIGN_BASELINE)
                  o.ry() -= baseLine();

            if (align() & ALIGN_RIGHT)
                  o.rx() -= size.width();
            else if (align() & ALIGN_HCENTER)
                  o.rx() -= (size.width() * .5);

            setbbox(QRectF(QPointF(0.0, 0.0), size));
            _doc->setModified(false);
            setPos(o);
            }
      if (parent()) {
            Element* e = parent();
            qreal w, h, xo, yo;
            if (layoutToParentWidth()) {
                  if (e->type() == HBOX || e->type() == VBOX || e->type() == TBOX) {
                        // consider inner margins of frame
                        Box* b = static_cast<Box*>(e);
                        xo = b->leftMargin() * MScore::DPMM;
                        yo = b->topMargin()  * MScore::DPMM;
                        w  = b->width()  - xo - b->rightMargin() * MScore::DPMM;
                        h  = b->height() - yo - b->bottomMargin()   * MScore::DPMM;
                        }
                  else {
                        w  = e->width();
                        h  = e->height();
                        xo = 0.0;
                        yo = 0.0;
                        }
                  QPointF ro(_textStyle.reloff() * .01);
                  rxpos() += xo + ro.x() * w;
                  rypos() += yo + ro.y() * h;
                  }
            if (e->type() == SEGMENT) {
                  Segment* s = static_cast<Segment*>(e);
                  rypos() += s->measure()->system()->staff(staffIdx())->y();
                  }
            }

      if (hasFrame())
            layoutFrame();
      }
Beispiel #2
0
void Arpeggio::draw(QPainter* p) const
      {
      qreal _spatium = spatium();

      p->setPen(curColor());
      qreal y1 = _spatium - _userLen1;
      qreal y2 = _height  + _userLen2;
      qreal x1;
      qreal m = magS();
      switch (subtype()) {
            case ArpeggioType::NORMAL:
                  for (qreal y = y1; y < y2; y += _spatium)
                        symbols[score()->symIdx()][arpeggioSym].draw(p, m, QPointF(0.0, y));
                  break;

            case ArpeggioType::UP:
                  symbols[score()->symIdx()][arpeggioarrowupSym].draw(p, m, QPointF(0.0, y1));
                  for (qreal y = y1 + _spatium; y < y2; y += _spatium)
                        symbols[score()->symIdx()][arpeggioSym].draw(p, m, QPointF(0.0, y));
                  break;

            case ArpeggioType::DOWN:
                  {
                  qreal y = y1;
                  for (; y < y2 - _spatium; y += _spatium)
                        symbols[score()->symIdx()][arpeggioSym].draw(p, m, QPointF(0.0, y));
                  symbols[score()->symIdx()][arpeggioarrowdownSym].draw(p, m, QPointF(0.0, y));
                  }
                  break;

            case ArpeggioType::UP_STRAIGHT:
                  y1-= _spatium * .5;
                  x1 = _spatium * .5;
                  symbols[score()->symIdx()][close11arrowHeadSym].draw(p, m, QPointF(x1, y1 - (_spatium * .5)));
                  p->save();
                  p->setPen(QPen(curColor(),
                     score()->styleS(ST_ArpeggioLineWidth).val() * _spatium,
                     Qt::SolidLine, Qt::RoundCap));
                  p->drawLine(QLineF(x1, y1, x1, y2));
                  p->restore();
                  break;

            case ArpeggioType::DOWN_STRAIGHT:
                  y1-= _spatium;
                  y2-= _spatium * .5;
                  x1 = _spatium * .5;
                  symbols[score()->symIdx()][close1M1arrowHeadSym].draw(p, m, QPointF(x1, y2 + (_spatium * .5)));
                  p->save();
                  p->setPen(QPen(curColor(),
                     score()->styleS(ST_ArpeggioLineWidth).val() * _spatium,
                     Qt::SolidLine, Qt::RoundCap));
                  p->drawLine(QLineF(x1, y1, x1, y2));
                  p->restore();
                  break;

            case ArpeggioType::BRACKET:
                  {
                  y1 = - _userLen1;
                  y2 = _height + _userLen2;
                  p->save();

                  p->setPen(QPen(curColor(),
                     score()->styleS(ST_ArpeggioLineWidth).val() * _spatium,
                     Qt::SolidLine, Qt::RoundCap));

                  qreal w = score()->styleS(ST_ArpeggioHookLen).val() * _spatium;
                  p->drawLine(QLineF(0.0, y1, 0.0, y2));
                  p->drawLine(QLineF(0.0, y1, w, y1));
                  p->drawLine(QLineF(0.0, y2, w, y2));
                  p->restore();
                  }
                  break;
            }
      }
Beispiel #3
0
void Slur::computeBezier(SlurSegment* ss, QPointF p6o)
      {
      qreal _spatium  = spatium();
      qreal shoulderW;              // height as fraction of slur-length
      qreal shoulderH;
      //
      // p1 and p2 are the end points of the slur
      //
      QPointF pp1 = ss->ups[GRIP_START].p + ss->ups[GRIP_START].off * _spatium;
      QPointF pp2 = ss->ups[GRIP_END].p   + ss->ups[GRIP_END].off   * _spatium;

      QPointF p2 = pp2 - pp1;
      if (p2.x() == 0.0) {
            qDebug("zero slur");
            Measure* m1 = startChord()->segment()->measure();
            Measure* m2 = endChord()->segment()->measure();
            Page* page = m1->system()->page();
            qDebug("   at tick %d in measure %d-%d page %d",
               m1->tick(), m1->no(), m2->no(), page->no());
            return;
            }

      qreal sinb = atan(p2.y() / p2.x());
      QTransform t;
      t.rotateRadians(-sinb);
      p2  = t.map(p2);
      p6o = t.map(p6o);

      double smallH = 0.5;
      qreal d = p2.x() / _spatium;
      if (d <= 2.0) {
            shoulderH = d * 0.5 * smallH * _spatium;
            shoulderW = .6;
            }
      else {
            qreal dd = log10(1.0 + (d - 2.0) * .5) * 2.0;
            if (dd > 3.0)
                  dd = 3.0;
            shoulderH = (dd + smallH) * _spatium;
            if (d > 18.0)
                  shoulderW = 0.8;
            else if (d > 10)
                  shoulderW = 0.7;
            else
                  shoulderW = 0.6;
            }

      if (!up())
            shoulderH = -shoulderH;
//      shoulderH -= p6o.y();

      qreal c    = p2.x();
      qreal c1   = (c - c * shoulderW) * .5 + p6o.x();
      qreal c2   = c1 + c * shoulderW       + p6o.x();

      QPointF p5 = QPointF(c * .5, 0.0);

      QPointF p3(c1, -shoulderH);
      QPointF p4(c2, -shoulderH);

      qreal w = (score()->styleS(ST_SlurMidWidth).val() - score()->styleS(ST_SlurEndWidth).val()) * _spatium;
      if (((c2 - c1) / _spatium) <= _spatium)
            w *= .5;
      QPointF th(0.0, w);    // thickness of slur

      QPointF p3o = p6o + t.map(ss->ups[GRIP_BEZIER1].off * _spatium);
      QPointF p4o = p6o + t.map(ss->ups[GRIP_BEZIER2].off * _spatium);

//??      ss->ups[GRIP_BEZIER1].off = t.inverted().map(p3o) / _spatium;
//??      ss->ups[GRIP_BEZIER2].off = t.inverted().map(p4o) / _spatium;

      //-----------------------------------calculate p6
      QPointF pp3  = p3 + p3o;
      QPointF pp4  = p4 + p4o;
      QPointF ppp4 = pp4 - pp3;

      qreal r2 = atan(ppp4.y() / ppp4.x());
      t.reset();
      t.rotateRadians(-r2);
      QPointF p6  = QPointF(t.map(ppp4).x() * .5, 0.0);

      t.rotateRadians(2 * r2);
      p6 = t.map(p6) + pp3; //  - p6o;
      //-----------------------------------

      ss->path = QPainterPath();
      ss->path.moveTo(QPointF());
      ss->path.cubicTo(p3 + p3o - th, p4 + p4o - th, p2);
      if (lineType() == 0)
            ss->path.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF());

      th = QPointF(0.0, 3.0 * w);
      ss->shapePath = QPainterPath();
      ss->shapePath.moveTo(QPointF());
      ss->shapePath.cubicTo(p3 + p3o - th, p4 + p4o - th, p2);
      ss->shapePath.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF());

      // translate back
      t.reset();
      t.translate(pp1.x(), pp1.y());
      t.rotateRadians(sinb);
      ss->path                 = t.map(ss->path);
      ss->shapePath            = t.map(ss->shapePath);
      ss->ups[GRIP_BEZIER1].p  = t.map(p3);
      ss->ups[GRIP_BEZIER2].p  = t.map(p4);
      ss->ups[GRIP_END].p      = t.map(p2) - ss->ups[GRIP_END].off * _spatium;
      ss->ups[GRIP_DRAG].p     = t.map(p5);
      ss->ups[GRIP_SHOULDER].p = t.map(p6);
      }
Beispiel #4
0
void HairpinSegment::layout()
      {
      if (hairpin()->useTextLine()) {
            if (parent())
                  rypos() += score()->styleS(StyleIdx::hairpinY).val() * spatium();
            TextLineSegment::layout();
            return;
            }

      QTransform t;
      qreal _spatium = spatium();
      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 = 0;
      if( drawCircledTip )
        circledTipRadius  = 0.6 * _spatium * .5;
      if (hairpin()->hairpinType() == Hairpin::Type::CRESCENDO) {
            // crescendo
            switch (spannerSegmentType()) {
                  case SpannerSegmentType::SINGLE:
                  case SpannerSegmentType::BEGIN:
                        l1.setLine(.0 + circledTipRadius*2, .0, len, h1);
                        l2.setLine(.0 + circledTipRadius*2, .0, len, -h1);
                        circledTip.setX( 0 + circledTipRadius );
                        circledTip.setY( 0 );
                        break;
                  case SpannerSegmentType::MIDDLE:
                  case SpannerSegmentType::END:
                        drawCircledTip = false;
                        l1.setLine(.0,  h2, len, h1);
                        l2.setLine(.0, -h2, len, -h1);
                        break;
                  }
            }
      else {
            // decrescendo
            switch(spannerSegmentType()) {
                  case SpannerSegmentType::SINGLE:
                  case SpannerSegmentType::END:
                        l1.setLine(.0,  h1, len - circledTipRadius*2, 0.0);
                        l2.setLine(.0, -h1, len - circledTipRadius*2, 0.0);
                        circledTip.setX( len - circledTipRadius );
                        circledTip.setY( 0 );
                        break;
                  case SpannerSegmentType::BEGIN:
                  case SpannerSegmentType::MIDDLE:
                        drawCircledTip = false;
                        l1.setLine(.0,  h1, len, + h2);
                        l2.setLine(.0, -h1, len, - h2);
                        break;
                  }
            }
// Do Coord rotation
      l1 = t.map(l1);
      l2 = t.map(l2);
      if( drawCircledTip )
        circledTip = t.map(circledTip);


      QRectF r = QRectF(l1.p1(), l1.p2()).normalized() | QRectF(l2.p1(), l2.p2()).normalized();
      qreal w = point(score()->styleS(StyleIdx::hairpinLineWidth));
      setbbox(r.adjusted(-w*.5, -w*.5, w, w));
      if (parent())
            rypos() += score()->styleS(StyleIdx::hairpinY).val() * _spatium;
      adjustReadPos();
      }
Beispiel #5
0
qreal Text::lineSpacing() const
      {
      return QFontMetricsF(textStyle().font(spatium())).lineSpacing();
      }
Beispiel #6
0
void SLine::layout()
      {
      if (parent() == 0) {
            //
            // when used in a palette, SLine has no parent and
            // tick and tick2 has no meaning so no layout is
            // possible and needed
            //
            if (!spannerSegments().isEmpty()) {
                  LineSegment* s = frontSegment();
                  s->layout();
                  setbbox(s->bbox());
                  }
            return;
            }
      if (startElement() == 0 || endElement() == 0) {
            qDebug("SLine::layout() failed: %s %s\n", parent()->name(), name());
            qDebug("   start %p   end %p\n", startElement(), endElement());
            return;
            }

      System* s1;
      System* s2;
      QPointF p1 = linePos(GRIP_LINE_START, &s1);
      QPointF p2 = linePos(GRIP_LINE_END,   &s2);

      QList<System*>* systems = score()->systems();
      int sysIdx1 = systems->indexOf(s1);
      int sysIdx2 = systems->indexOf(s2);
      int segmentsNeeded = 0;
      for (int i = sysIdx1; i < sysIdx2+1;  ++i) {
            if (systems->at(i)->isVbox())
                  continue;
            ++segmentsNeeded;
            }
      int segCount = spannerSegments().size();

      if (segmentsNeeded != segCount) {
            if (segmentsNeeded > segCount) {
                  int n = segmentsNeeded - segCount;
                  for (int i = 0; i < n; ++i) {
                        LineSegment* ls = createLineSegment();
                        add(ls);
                        // set user offset to previous segment's offset
                        if (segCount > 0)
                              ls->setUserOff(QPointF(0, segmentAt(segCount+i-1)->userOff().y()));
                        }
                  }
            else {
                  int n = segCount - segmentsNeeded;
                  qDebug("SLine: segments %d needed %d, remove %d\n", segCount, segmentsNeeded, n);
                  for (int i = 0; i < n; ++i) {
                        if (spannerSegments().isEmpty()) {
                              qDebug("SLine::layout(): no segment %d, %d expected\n", i, n);
                              break;
                              }
                        else {
                              // LineSegment* seg = takeLastSegment();
                              // TODO delete seg;
                              }
                        }
                  }
            }

      int segIdx = 0;
      int si  = staffIdx();
      for (int i = sysIdx1; i <= sysIdx2; ++i) {
            System* system = systems->at(i);
            if (system->isVbox())
                  continue;
            LineSegment* seg = segmentAt(segIdx++);
            seg->setSystem(system);

            Measure* m = system->firstMeasure();
            qreal x1 = m->first(SegChordRest)->pos().x() + m->pos().x();
            qreal x2 = system->bbox().right();
            qreal y  = system->staff(si)->y();

            if (sysIdx1 == sysIdx2) {
                  // single segment
                  seg->setSubtype(SEGMENT_SINGLE);
                  seg->setPos(p1);
                  seg->setPos2(QPointF(p2.x() - p1.x(), 0.0));
                  }
            else if (i == sysIdx1) {
                  // start segment
                  seg->setSubtype(SEGMENT_BEGIN);
                  seg->setPos(p1);
                  seg->setPos2(QPointF(x2 - p1.x(), 0.0));
                  }
            else if (i > 0 && i != sysIdx2) {
                  // middle segment
                  seg->setSubtype(SEGMENT_MIDDLE);
                  seg->setPos(QPointF(x1, y));
                  seg->setPos2(QPointF(x2 - x1, 0.0));
                  }
            else if (i == sysIdx2) {
                  // end segment
                  seg->setSubtype(SEGMENT_END);
                  seg->setPos(QPointF(x1, y));
                  seg->setPos2(QPointF(p2.x() - x1, 0.0));
                  }
            seg->layout();
            seg->rypos() += (_yoffset * spatium());
            seg->adjustReadPos();
            }
      }
Beispiel #7
0
Space Glissando::space() const
      {
      return Space(0.0, spatium() * 2.0);
      }
Beispiel #8
0
void Tremolo::layout()
      {
      qreal _spatium  = spatium();

      qreal w2  = _spatium * score()->styleS(StyleIdx::tremoloWidth).val() * .5;
      qreal h2  = _spatium * score()->styleS(StyleIdx::tremoloBoxHeight).val()  * .5;
      qreal lw  = _spatium * score()->styleS(StyleIdx::tremoloStrokeWidth).val();
      qreal td  = _spatium * score()->styleS(StyleIdx::tremoloDistance).val();
      path      = QPainterPath();

      qreal ty   = 0.0;
      for (int i = 0; i < _lines; ++i) {
            path.moveTo(-w2,  ty + h2 - lw);
            path.lineTo( w2,  ty - h2);
            path.lineTo( w2,  ty - h2 + lw);
            path.lineTo(-w2,  ty + h2);

            path.closeSubpath();
            ty += td;
            }

      QRectF rect = path.boundingRect();
      if ((parent() == 0) && !twoNotes())
            rect.setHeight(rect.height() + _spatium);
      setbbox(rect);

      _chord1 = static_cast<Chord*>(parent());
      if (_chord1 == 0)
            return;
      Note* anchor1 = _chord1->upNote();
      Stem* stem    = _chord1->stem();
      qreal x, y, h;
      if (stem) {
            x  = stem->pos().x();
            y  = stem->pos().y();
            h  = stem->stemLen();
            }
      else {
            // center tremolo above note
            x = anchor1->x() + anchor1->headWidth() * .5;
            y = anchor1->y();
            h = 2.0 * _spatium + bbox().height();
            if (anchor1->line() > 4)
                  h *= -1;
            }
      if (!twoNotes()) {
            //
            // single note tremolos
            //
            bool up = _chord1->up();
            int line = up ? _chord1->upLine() : _chord1->downLine();
            static const qreal t[3][2][4][2] = {
                  // normal stem
                  {
                     // DOWN
                     {
                        // even line   odd line
                        { 6,           5          },  // line 1
                        { 6 - 2 * .8,  5 - 2 * .8 },  // line 2
                        { 6 - 4 * .8,  3          },  // line 3
                        { 2         ,  3          }   // line 4
                        },
                     // UP
                     {
                        // even line   odd line
                        { -6,          -5          },  // line 1
                        { -6,          -5          },  // line 2
                        { -6,          -3 - 4 * .8 },  // line 3
                        { -2 - 6 * .8, -3 - 6 * .8 }   // line 4
                        }
                     },
                  // stem with hook
                  {
                     // DOWN
                     {
                        // even line   odd line
                        { 3,           3          },  // line 1
                        { 2,           2          },  // line 2
                        { 2,           2          },  // line 3
                        { 2,           2          }   // line 4
                        },
                     // UP
                     {
                        // even line   odd line
                        { -3,          -3          },  // line 1
                        { -2 - 2 * .8, -2 - 2 * .8 },  // line 2
                        { -2 - 4 * .8, -2 - 4 * .8 },  // line 3
                        { -2 - 6 * .8, -2 - 6 * .8 }   // line 4
                        }
                     },
                  // stem with beam
                  {
                     // DOWN
                     {
                        // even line   odd line
                        { 3,           3          },  // line 1
                        { 2,           2          },  // line 2
                        { 2,           2          },  // line 3
                        { 2,           2          }   // line 4
                        },
                     // UP
                     {
                        // even line   odd line
                        { -3,          -3          },  // line 1
                        { -2 - 2 * .8, -2 - 2 * .8 },  // line 2
                        { -2 - 4 * .8, -2 - 4 * .8 },  // line 3
                        { -2 - 6 * .8, -2 - 6 * .8 }   // line 4
                        }
                     },
                  };
            int idx = _chord1->hook() ? 1 : (_chord1->beam() ? 2 : 0);
            y = (line + t[idx][up][_lines-1][line & 1]) * _spatium * .5;
            setPos(x, y);
            return;
            }
      y += (h - bbox().height()) * .5;
      //
      // two chord tremolo
      //
      Segment* s = _chord1->segment()->next();
      while (s) {
            if (s->element(track()) && (s->element(track())->type() == Element::Type::CHORD))
                  break;
            s = s->next();
            }
      if (s == 0) {
            qDebug("no second note of tremolo found");
            return;
            }

      _chord2 = static_cast<Chord*>(s->element(track()));
      _chord2->setTremolo(this);

      int x2  = _chord2->stemPosBeam().x();
      int x1  = _chord1->stemPosBeam().x();

      // qreal x2     = _chord2->_chord2->up()stemPos(_chord2->up(), true).x();
      // qreal x1     = _chord1->stemPos(_chord1->up(), true).x();
      x             = x1 - _chord1->pagePos().x() + (x2 - x1 + _chord1->upNote()->headWidth()) * .5;
      setPos(x, y);
      }
Beispiel #9
0
void Tremolo::layout()
      {
      qreal _spatium  = spatium() * mag();

      qreal w2  = _spatium * score()->styleS(StyleIdx::tremoloWidth).val() * .5;
      qreal lw  = _spatium * score()->styleS(StyleIdx::tremoloStrokeWidth).val();
      qreal td  = _spatium * score()->styleS(StyleIdx::tremoloDistance).val();
      path      = QPainterPath();

      qreal ty   = 0.0;

      for (int i = 0; i < _lines; i++) {
            path.addRect(-w2, ty, 2.0 * w2, lw);
            ty += td;
            }

      // QRectF rect = path.boundingRect();
      // if ((parent() == 0) && !twoNotes())
      //       rect.setHeight(rect.height() + _spatium);

      _chord1 = static_cast<Chord*>(parent());
      if (_chord1 == 0) {
            // just for the palette
            QTransform shearTransform;
            shearTransform.shear(0.0, -(lw / 2.0) / w2);
            path = shearTransform.map(path);
            setbbox(path.boundingRect());
            addbbox(QRectF(bbox().x(), bbox().bottom(), bbox().width(), _spatium));
            return;
            }
      Note* anchor1 = _chord1->upNote();
      Stem* stem    = _chord1->stem();
      qreal x, y, h;
      if (stem) {
            x  = stem->pos().x();
            y  = stem->pos().y();
            h  = stem->stemLen();
            }
      else {
            // center tremolo above note
            x = anchor1->x() + anchor1->headWidth() * .5;
            y = anchor1->y();
            h = 2.0 * _spatium + bbox().height();
            if (anchor1->line() > 4)
                  h *= -1;
            }
      if (!twoNotes()) {
            //
            // single note tremolos
            //
            bool up = _chord1->up();
            int line = up ? _chord1->upLine() : _chord1->downLine();
            static const qreal t[3][2][4][2] = {
                  // normal stem
                  {
                     // DOWN
                     {
                        // even line   odd line
                        { 6,           5          },  // line 1
                        { 6 - 2 * .8,  5 - 2 * .8 },  // line 2
                        { 6 - 4 * .8,  3          },  // line 3
                        { 2         ,  3          }   // line 4
                        },
                     // UP
                     {
                        // even line   odd line
                        { -6,          -5          },  // line 1
                        { -6,          -5          },  // line 2
                        { -6,          -3 - 4 * .8 },  // line 3
                        { -2 - 6 * .8, -3 - 6 * .8 }   // line 4
                        }
                     },
                  // stem with hook
                  {
                     // DOWN
                     {
                        // even line   odd line
                        { 3,           3          },  // line 1
                        { 2,           2          },  // line 2
                        { 2,           2          },  // line 3
                        { 2,           2          }   // line 4
                        },
                     // UP
                     {
                        // even line   odd line
                        { -3,          -3          },  // line 1
                        { -2 - 2 * .8, -2 - 2 * .8 },  // line 2
                        { -2 - 4 * .8, -2 - 4 * .8 },  // line 3
                        { -2 - 6 * .8, -2 - 6 * .8 }   // line 4
                        }
                     },
                  // stem with beam
                  {
                     // DOWN
                     {
                        // even line   odd line
                        { 3,           3          },  // line 1
                        { 2,           2          },  // line 2
                        { 2,           2          },  // line 3
                        { 2,           2          }   // line 4
                        },
                     // UP
                     {
                        // even line   odd line
                        { -3,          -3          },  // line 1
                        { -2 - 2 * .8, -2 - 2 * .8 },  // line 2
                        { -2 - 4 * .8, -2 - 4 * .8 },  // line 3
                        { -2 - 6 * .8, -2 - 6 * .8 }   // line 4
                        }
                     },
                  };
            int idx = _chord1->hook() ? 1 : (_chord1->beam() ? 2 : 0);
            y = (line + t[idx][up][_lines-1][line & 1]) * spatium() * .5;

            QTransform shearTransform;
            shearTransform.shear(0.0, -(lw / 2.0) / w2);
            path = shearTransform.map(path);

            setbbox(path.boundingRect());
            setPos(x, y);
            adjustReadPos();
            return;
            }
      y += (h - bbox().height()) * .5;
      //
      // two chord tremolo
      //
      Segment* s = _chord1->segment()->next();
      while (s) {
            if (s->element(track()) && (s->element(track())->type() == Element::Type::CHORD))
                  break;
            s = s->next();
            }
      if (s == 0) {
            qDebug("no second note of tremolo found");
            return;
            }

      _chord2 = static_cast<Chord*>(s->element(track()));
      _chord2->setTremolo(this);

      Stem* stem1 = _chord1->stem();
      Stem* stem2 = _chord2->stem();

      // compute the y coordinates of the tips of the stems
      qreal y1, y2;
      qreal firstChordStaffY;

      if (stem2 && stem1) {
            // stemPageYOffset variable is used for the case when the first
            // chord is cross-staff
            firstChordStaffY = stem1->pagePos().y() - stem1->y();  // y coordinate of the staff of the first chord
            y1 = stem1->y() + stem1->p2().y();
            y2 = stem2->pagePos().y() - firstChordStaffY + stem2->p2().y();  // ->p2().y() is better than ->stemLen()
            }
      else {
            firstChordStaffY = _chord1->pagePos().y() - _chord1->y();  // y coordinate of the staff of the first chord
            y1 = _chord1->stemPosBeam().y() - firstChordStaffY + _chord1->defaultStemLength();
            y2 = _chord2->stemPosBeam().y() - firstChordStaffY + _chord2->defaultStemLength();
            }

      // improve the case when one stem is up and another is down
      if (_chord1->beams() == 0 && _chord2->beams() == 0 &&
          _chord1->up() != _chord2->up()) {
            qreal meanNote1Y = .5 * (_chord1->upNote()->pagePos().y() - firstChordStaffY + _chord1->downNote()->pagePos().y() - firstChordStaffY);
            qreal meanNote2Y = .5 * (_chord2->upNote()->pagePos().y() - firstChordStaffY + _chord2->downNote()->pagePos().y() - firstChordStaffY);
            y1 = .5 * (y1 + meanNote1Y);
            y2 = .5 * (y2 + meanNote2Y);
            }

      y = (y1 + y2) * .5;
      if (!_chord1->up()) {
            y -= path.boundingRect().height() * .5;
            }
      if (!_chord2->up()) {
            y -= path.boundingRect().height() * .5;
            }

      // compute the x coordinates of the inner edge of the stems
      qreal x2  = _chord2->stemPosBeam().x();
      if (_chord2->up() && stem2)
            x2 -= stem2->lineWidth();
      qreal x1  = _chord1->stemPosBeam().x();
      if (!_chord1->up() && stem1)
            x1 += stem1->lineWidth();

      x = (x1 + x2) * .5 - _chord1->pagePos().x();

      QTransform xScaleTransform;
      // TODO const qreal H_MULTIPLIER = score()->styleS(StyleIdx::tremoloBeamLengthMultiplier).val();
      const qreal H_MULTIPLIER = 0.62;
      // TODO const qreal MAX_H_LENGTH = _spatium * score()->styleS(StyleIdx::tremoloBeamLengthMultiplier).val();
      const qreal MAX_H_LENGTH = _spatium * 12.0;

      qreal xScaleFactor = qMin(H_MULTIPLIER * (x2 - x1), MAX_H_LENGTH);
      xScaleFactor /= (2.0 * w2);

      xScaleTransform.scale(xScaleFactor, 1.0);
      path = xScaleTransform.map(path);

      qreal beamYOffset = 0.0;

      if (_chord1->beams() == _chord2->beams() && _chord1->beam()) {
            int beams = _chord1->beams();
            qreal beamHalfLineWidth = point(score()->styleS(StyleIdx::beamWidth)) * .5 * mag();
            beamYOffset = beams * _chord1->beam()->beamDist() - beamHalfLineWidth;
            if (_chord1->up() != _chord2->up()) {  // cross-staff
                  beamYOffset += beamYOffset + beamHalfLineWidth;
                  }
            else if (!_chord1->up() && !_chord2->up()) {
                  beamYOffset = -beamYOffset;
                  }
            }

      QTransform shearTransform;
      if (_chord1->beams() == 0 && _chord2->beams() == 0) {
            if (_chord1->up() && !_chord2->up())
                  shearTransform.shear(0.0, (y2 - y1 - path.boundingRect().height()) / (x2 - x1));
            else if (!_chord1->up() && _chord2->up())
                  shearTransform.shear(0.0, (y2 - y1 + path.boundingRect().height()) / (x2 - x1));
            else
                  shearTransform.shear(0.0, (y2 - y1) / (x2 - x1));
            }
      else {
            shearTransform.shear(0.0, (y2 - y1) / (x2 - x1));
            }

      path = shearTransform.map(path);

      setbbox(path.boundingRect());
      setPos(x, y + beamYOffset);
      adjustReadPos();
      }
Beispiel #10
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();
      }
Beispiel #11
0
void Clef::layout1()
      {
      qreal smag     = _small ? score()->style(ST_smallClefMag).toDouble() : 1.0;
      qreal _spatium = spatium();
      qreal msp      = _spatium * smag;
      qreal yoff     = 0.0;

      qDeleteAll(elements);
      elements.clear();

      Symbol* symbol = new Symbol(score());

      switch (curClefType) {
      case CLEF_G:                              // G clef on 2nd line
            symbol->setSym(trebleclefSym);
            yoff = 3.0 * curLineDist;
            break;
      case CLEF_G1:                             // G clef 8va on 2nd line
            {
            symbol->setSym(trebleclefSym);
            yoff = 3.0 * curLineDist;
            Symbol* number = new Symbol(score());
            number->setMag(smag);
            number->setSym(clefEightSym);
            addElement(number, 1.0 * msp, -5.0 * msp + yoff * _spatium);
            }
            break;
      case CLEF_G2:                             // G clef 15ma on 2nd line
            {
            symbol->setSym(trebleclefSym);
            yoff = 3.0 * curLineDist;
            Symbol* number = new Symbol(score());
            symbol->setMag(smag);
            number->setSym(clefOneSym);
            addElement(number, .6 * msp, -5.0 * msp + yoff * _spatium);
            number = new Symbol(score());
            number->setSym(clefFiveSym);
            addElement(number, 1.4 * msp, -5.0 * msp + yoff * _spatium);
            }
            break;
      case CLEF_G3:                             // G clef 8va bassa on 2nd line
            {
            symbol->setSym(trebleclefSym);
            yoff = 3.0 * curLineDist;
            Symbol* number = new Symbol(score());
            symbol->setMag(smag);
            number->setSym(clefEightSym);
            addElement(number, 1.0 * msp, 4.0 * msp + yoff * _spatium);
            }
            break;
      case CLEF_F:                              // F clef on penultimate line
            symbol->setSym(bassclefSym);
            yoff = 1.0 * curLineDist;
            break;
      case CLEF_F8:                             // F clef 8va bassa on penultimate line
            {
            symbol->setSym(bassclefSym);
            yoff = 1.0 * curLineDist;
            Symbol* number = new Symbol(score());
            symbol->setMag(smag);
            number->setSym(clefEightSym);
            addElement(number, .0, 4.5 * msp + yoff * _spatium);
            }
            break;
      case CLEF_F15:                            // F clef 15ma bassa on penultimate line
            {
            symbol->setSym(bassclefSym);
            yoff = 1.0 * curLineDist;
            Symbol* number = new Symbol(score());
            symbol->setMag(smag);
            number->setSym(clefOneSym);
            addElement(number, .0, 4.5 * msp + yoff * _spatium);
            number = new Symbol(score());
            number->setSym(clefFiveSym);
            addElement(number, .8 * msp, 4.5 * msp + yoff * _spatium);
            }
            break;
      case CLEF_F_B:                            // baritone clef
            symbol->setSym(bassclefSym);
            yoff = 2.0 * curLineDist;
            break;
      case CLEF_F_C:                            // subbass clef
            symbol->setSym(bassclefSym);
            yoff = 0.0;
            break;
      case CLEF_C1:                             // C clef in 1st line
            symbol->setSym(altoclefSym);
            yoff = 4.0 * curLineDist;
            break;
      case CLEF_C2:                             // C clef on 2nd line
            symbol->setSym(altoclefSym);
            yoff = 3.0 * curLineDist;
            break;
      case CLEF_C3:                             // C clef in 3rd line
            symbol->setSym(altoclefSym);
            yoff = 2.0 * curLineDist;
            break;
      case CLEF_C4:                             // C clef on 4th line
            symbol->setSym(altoclefSym);
            yoff = 1.0 * curLineDist;
            break;
      case CLEF_C5:                             // C clef on 5th line
            symbol->setSym(altoclefSym);
            yoff = 0.0;
            break;
      case CLEF_TAB:                            // TAB clef
            symbol->setSym(tabclefSym);
            // on tablature, position clef at half the number of spaces * line distance
            yoff = curLineDist * (curLines - 1) * .5;
            break;                              // TAB clef alternate style
      case CLEF_TAB2:
            symbol->setSym(tabclef2Sym);
            // on tablature, position clef at half the number of spaces * line distance
            yoff = curLineDist * (curLines - 1) * .5;
            break;
      case CLEF_PERC:                           // percussion clefs
      case CLEF_PERC2:
            symbol->setSym(percussionclefSym);
            yoff = curLineDist * (curLines - 1) * 0.5;
            break;
      case CLEF_G4:                             // G clef in 1st line
            symbol->setSym(trebleclefSym);
            yoff = 4.0 * curLineDist;
            break;
      case CLEF_F_8VA:                          // F clef 8va on penultimate line
            {
            symbol->setSym(bassclefSym);
            yoff = 1.0 * curLineDist;
            Symbol* number = new Symbol(score());
            number->setMag(smag);
            number->setSym(clefEightSym);
            addElement(number, .5 * msp, -1.5 * msp + yoff * _spatium);
            }
            break;
      case CLEF_F_15MA:                         // F clef 15ma on penultimate line
            {
            symbol->setSym(bassclefSym);
            yoff = 1.0 * curLineDist;
            Symbol* number = new Symbol(score());
            symbol->setMag(smag);
            number->setSym(clefOneSym);
            addElement(number, .0 * msp, -1.5 * msp + yoff * _spatium);
            number = new Symbol(score());
            number->setSym(clefFiveSym);
            addElement(number, .8 * msp, -1.5 * msp + yoff * _spatium);
            }
            break;
      case CLEF_INVALID:
      case CLEF_MAX:
            return;
      }

      symbol->setMag(smag * mag());
      symbol->layout();
      addElement(symbol, .0, yoff * _spatium);
      setbbox(QRectF());
      for (auto i = elements.begin(); i != elements.end(); ++i) {
            Element* e = *i;
            e->setColor(curColor());
            addbbox(e->bbox().translated(e->pos()));
            e->setSelected(selected());
            }
      }
void Trill::setYoff(qreal val)
      {
      rUserYoffset() += (val - score()->styleS(StyleIdx::trillY).val()) * spatium();
      }
Beispiel #13
0
void Rest::layout()
      {
      int lines = staff()->lines();

      switch(durationType().type()) {
            case Duration::V_64TH:
            case Duration::V_32ND:
                  dotline = -3;
                  break;
            case Duration::V_256TH:
            case Duration::V_128TH:
                  dotline = -5;
                  break;
            default:
                  dotline = -1;
                  break;
            }
      qreal _spatium = spatium();
      int line        = lrint(userOff().y() / _spatium); //  + ((staff()->lines()-1) * 2);
      int lineOffset  = 0;

      if (measure()->mstaff(staffIdx())->hasVoices) {
            // move rests in a multi voice context
            bool up = (voice() == 0) || (voice() == 2);       // TODO: use style values
            switch(durationType().type()) {
                  case Duration::V_LONG:
                        lineOffset = up ? -3 : 5;
                        break;
                  case Duration::V_BREVE:
                        lineOffset = up ? -3 : 5;
                        break;
                  case Duration::V_MEASURE:
                  case Duration::V_WHOLE:
                        lineOffset = up ? -4 : 6;
                        break;
                  case Duration::V_HALF:
                        lineOffset = up ? -4 : 4;
                        break;
                  case Duration::V_QUARTER:
                        lineOffset = up ? -4 : 4;
                        break;
                  case Duration::V_EIGHT:
                        lineOffset = up ? -4 : 4;
                        break;
                  case Duration::V_16TH:
                        lineOffset = up ? -6 : 4;
                        break;
                  case Duration::V_32ND:
                        lineOffset = up ? -6 : 6;
                        break;
                  case Duration::V_64TH:
                        lineOffset = up ? -8 : 6;
                        break;
                  case Duration::V_128TH:
                        lineOffset = up ? -8 : 8;
                        break;
                  case Duration::V_256TH:             // not available
                        lineOffset = up ? -10 : 6;
                        break;
                  default:
                        break;
                  }
            }
      else {
            switch(durationType().type()) {
                  case Duration::V_LONG:
                  case Duration::V_BREVE:
                  case Duration::V_MEASURE:
                  case Duration::V_WHOLE:
                        if (lines == 1)
                              lineOffset = -2;
                        break;
                  case Duration::V_HALF:
                  case Duration::V_QUARTER:
                  case Duration::V_EIGHT:
                  case Duration::V_16TH:
                  case Duration::V_32ND:
                  case Duration::V_64TH:
                  case Duration::V_128TH:
                  case Duration::V_256TH:             // not available
                        if (lines == 1)
                              lineOffset = -4;
                        break;
                  default:
                        break;
                  }
            }

      int yo;
      _sym = getSymbol(durationType().type(), line + lineOffset/2, lines, &yo);
      setYoff(qreal(yo) + qreal(lineOffset) * .5);
      layoutArticulations();
      setPos(0.0, yoff() * _spatium);

      Spatium rs;
      if (dots()) {
            rs = Spatium(score()->styleS(ST_dotNoteDistance)
               + dots() * score()->styleS(ST_dotDotDistance));
            }
      Segment* s = segment();
      if (s && s->measure() && s->measure()->multiMeasure()) {
            qreal _spatium = spatium();
            qreal h = _spatium * 6.5;
            qreal w = point(score()->styleS(ST_minMMRestWidth));
            setbbox(QRectF(-w * .5, -h + 2 * _spatium, w, h));
            }
      else {
            if (dots()) {
                  rs = Spatium(score()->styleS(ST_dotNoteDistance)
                     + dots() * score()->styleS(ST_dotDotDistance));
                  }
            setbbox(symbols[score()->symIdx()][_sym].bbox(magS()));
            }
      _space.setLw(point(_extraLeadingSpace));
      _space.setRw(width() + point(_extraTrailingSpace + rs));
//      adjustReadPos();
      }
void LayoutBreak::spatiumChanged(qreal, qreal)
      {
      lw = spatium() * 0.3;
      layout0();
      }
Beispiel #15
0
void Tie::layout()
      {
      qreal _spatium = spatium();

      //
      //    show short bow
      //
      if (startNote() == 0 || endNote() == 0) {
            if (startNote() == 0) {
                  qDebug("Tie::layout(): no start note");
                  return;
                  }
            Chord* c1 = startNote()->chord();
            if (_slurDirection == MScore::Direction::AUTO) {
                  if (c1->measure()->mstaff(c1->staffIdx())->hasVoices) {
                        // in polyphonic passage, ties go on the stem side
                        _up = c1->up();
                        }
                  else
                        _up = !c1->up();
                  }
            else
                  _up = _slurDirection == MScore::Direction::UP ? true : false;
            fixupSegments(1);
            SlurSegment* segment = segmentAt(0);
            segment->setSpannerSegmentType(SpannerSegmentType::SINGLE);
            segment->setSystem(startNote()->chord()->segment()->measure()->system());
            SlurPos sPos;
            slurPos(&sPos);
            segment->layout(sPos.p1, sPos.p2);
            return;
            }

      calculateDirection();

      qreal w   = startNote()->headWidth();
      qreal xo1 = w * 1.12;
      qreal h   = w * 0.3;
      qreal yo  = _up ? -h : h;

      QPointF off1(xo1, yo);
      QPointF off2(0.0, yo);

#if 0 // yet(?) unused
      QPointF ppos(pagePos());
#endif

      // TODO: cleanup

      SlurPos sPos;
      slurPos(&sPos);

      // p1, p2, s1, s2

      QList<System*>* systems = score()->systems();
      setPos(0, 0);

      //---------------------------------------------------------
      //   count number of segments, if no change, all
      //    user offsets (drags) are retained
      //---------------------------------------------------------

      int sysIdx1 = systems->indexOf(sPos.system1);
      if (sysIdx1 == -1) {
            qDebug("system not found");
            foreach(System* s, *systems)
                  qDebug("   search %p in %p", sPos.system1, s);
            return;
            }

      int sysIdx2     = systems->indexOf(sPos.system2);
      if (sysIdx2 < 0)
            sysIdx2 = sysIdx1;
      unsigned nsegs  = sysIdx2 - sysIdx1 + 1;
      fixupSegments(nsegs);

      int i = 0;
      for (uint ii = 0; ii < nsegs; ++ii) {
            System* system = (*systems)[sysIdx1++];
            if (system->isVbox())
                  continue;
            SlurSegment* segment = segmentAt(i);
            segment->setSystem(system);

            // case 1: one segment
            if (sPos.system1 == sPos.system2) {
                  segment->layout(sPos.p1, sPos.p2);
                  segment->setSpannerSegmentType(SpannerSegmentType::SINGLE);
                  }
            // case 2: start segment
            else if (i == 0) {
                  qreal x = system->bbox().width();
                  segment->layout(sPos.p1, QPointF(x, sPos.p1.y()));
                  segment->setSpannerSegmentType(SpannerSegmentType::BEGIN);
                  }
            // case 4: end segment
            else {
                  qreal x = firstNoteRestSegmentX(system) - 2 * _spatium;

                  segment->layout(QPointF(x, sPos.p2.y()), sPos.p2);
                  segment->setSpannerSegmentType(SpannerSegmentType::END);
                  }
            ++i;
            }
      }
Beispiel #16
0
QSizeF Image::pixel2size(const QSizeF& s) const
      {
      return s / (_sizeIsSpatium ? spatium() : DPMM);
      }
Beispiel #17
0
void BarLine::endEditDrag()
      {
      qreal y1, y2;
      getY(&y1, &y2);
      qreal ay0 = pagePos().y();
      qreal ay2 = ay0 + y2;                     // absolute (page-relative) bar line bottom coord

      int staffIdx1 = staffIdx();
      int staffIdx2;

      System* syst;
      if (parent()->type() == SYSTEM) {
            syst = static_cast<System*>(parent());
            }
      else {
            syst = static_cast<Segment*>(parent())->measure()->system();
            }
      qreal systTopY = syst->pagePos().y();

      // determine new span value
      int numOfStaves = syst->staves()->size();
      if (staffIdx1 + 1 >= numOfStaves)
            // if initial staff is last staff, ending staff must be the same
            staffIdx2 = staffIdx1;

      else {
            // if there are other staves after it, look for staff nearest to bar line bottom coord
            qreal staff1TopY = syst->staff(staffIdx1)->y() + systTopY;

            for (staffIdx2 = staffIdx1 + 1; staffIdx2 < numOfStaves; ++staffIdx2) {
                  // compute 1st staff height, absolute top Y of 2nd staff and height of blank between the staves
                  Staff * staff1      = score()->staff(staffIdx2-1);
                  qreal staff1Hght    = (staff1->lines()-1) * staff1->lineDistance() * spatium();
                  qreal staff2TopY    = systTopY   + syst->staff(staffIdx2)->y();
                  qreal blnkBtwnStaff = staff2TopY - staff1TopY - staff1Hght;
                  // if bar line bottom coord is above than mid-way of blank between staves...
                  if (ay2 < (staff1TopY + staff1Hght + blnkBtwnStaff * .5))
                        break;                  // ...staff 1 is ending staff
                  // if bar line is below, advance to next staff
                  staff1TopY = staff2TopY;
                  }
            staffIdx2 -= 1;
            }
      int newSpan = staffIdx2 - staffIdx1 + 1;

      // determine new spanFrom value
      int newSpanFrom = _spanFrom;
      if(yoff1 != 0.0) {
            // round bar line top coord to nearest line of 1st staff (in half line dist units)
            newSpanFrom = ((int)floor(y1 / (staff()->lineDistance() * spatium()) + 0.5 )) * 2;
            // min = 1 line dist above 1st staff line | max = 1 line dist below last staff line
            if(newSpanFrom <  MIN_BARLINE_SPAN_FROMTO)
                  newSpanFrom = MIN_BARLINE_SPAN_FROMTO;
            if(newSpanFrom > staff()->lines()*2)
                  newSpanFrom = staff()->lines()*2;
            }

      // determine new spanTo value
      int newSpanTo = _spanTo;
      if(yoff2 != 0.0) {
            // round bar line bottom coord to nearest line of 2nd staff (in half line dist units)
            Staff * staff2   = score()->staff(staffIdx2);
            qreal staff2TopY = systTopY + syst->staff(staffIdx2)->y();
            newSpanTo = ((int)floor( (ay2 - staff2TopY) / (staff2->lineDistance() * spatium()) + 0.5 )) * 2;
            // min = 1 line dist above 1st staff line | max = 1 line dist below last staff line
            if(newSpanTo <  MIN_BARLINE_SPAN_FROMTO)
                  newSpanTo = MIN_BARLINE_SPAN_FROMTO;
            if(newSpanTo > staff()->lines()*2)
                  newSpanTo = staff2->lines()*2;
            }

      // if any value changed, update
      if(newSpan != _span || newSpanFrom != _spanFrom || newSpanTo != _spanTo) {
            _span       = newSpan;
            _spanFrom   = newSpanFrom;
            _spanTo     = newSpanTo;
            }

      yoff1 = yoff2 = 0.0;
      }
Beispiel #18
0
QSizeF Image::size2pixel(const QSizeF& s) const
      {
      return s * (_sizeIsSpatium ? spatium() : DPMM);
      }
Beispiel #19
0
void Stem::draw(QPainter* painter) const
      {
      // hide if second chord of a cross-measure pair
      if (chord() && chord()->crossMeasure() == CrossMeasure::SECOND)
            return;

      Staff* st = staff();
      bool useTab = st && st->isTabStaff();

      qreal lw = lineWidth();
      painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::RoundCap));
      painter->drawLine(line);

      if (!useTab || !chord())
            return;

      // TODO: adjust bounding rectangle in layout() for dots and for slash
      StaffType* stt = st->staffType();
      qreal sp = spatium();
      bool _up = up();

      // slashed half note stem
      if (chord()->durationType().type() == TDuration::DurationType::V_HALF && stt->minimStyle() == TablatureMinimStyle::SLASHED) {
            // position slashes onto stem
            qreal y = _up ? -(_len+_userLen) + STAFFTYPE_TAB_SLASH_2STARTY_UP*sp : (_len+_userLen) - STAFFTYPE_TAB_SLASH_2STARTY_DN*sp;
            // if stems through, try to align slashes within or across lines
            if (stt->stemThrough()) {
                  qreal halfLineDist = stt->lineDistance().val() * sp * 0.5;
                  qreal halfSlashHgt = STAFFTYPE_TAB_SLASH_2TOTHEIGHT * sp * 0.5;
                  y = lrint( (y + halfSlashHgt) / halfLineDist) * halfLineDist - halfSlashHgt;
                  }
            // draw slashes
            qreal hlfWdt= sp * STAFFTYPE_TAB_SLASH_WIDTH * 0.5;
            qreal sln   = sp * STAFFTYPE_TAB_SLASH_SLANTY;
            qreal thk   = sp * STAFFTYPE_TAB_SLASH_THICK;
            qreal displ = sp * STAFFTYPE_TAB_SLASH_DISPL;
            QPainterPath path;
            for (int i = 0; i < 2; ++i) {
                  path.moveTo( hlfWdt, y);            // top-right corner
                  path.lineTo( hlfWdt, y+thk);        // bottom-right corner
                  path.lineTo(-hlfWdt, y+thk+sln);    // bottom-left corner
                  path.lineTo(-hlfWdt, y+sln);        // top-left corner
                  path.closeSubpath();
                  y += displ;
                  }
            painter->setBrush(QBrush(curColor()));
            painter->setPen(Qt::NoPen);
            painter->drawPath(path);
            }

      // dots
      // NOT THE BEST PLACE FOR THIS?
      // with tablatures and stems beside staves, dots are not drawn near 'notes', but near stems
      int nDots = chord()->dots();
      if (nDots > 0 && !stt->stemThrough()) {
            qreal x     = chord()->dotPosX();
            qreal y     = ( (STAFFTYPE_TAB_DEFAULTSTEMLEN_DN * 0.2) * sp) * (_up ? -1.0 : 1.0);
            qreal step  = score()->styleS(StyleIdx::dotDotDistance).val() * sp;
            for (int dot = 0; dot < nDots; dot++, x += step)
                  drawSymbol(SymId::augmentationDot, painter, QPointF(x, y));
            }
      }
Beispiel #20
0
Space Breath::space() const
      {
      return Space(0.0, spatium() * 1.5);
      }
Beispiel #21
0
QFont Text::font() const
      {
      return _textStyle.font(spatium());
      }
Beispiel #22
0
void Glissando::layout()
      {
      qreal       _spatium    = spatium();

      if (score() == gscore                                                   // for use in palettes
                  || startElement() == nullptr || endElement() == nullptr) {  // or while dragging
            if (spannerSegments().isEmpty())
                  add(createLineSegment());
            LineSegment* s = frontSegment();
            s->setPos(QPointF());
            s->setPos2(QPointF(_spatium * GLISS_PALETTE_WIDTH, -_spatium * GLISS_PALETTE_HEIGHT));
            s->layout();
            return;
            }

      SLine::layout();
      setPos(0.0, 0.0);
      adjustReadPos();

      Note*       anchor1     = static_cast<Note*>(startElement());
      Note*       anchor2     = static_cast<Note*>(endElement());
      Chord*      cr1         = anchor1->chord();
      Chord*      cr2         = anchor2->chord();
      GlissandoSegment*       segm1 = static_cast<GlissandoSegment*>(frontSegment());
      GlissandoSegment*       segm2 = static_cast<GlissandoSegment*>(backSegment());

      // Note: line segments are defined by
      // initial point: ipos() (relative to system origin)
      // ending point:  pos2() (relative to initial point)

      // LINE ENDING POINTS TO NOTE HEAD CENTRES

      // assume gliss. line goes from centre of initial note centre to centre of ending note:
      // move first segment origin and last segment ending point from note head origin to note head centre
      QPointF     offs1       = QPointF(anchor1->headWidth() * 0.5, 0.0);
      QPointF     offs2       = QPointF(anchor2->headWidth() * 0.5, 0.0);

      // AVOID HORIZONTAL LINES

      int         upDown      = (0 < (anchor2->pitch() - anchor1->pitch())) - ((anchor2->pitch() - anchor1->pitch()) < 0);
      // on TAB's, glissando are by necessity on the same string, this gives an horizontal glissando line;
      // make bottom end point lower and top ending point higher
      if (cr1->staff()->isTabStaff()) {
                  qreal yOff = cr1->staff()->lineDistance() * 0.3 * _spatium;
                  offs1.ry() += yOff * upDown;
                  offs2.ry() -= yOff * upDown;
            }
      // if not TAB, angle glissando between notes on the same line
      else {
            if (anchor1->line() == anchor2->line()) {
                  offs1.ry() += _spatium * 0.25 * upDown;
                  offs2.ry() -= _spatium * 0.25 * upDown;
                  }
            }

      // move initial point of first segment and adjust its length accordingly
      segm1->setPos (segm1->ipos()  + offs1);
      segm1->setPos2(segm1->ipos2() - offs1);
      // adjust ending point of last segment
      segm2->setPos2(segm2->ipos2() + offs2);

      // FINAL SYSTEM-INITIAL NOTE
      // if the last gliss. segment attaches to a system-initial note, some extra width has to be added
      if (cr2->segment()->measure() == cr2->segment()->system()->firstMeasure() && cr2->rtick() == 0)
      {
            segm2->rxpos() -= GLISS_STARTOFSYSTEM_WIDTH * _spatium;
            segm2->rxpos2()+= GLISS_STARTOFSYSTEM_WIDTH * _spatium;
      }

      // INTERPOLATION OF INTERMEDIATE POINTS
      // This probably belongs to SLine class itself; currently it does not seem
      // to be needed for anything else than Glissando, though

      // get total x-width and total y-height of all segments
      qreal xTot = 0.0;
      for (SpannerSegment* segm : spannerSegments())
            xTot += segm->ipos2().x();
      qreal y0   = segm1->ipos().y();
      qreal yTot = segm2->ipos().y() + segm2->ipos2().y() - y0;
      qreal ratio = yTot / xTot;
      // interpolate y-coord of intermediate points across total width and height
      qreal xCurr = 0.0;
      qreal yCurr;
      for (int i = 0; i < spannerSegments().count()-1; i++)
      {
           SpannerSegment* segm = segmentAt(i);
           xCurr += segm->ipos2().x();
           yCurr = y0 + ratio * xCurr;
           segm->rypos2() = yCurr - segm->ipos().y();       // position segm. end point at yCurr
           // next segment shall start where this segment stopped
           segm = segmentAt(i+1);
           segm->rypos2() += segm->ipos().y() - yCurr;      // adjust next segm. vertical length
           segm->rypos() = yCurr;                           // position next segm. start point at yCurr
      }

      // STAY CLEAR OF NOTE APPENDAGES

      // initial note dots / ledger line / note head
      offs1 *= -1.0;          // discount changes already applied
      int dots = cr1->dots();
      LedgerLine * ledLin = cr1->ledgerLines();
      // if dots, start at right of last dot
      // if no dots, from right of ledger line, if any; from right of note head, if no ledger line
      offs1.rx() += (dots && anchor1->dot(dots-1) ? anchor1->dot(dots-1)->pos().x() + anchor1->dot(dots-1)->width()
                  : (ledLin ? ledLin->pos().x() + ledLin->width() : anchor1->headWidth()) );

      // final note arpeggio / accidental / ledger line / accidental / arpeggio (i.e. from outermost to innermost)
      offs2 *= -1.0;          // discount changes already applied
      if (Arpeggio* a = cr2->arpeggio())
            offs2.rx() += a->pos().x() + a->userOff().x();
      else if (Accidental* a = anchor2->accidental())
            offs2.rx() += a->pos().x() + a->userOff().x();
      else if ( (ledLin = cr2->ledgerLines()) != nullptr)
            offs2.rx() += ledLin->pos().x();

      // add another a quarter spatium of 'air'
      offs1.rx() += _spatium * 0.25;
      offs2.rx() -= _spatium * 0.25;

      // apply offsets: shorten first segment by x1 (and proportionally y) and adjust its length accordingly
      offs1.ry() = segm1->ipos2().y() * offs1.x() / segm1->ipos2().x();
      segm1->setPos(segm1->ipos() + offs1);
      segm1->setPos2(segm1->ipos2() - offs1);
      // adjust last segment length by x2 (and proportionally y)
      offs2.ry() = segm2->ipos2().y() * offs2.x() / segm2->ipos2().x();
      segm2->setPos2(segm2->ipos2() + offs2);

      for (SpannerSegment* segm : spannerSegments())
            static_cast<GlissandoSegment*>(segm)->layout();

      // compute glissando bbox as the bbox of the last segment, relative to the end anchor note
      QPointF anchor2PagePos = anchor2->pagePos();
      QPointF system2PagePos = cr2->segment()->system()->pagePos();
      QPointF anchor2SystPos = anchor2PagePos - system2PagePos;
      QRectF r = QRectF(anchor2SystPos - segm2->pos(), anchor2SystPos - segm2->pos() - segm2->pos2()).normalized();
      qreal lw = _spatium * lineWidth().val() * .5;
      setbbox(r.adjusted(-lw, -lw, lw, lw));
      }
Beispiel #23
0
bool Text::readProperties(const QDomElement& e)
      {
      const QString& tag(e.tagName());
      const QString& val(e.text());

      if (tag == "style") {
            int st;
            bool ok;
            int i = val.toInt(&ok);
            if (ok) {
                  // obsolete old text styles
                  switch (i) {
                        case 1:  i = TEXT_STYLE_UNSTYLED;  break;
                        case 2:  i = TEXT_STYLE_TITLE;     break;
                        case 3:  i = TEXT_STYLE_SUBTITLE;  break;
                        case 4:  i = TEXT_STYLE_COMPOSER;  break;
                        case 5:  i = TEXT_STYLE_POET;      break;
                        case 6:  i = TEXT_STYLE_LYRIC1;    break;
                        case 7:  i = TEXT_STYLE_LYRIC2;    break;
                        case 8:  i = TEXT_STYLE_FINGERING; break;
                        case 9:  i = TEXT_STYLE_INSTRUMENT_LONG;    break;
                        case 10: i = TEXT_STYLE_INSTRUMENT_SHORT;   break;
                        case 11: i = TEXT_STYLE_INSTRUMENT_EXCERPT; break;

                        case 12: i = TEXT_STYLE_DYNAMICS;  break;
                        case 13: i = TEXT_STYLE_TECHNIK;   break;
                        case 14: i = TEXT_STYLE_TEMPO;     break;
                        case 15: i = TEXT_STYLE_METRONOME; break;
                        case 16: i = TEXT_STYLE_FOOTER;    break;  // TEXT_STYLE_COPYRIGHT
                        case 17: i = TEXT_STYLE_MEASURE_NUMBER; break;
                        case 18: i = TEXT_STYLE_FOOTER; break;    // TEXT_STYLE_PAGE_NUMBER_ODD
                        case 19: i = TEXT_STYLE_FOOTER; break;    // TEXT_STYLE_PAGE_NUMBER_EVEN
                        case 20: i = TEXT_STYLE_TRANSLATOR; break;
                        case 21: i = TEXT_STYLE_TUPLET;     break;

                        case 22: i = TEXT_STYLE_SYSTEM;         break;
                        case 23: i = TEXT_STYLE_STAFF;          break;
                        case 24: i = TEXT_STYLE_HARMONY;        break;
                        case 25: i = TEXT_STYLE_REHEARSAL_MARK; break;
                        case 26: i = TEXT_STYLE_REPEAT;         break;
                        case 27: i = TEXT_STYLE_VOLTA;          break;
                        case 28: i = TEXT_STYLE_FRAME;          break;
                        case 29: i = TEXT_STYLE_TEXTLINE;       break;
                        case 30: i = TEXT_STYLE_GLISSANDO;      break;
                        case 31: i = TEXT_STYLE_STRING_NUMBER;  break;

                        case 32: i = TEXT_STYLE_OTTAVA;  break;
                        case 33: i = TEXT_STYLE_BENCH;   break;
                        case 34: i = TEXT_STYLE_HEADER;  break;
                        case 35: i = TEXT_STYLE_FOOTER;  break;
                        case 0:
                        default:
                              qDebug("Text:readProperties: style %d<%s> invalid", i, qPrintable(val));
                              i = TEXT_STYLE_UNSTYLED;
                              break;
                        }
                  st = i;
                  }
            else
                  st = score()->style()->textStyleType(val);

            if (st == TEXT_STYLE_UNSTYLED)
                  setUnstyled();
            else if (st == TEXT_STYLE_UNKNOWN)
                  _styleIndex = st;
            else
                  setTextStyleType(st);
            }
      else if (tag == "styleName")          // obsolete, unstyled text
            ; // _styleName = val;
      else if (tag == "data")                  // obsolete
            _doc->setHtml(val);
      else if (tag == "html") {
            QString s = Xml::htmlToString(e);
            setHtml(s);
            }
      else if (tag == "text")
            setText(val);
      else if (tag == "html-data") {
            QString s = Xml::htmlToString(e.firstChildElement());
            if (score()->mscVersion() <= 114) {
                  s.replace("MScore1", "FreeSerifMscore");
                  s.replace(QChar(0xe10e), QChar(0x266e));    //natural
                  s.replace(QChar(0xe10c), QChar(0x266f));    // sharp
                  s.replace(QChar(0xe10d), QChar(0x266d));    // flat
                  s.replace(QChar(0xe104), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd5e))),    // note2_Sym
                  s.replace(QChar(0xe105), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd5f)));    // note4_Sym
//test                  s.replace(QChar(0xe105), QString("XXX"));
                  s.replace(QChar(0xe106), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd60)));    // note8_Sym
                  s.replace(QChar(0xe107), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd61)));    // note16_Sym
                  s.replace(QChar(0xe108), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd62)));    // note32_Sym
                  s.replace(QChar(0xe109), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd63)));    // note64_Sym
                  s.replace(QChar(0xe10a), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd6d)));    // dot
                  s.replace(QChar(0xe10b), QString("%1%2%3%4").arg(QChar(0xd834)).arg(QChar(0xdd6d)).arg(QChar(0xd834)).arg(QChar(0xdd6d)));    // dotdot
                  s.replace(QChar(0xe167), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd0b)));    // coda
                  s.replace(QChar(0xe168), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd0c)));    // varcoda
                  s.replace(QChar(0xe169), QString("%1%2").arg(QChar(0xd834)).arg(QChar(0xdd0c)));    // segno
                  if (_doc == 0)
                        createDoc();
                  _doc->setHtml(s);
                  if (isSimpleText()) {
                        QString s = _doc->toPlainText();
                        delete _doc;
                        _doc = 0;
                        setText(s);
                        }
                  else {
                        setUnstyled();
                        setHtml(s);
                        }
                  }
            else {
                  setHtml(s);
                  }
            }
      else if (tag == "subtype")          // obsolete
            ;
      else if (tag == "frameWidth") {           // obsolete
            qreal spMM = spatium() / MScore::DPMM;
            setFrameWidth(Spatium(val.toDouble() / spMM));
            }
      else if (tag == "paddingWidth") {          // obsolete
            qreal spMM = spatium() / MScore::DPMM;
            setPaddingWidth(Spatium(val.toDouble() / spMM));
            }
      else if (_textStyle.readProperties(e))
            ;
      else if (!Element::readProperties(e))
            return false;
      return true;
      }
Beispiel #24
0
void System::layoutSystem(qreal xo1)
      {
      if (_staves.empty())                 // ignore vbox
            return;

      static const Spatium instrumentNameOffset(1.0);       // TODO: make style value

      int nstaves  = _staves.size();

      //---------------------------------------------------
      //  find x position of staves
      //    create brackets
      //---------------------------------------------------

      qreal xoff2 = 0.0;         // x offset for instrument name

      int bracketLevels = 0;
      for (int idx = 0; idx < nstaves; ++idx)
            bracketLevels = qMax(bracketLevels, score()->staff(idx)->bracketLevels());

      qreal bracketWidth[bracketLevels];
      for (int i = 0; i < bracketLevels; ++i)
            bracketWidth[i] = 0.0;

      QList<Bracket*> bl;
      bl.swap(_brackets);

      for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
            Staff* s = score()->staff(staffIdx);
            for (int i = 0; i < bracketLevels; ++i) {
                  if (s->bracket(i) == BracketType::NO_BRACKET)
                        continue;
                  int firstStaff = staffIdx;
                  int lastStaff  = staffIdx + s->bracketSpan(i) - 1;
                  if (lastStaff >= nstaves)
                        lastStaff = nstaves - 1;

                  for (; firstStaff <= lastStaff; ++firstStaff) {
                        if (score()->staff(firstStaff)->show())
                              break;
                        }
                  for (; lastStaff >= firstStaff; --lastStaff) {
                        if (score()->staff(lastStaff)->show())
                              break;
                        }
                  int span = lastStaff - firstStaff + 1;
                  //
                  // do not show bracket if it only spans one
                  // system due to some invisible staves
                  //
                  if ((span > 1) || (s->bracketSpan(i) == span)) {
                        //
                        // this bracket is visible
                        //
                        Bracket* b = 0;
                        int track = staffIdx * VOICES;
                        for (int k = 0; k < bl.size(); ++k) {
                              if (bl[k]->track() == track && bl[k]->level() == i) {
                                    b = bl.takeAt(k);
                                    break;
                                    }
                              }
                        if (b == 0) {
                              b = new Bracket(score());
                              b->setGenerated(true);
                              b->setTrack(track);
                              b->setLevel(i);
                              }
                        add(b);
                        b->setFirstStaff(firstStaff);
                        b->setLastStaff(lastStaff);
                        b->setBracketType(s->bracket(i));
                        b->setSpan(s->bracketSpan(i));
                        bracketWidth[i] = qMax(bracketWidth[i], b->width());
                        }
                  }
            if (!s->show())
                  continue;
            for (InstrumentName* t : _staves[staffIdx]->instrumentNames) {
                  t->layout();
                  qreal w = t->width() + point(instrumentNameOffset);
                  if (w > xoff2)
                        xoff2 = w;
                  }
            }

      for (Bracket* b : bl)
            delete b;

      //---------------------------------------------------
      //  layout  SysStaff and StaffLines
      //---------------------------------------------------

      _leftMargin = xoff2;


      qreal bd = score()->styleP(StyleIdx::bracketDistance);
      if ( _brackets.size() > 0) {
            for (int i = 0; i < bracketLevels; ++i)
                  _leftMargin += bracketWidth[i] + bd;
            }

      int nVisible = 0;
      for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
            SysStaff* s  = _staves[staffIdx];
            Staff* staff = score()->staff(staffIdx);
            if (!staff->show() || !s->show()) {
                  s->setbbox(QRectF());
                  continue;
                  }
            ++nVisible;
            qreal staffMag = staff->mag();
            qreal h;
            if (staff->lines() == 1)
                  h = 2;
            else
                  h = (staff->lines()-1) * staff->lineDistance();
            h = h * staffMag * spatium();
            s->bbox().setRect(_leftMargin + xo1, 0.0, 0.0, h);
            }

      //---------------------------------------------------
      //  layout brackets
      //---------------------------------------------------

      for (Bracket* b : _brackets) {
            qreal xo = -xo1;
            for (const Bracket* b2 : _brackets) {
                   if (b->level() > b2->level() &&
                      ((b->firstStaff() >= b2->firstStaff() && b->firstStaff() <= b2->lastStaff()) ||
                      (b->lastStaff() >= b2->firstStaff() && b->lastStaff() <= b2->lastStaff())))
                        xo += b2->width() + bd;
                   }
            b->rxpos() = _leftMargin - xo - b->width();
            }

      //---------------------------------------------------
      //  layout instrument names x position
      //---------------------------------------------------

      int idx = 0;
      for (const Part* p : score()->parts()) {
            SysStaff* s = staff(idx);
            if (s->show() && p->show()) {
                  for (InstrumentName* t : s->instrumentNames) {
                        switch (t->textStyle().align() & AlignmentFlags::HMASK) {
                              case int(AlignmentFlags::LEFT):
                                    t->rxpos() = 0;
                                    break;
                              case int(AlignmentFlags::HCENTER):
                                    t->rxpos() = (xoff2 - point(instrumentNameOffset) + xo1) * .5;
                                    break;
                              case int(AlignmentFlags::RIGHT):
                              default:
                                    t->rxpos() = xoff2 - point(instrumentNameOffset) + xo1;
                                    break;
                              }
                        t->rxpos() += t->textStyle().offset(t->spatium()).x();
                        }
                  }
            idx += p->nstaves();
            }
      }
Beispiel #25
0
qreal Text::lineHeight() const
      {
      return QFontMetricsF(textStyle().font(spatium())).height();
      }
Beispiel #26
0
void System::layout2()
      {
      VBox* b = vbox();
      if (b) {
            b->layout();
            setbbox(b->bbox());
            return;
            }

      setPos(0.0, 0.0);
      QList<std::pair<int,SysStaff*>> visibleStaves;

      int firstStaffIdx        = -1;
      int lastStaffIdx         = 0;
      int firstStaffInitialIdx = -1;
      int lastStaffInitialIdx  = 0;
      Measure* fm              = firstMeasure();

      for (int i = 0; i < _staves.size(); ++i) {
            Staff*    s  = score()->staff(i);
            SysStaff* ss = _staves[i];
            if (s->show() && ss->show()) {
                  visibleStaves.append(std::pair<int,SysStaff*>(i, ss));
                  if (firstStaffIdx == -1)
                        firstStaffIdx = i;
                  if (i > lastStaffIdx)
                        lastStaffIdx = i;
                  if (fm && fm->visible(i)) {
                        if (firstStaffInitialIdx == -1)
                              firstStaffInitialIdx = i;
                        lastStaffInitialIdx = i;
                        }
                  }
            else {
                  ss->setbbox(QRectF());  // already done in layout() ?
                  }
            }
      if (firstStaffIdx == -1)
            firstStaffIdx = 0;
      if (firstStaffInitialIdx == -1)
            firstStaffInitialIdx = 0;

      qreal _spatium            = spatium();
      qreal y                   = 0.0;
      qreal minVerticalDistance = score()->styleP(StyleIdx::minVerticalDistance);
      qreal staffDistance       = score()->styleP(StyleIdx::staffDistance);
      qreal akkoladeDistance    = score()->styleP(StyleIdx::akkoladeDistance);

      if (visibleStaves.empty()) {
            qDebug("====no visible staves, staves %d, score staves %d", _staves.size(), score()->nstaves());
            }

      for (auto i = visibleStaves.begin();; ++i) {
            SysStaff* ss  = i->second;
            int si1       = i->first;
            Staff* staff  = score()->staff(si1);
            auto ni       = i + 1;

            qreal h = staff->height();
            if (ni == visibleStaves.end()) {
                  ss->setYOff(staff->lines() == 1 ? _spatium * staff->mag() : 0.0);
                  ss->bbox().setRect(_leftMargin, y, width() - _leftMargin, h);
                  break;
                  }

            int si2    = ni->first;
            qreal dist = h;

            switch (staff->innerBracket()) {
                  case BracketType::BRACE:
                        dist += akkoladeDistance;
                        break;
                  case BracketType::NORMAL:
                  case BracketType::SQUARE:
                  case BracketType::LINE:
                  case BracketType::NO_BRACKET:
                        dist += staffDistance;
                        break;
                  }
            dist += score()->staff(si2)->userDist();

            for (MeasureBase* mb : ml) {
                  if (!mb->isMeasure())
                        continue;
                  Measure* m = toMeasure(mb);
                  Shape& s1 = m->staffShape(si1);
                  Shape& s2 = m->staffShape(si2);

                  qreal d = s1.minVerticalDistance(s2) + minVerticalDistance;
                  dist    = qMax(dist, d);

                  Spacer* sp = m->mstaff(si1)->_vspacerDown;
                  if (sp) {
                        if (sp->spacerType() == SpacerType::FIXED) {
                              dist = staff->height() + sp->gap();
                              break;
                              }
                        else
                              dist = qMax(dist, staff->height() + sp->gap());
                        }
                  sp = m->mstaff(si2)->_vspacerUp;
                  if (sp)
                        dist = qMax(dist, sp->gap());
                  }

            ss->setYOff(staff->lines() == 1 ? _spatium * staff->mag() : 0.0);
            ss->bbox().setRect(_leftMargin, y, width() - _leftMargin, h);
            y += dist;
            }

      qreal systemHeight = staff(lastStaffIdx)->bbox().bottom();
      setHeight(systemHeight);

      for (MeasureBase* m : ml) {
            if (m->isMeasure()) {
                  // note that the factor 2 * _spatium must be corrected for when exporting
                  // system distance in MusicXML (issue #24733)
                  m->bbox().setRect(0.0, -_spatium, m->width(), systemHeight + 2.0 * _spatium);
                  }
            else if (m->isHBox()) {
                  m->bbox().setRect(0.0, 0.0, m->width(), systemHeight);
                  toHBox(m)->layout2();
                  }
            else if (m->isTBox()) {
//                  m->bbox().setRect(0.0, 0.0, m->width(), systemHeight);
                  toTBox(m)->layout();
                  }
            else
                  qDebug("unhandled measure type %s", m->name());
            }

      if (fm) {
            Segment* s        = fm->first();
            BarLine* _barLine = s->isBeginBarLineType() ? toBarLine(s->element(0)) : 0;

            if (_barLine) {
                  _barLine->setTrack(firstStaffInitialIdx * VOICES);
                  _barLine->setSpan(lastStaffInitialIdx - firstStaffInitialIdx + 1);
                  if (score()->staff(firstStaffInitialIdx)->lines() == 1)
                        _barLine->setSpanFrom(BARLINE_SPAN_1LINESTAFF_FROM);
                  else
                        _barLine->setSpanFrom(0);
                  int llines = score()->staff(lastStaffInitialIdx)->lines();
                  int spanTo = llines == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (llines - 1) * 2;
                  _barLine->setSpanTo(spanTo);
                  _barLine->layout();
                  }
            }

      //---------------------------------------------------
      //  layout brackets vertical position
      //---------------------------------------------------

      for (Bracket* b : _brackets) {
            int staffIdx1 = b->firstStaff();
            int staffIdx2 = b->lastStaff();
            qreal sy = 0;                       // assume bracket not visible
            qreal ey = 0;
            // if start staff not visible, try next staff
            while (staffIdx1 <= staffIdx2 && !_staves[staffIdx1]->show())
                  ++staffIdx1;
            // if end staff not visible, try prev staff
            while (staffIdx1 <= staffIdx2 && !_staves[staffIdx2]->show())
                  --staffIdx2;
            // the bracket will be shown IF:
            // it spans at least 2 visible staves (staffIdx1 < staffIdx2) OR
            // it spans just one visible staff (staffIdx1 == staffIdx2) but it is required to do so
            // (the second case happens at least when the bracket is initially dropped)
            bool notHidden = (staffIdx1 < staffIdx2) || (b->span() == 1 && staffIdx1 == staffIdx2);
            if (notHidden) {                    // set vert. pos. and height to visible spanned staves
                  sy = _staves[staffIdx1]->bbox().top();
                  ey = _staves[staffIdx2]->bbox().bottom();
                  }
            b->rypos() = sy;
//            if (score()->staff(firstStaffInitialIdx)->lines() == 1)   // bbox of one line staff bad?
//                  b->rypos() -= _spatium;
            b->setHeight(ey - sy);
            b->layout();
            }

      //---------------------------------------------------
      //  layout instrument names
      //---------------------------------------------------

      int staffIdx = 0;

      for (Part* p : score()->parts()) {
            SysStaff* s = staff(staffIdx);
            SysStaff* s2;
            int nstaves = p->nstaves();
            if (s->show()) {
                  for (InstrumentName* t : s->instrumentNames) {
                        //
                        // override Text->layout()
                        //
                        qreal y1, y2;
                        switch (t->layoutPos()) {
                              default:
                              case 0:           // center at part
                                    y1 = s->bbox().top();
                                    s2 = staff(staffIdx);
                                    for (int i = staffIdx + nstaves - 1; i > 0; --i) {
                                          SysStaff* s = staff(i);
                                          if (s->show()) {
                                                s2 = s;
                                                break;
                                                }
                                          }
                                    y2 = s2->bbox().bottom();
                                    break;
                              case 1:           // center at first staff
                                    y1 = s->bbox().top();
                                    y2 = s->bbox().bottom();
                                    break;

                              // TODO:
                              // sort out invisible staves

                              case 2:           // center between first and second staff
                                    y1 = s->bbox().top();
                                    y2 = staff(staffIdx + 1)->bbox().bottom();
                                    break;
                              case 3:           // center at second staff
                                    y1 = staff(staffIdx + 1)->bbox().top();
                                    y2 = staff(staffIdx + 1)->bbox().bottom();
                                    break;
                              case 4:           // center between first and second staff
                                    y1 = staff(staffIdx + 1)->bbox().top();
                                    y2 = staff(staffIdx + 2)->bbox().bottom();
                                    break;
                              case 5:           // center at third staff
                                    y1 = staff(staffIdx + 2)->bbox().top();
                                    y2 = staff(staffIdx + 2)->bbox().bottom();
                                    break;
                              }
                        t->rypos() = y1 + (y2 - y1) * .5 + t->textStyle().offset(t->spatium()).y();
                        }
                  }
            staffIdx += nstaves;
            }
      }
Beispiel #27
0
void Hairpin::setYoff(qreal val)
      {
      rUserYoffset() += (val - score()->styleS(StyleIdx::hairpinY).val()) * spatium();
      }
Beispiel #28
0
void Fingering::layout()
      {
      if (parent()) {
            Fraction tick = parent()->tick();
            const Staff* st = staff();
            if (st && st->isTabStaff(tick) && !st->staffType(tick)->showTabFingering()) {
                  setbbox(QRectF());
                  return;
                  }
            }

      TextBase::layout();
      rypos() = 0.0;    // handle placement below

      if (autoplace() && note()) {
            Note* n      = note();
            Chord* chord = n->chord();
            bool voices  = chord->measure()->hasVoices(chord->staffIdx());
            bool tight   = voices && chord->notes().size() == 1 && !chord->beam() && tid() != Tid::STRING_NUMBER;

            qreal headWidth = n->bboxRightPos();

            // update offset after drag
            qreal rebase = 0.0;
            if (offsetChanged() != OffsetChange::NONE)
                  rebase = rebaseOffset();

            // temporarily exclude self from chord shape
            setAutoplace(false);

            if (layoutType() == ElementType::CHORD) {
                  Stem* stem = chord->stem();
                  Segment* s = chord->segment();
                  Measure* m = s->measure();
                  qreal sp = spatium();
                  qreal md = minDistance().val() * sp;
                  SysStaff* ss = m->system()->staff(chord->vStaffIdx());
                  Staff* vStaff = chord->staff();     // TODO: use current height at tick

                  if (n->mirror())
                        rxpos() -= n->ipos().x();
                  rxpos() += headWidth * .5;
                  if (placeAbove()) {
                        if (tight) {
                              if (chord->stem())
                                    rxpos() -= 0.8 * sp;
                              rypos() -= 1.5 * sp;
                              }
                        else {
                              QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos());
                              SkylineLine sk(false);
                              sk.add(r.x(), r.bottom(), r.width());
                              qreal d = sk.minDistance(ss->skyline().north());
                              qreal yd = 0.0;
                              if (d > 0.0 && isStyled(Pid::MIN_DISTANCE))
                                    yd -= d + height() * .25;
                              // force extra space above staff & chord (but not other fingerings)
                              qreal top;
                              if (chord->up() && chord->beam() && stem) {
                                    top = stem->y() + stem->bbox().top();
                                    }
                              else {
                                    Note* un = chord->upNote();
                                    top = qMin(0.0, un->y() + un->bbox().top());
                                    }
                              top -= md;
                              qreal diff = (bbox().bottom() + ipos().y() + yd + n->y()) - top;
                              if (diff > 0.0)
                                    yd -= diff;
                              if (offsetChanged() != OffsetChange::NONE) {
                                    // user moved element within the skyline
                                    // we may need to adjust minDistance, yd, and/or offset
                                    bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height();
                                    rebaseMinDistance(md, yd, sp, rebase, inStaff);
                                    }
                              rypos() += yd;
                              }
                        }
                  else {
                        if (tight) {
                              if (chord->stem())
                                    rxpos() += 0.8 * sp;
                              rypos() += 1.5 * sp;
                              }
                        else {
                              QRectF r = bbox().translated(m->pos() + s->pos() + chord->pos() + n->pos() + pos());
                              SkylineLine sk(true);
                              sk.add(r.x(), r.top(), r.width());
                              qreal d = ss->skyline().south().minDistance(sk);
                              qreal yd = 0.0;
                              if (d > 0.0 && isStyled(Pid::MIN_DISTANCE))
                                    yd += d + height() * .25;
                              // force extra space below staff & chord (but not other fingerings)
                              qreal bottom;
                              if (!chord->up() && chord->beam() && stem) {
                                    bottom = stem->y() + stem->bbox().bottom();
                                    }
                              else {
                                    Note* dn = chord->downNote();
                                    bottom = qMax(vStaff->height(), dn->y() + dn->bbox().bottom());
                                    }
                              bottom += md;
                              qreal diff = bottom - (bbox().top() + ipos().y() + yd + n->y());
                              if (diff > 0.0)
                                    yd += diff;
                              if (offsetChanged() != OffsetChange::NONE) {
                                    // user moved element within the skyline
                                    // we may need to adjust minDistance, yd, and/or offset
                                    bool inStaff = placeAbove() ? r.bottom() + rebase > 0.0 : r.top() + rebase < staff()->height();
                                    rebaseMinDistance(md, yd, sp, rebase, inStaff);
                                    }
                              rypos() += yd;
                              }
                        }
                  }
            else if (tid() == Tid::LH_GUITAR_FINGERING) {
                  // place to left of note
                  qreal left = n->shape().left();
                  if (left - n->x() > 0.0)
                        rxpos() -= left;
                  else
                        rxpos() -= n->x();
                  }
            // for other fingering styles, do not autoplace

            // restore autoplace
            setAutoplace(true);
            }
      else if (offsetChanged() != OffsetChange::NONE) {
            // rebase horizontally too, as autoplace may have adjusted it
            rebaseOffset(false);
            }
      setOffsetChanged(false);
      }
Beispiel #29
0
void Tie::computeBezier(SlurSegment* ss, QPointF p6o)
      {
      qreal _spatium  = spatium();
      qreal shoulderW;              // height as fraction of slur-length
      qreal shoulderH;

      //
      // pp1      start of slur
      // pp2      end of slur
      // pp3      bezier 1
      // pp4      bezier 2
      // pp5      drag
      // pp6      shoulder
      //
      QPointF pp1 = ss->ups[GRIP_START].p + ss->ups[GRIP_START].off * _spatium;
      QPointF pp2 = ss->ups[GRIP_END].p   + ss->ups[GRIP_END].off   * _spatium;

      QPointF p2 = pp2 - pp1;       // normalize to zero
      if (p2.x() == 0.0) {
            qDebug("zero tie");
            return;
            }

      qreal sinb = atan(p2.y() / p2.x());
      QTransform t;
      t.rotateRadians(-sinb);
      p2  = t.map(p2);
      p6o = t.map(p6o);

      double smallH = 0.38;
      qreal d   = p2.x() / _spatium;
      shoulderH = d * 0.4 * smallH;
      if (shoulderH > 1.3)            // maximum tie shoulder height
            shoulderH = 1.3;
      shoulderH *= _spatium;
      shoulderW = .6;

      if (!up())
            shoulderH = -shoulderH;

      qreal c    = p2.x();
      qreal c1   = (c - c * shoulderW) * .5 + p6o.x();
      qreal c2   = c1 + c * shoulderW       + p6o.x();

      QPointF p5 = QPointF(c * .5, 0.0);

      QPointF p3(c1, -shoulderH);
      QPointF p4(c2, -shoulderH);

      qreal w = (score()->styleS(ST_SlurMidWidth).val() - score()->styleS(ST_SlurEndWidth).val()) * _spatium;
      QPointF th(0.0, w);    // thickness of slur

      QPointF p3o = p6o + t.map(ss->ups[GRIP_BEZIER1].off * _spatium);
      QPointF p4o = p6o + t.map(ss->ups[GRIP_BEZIER2].off * _spatium);
//      ss->ups[GRIP_BEZIER1].off = t.inverted().map(p3o) / _spatium;
//      ss->ups[GRIP_BEZIER2].off = t.inverted().map(p4o) / _spatium;

      //-----------------------------------calculate p6
      QPointF pp3  = p3 + p3o;
      QPointF pp4  = p4 + p4o;
      QPointF ppp4 = pp4 - pp3;

      qreal r2 = atan(ppp4.y() / ppp4.x());
      t.reset();
      t.rotateRadians(-r2);
      QPointF p6  = QPointF(t.map(ppp4).x() * .5, 0.0);

      t.rotateRadians(2 * r2);
      p6 = t.map(p6) + pp3; //  - p6o;
      //-----------------------------------

      ss->path = QPainterPath();
      ss->path.moveTo(QPointF());
      ss->path.cubicTo(p3 + p3o - th, p4 + p4o - th, p2);
      if (lineType() == 0)
            ss->path.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF());

      th = QPointF(0.0, 3.0 * w);
      ss->shapePath = QPainterPath();
      ss->shapePath.moveTo(QPointF());
      ss->shapePath.cubicTo(p3 + p3o - th, p4 + p4o - th, p2);
      ss->shapePath.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF());

      // translate back
      t.reset();
      t.translate(pp1.x(), pp1.y());
      t.rotateRadians(sinb);
      ss->path                 = t.map(ss->path);
      ss->shapePath            = t.map(ss->shapePath);
      ss->ups[GRIP_BEZIER1].p  = t.map(p3);
      ss->ups[GRIP_BEZIER2].p  = t.map(p4);
      ss->ups[GRIP_END].p      = t.map(p2) - ss->ups[GRIP_END].off * _spatium;
      ss->ups[GRIP_DRAG].p     = t.map(p5);
      ss->ups[GRIP_SHOULDER].p = t.map(p6);
      }
Beispiel #30
0
void OttavaSegment::layout()
      {
      TextLineBaseSegment::layout();
      autoplaceSpannerSegment(spatium() * .7);
      }