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(); }
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; } }
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); }
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(); }
qreal Text::lineSpacing() const { return QFontMetricsF(textStyle().font(spatium())).lineSpacing(); }
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(); } }
Space Glissando::space() const { return Space(0.0, spatium() * 2.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); }
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(); }
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(); }
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(); }
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(); }
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; } }
QSizeF Image::pixel2size(const QSizeF& s) const { return s / (_sizeIsSpatium ? spatium() : DPMM); }
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; }
QSizeF Image::size2pixel(const QSizeF& s) const { return s * (_sizeIsSpatium ? spatium() : DPMM); }
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)); } }
Space Breath::space() const { return Space(0.0, spatium() * 1.5); }
QFont Text::font() const { return _textStyle.font(spatium()); }
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)); }
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; }
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(); } }
qreal Text::lineHeight() const { return QFontMetricsF(textStyle().font(spatium())).height(); }
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; } }
void Hairpin::setYoff(qreal val) { rUserYoffset() += (val - score()->styleS(StyleIdx::hairpinY).val()) * spatium(); }
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); }
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); }
void OttavaSegment::layout() { TextLineBaseSegment::layout(); autoplaceSpannerSegment(spatium() * .7); }