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 Image::layout() { setPos(0.0, 0.0); if (imageType == ImageType::SVG && !svgDoc) { if (_storeItem) svgDoc = new QSvgRenderer(_storeItem->buffer()); } else if (imageType == ImageType::RASTER && !rasterDoc) { if (_storeItem) { rasterDoc = new QImage; rasterDoc->loadFromData(_storeItem->buffer()); if (!rasterDoc->isNull()) _dirty = true; } } if (_size.isNull()) _size = pixel2size(imageSize()); // if autoscale && inside a box, scale to box relevant size if (autoScale() && parent() && ((parent()->isHBox() || parent()->isVBox()))) { if (_lockAspectRatio) { qreal f = _sizeIsSpatium ? spatium() : DPMM; QSizeF size(imageSize()); qreal ratio = size.width() / size.height(); qreal w = parent()->width(); qreal h = parent()->height(); if ((w / h) < ratio) { _size.setWidth(w / f); _size.setHeight((w / ratio) / f); } else { _size.setHeight(h / f); _size.setWidth(h * ratio / f); } } else _size = pixel2size(parent()->bbox().size()); } // in any case, adjust position relative to parent setbbox(QRectF(QPointF(), size2pixel(_size))); }
void Stem::layout() { qreal l = _len + _userLen; qreal _up = up() ? -1.0 : 1.0; l *= _up; qreal y1 = 0.0; // vertical displacement to match note attach point Staff* stf = staff(); if (chord()) { int tick = chord()->tick(); StaffType* st = stf->staffType(tick); if (st->isTabStaff() ) { // TAB staves if (st->stemThrough()) { // if stems through staves, gets Y pos. of stem-side note relative to chord other side qreal lineDist = st->lineDistance().val() * spatium(); y1 = (chord()->downString() - chord()->upString()) * _up * lineDist; // if fret marks above lines, raise stem beginning by 1/2 line distance if (!st->onLines()) y1 -= lineDist * 0.5; // shorten stem by 1/2 lineDist to clear the note and a little more to keep 'air' betwen stem and note lineDist *= 0.7 * mag(); y1 += _up * lineDist; } // in other TAB types, no correction } else { // non-TAB // move stem start to note attach point Note* n = up() ? chord()->downNote() : chord()->upNote(); y1 += (up() ? n->stemUpSE().y() : n->stemDownNW().y()); rypos() = n->rypos(); } } qreal lw5 = _lineWidth * .5; line.setLine(0.0, y1, 0.0, l); // compute bounding rectangle QRectF r(line.p1(), line.p2()); setbbox(r.normalized().adjusted(-lw5, -lw5, lw5, lw5)); adjustReadPos(); // does not work if stem is layouted twice }
void TrillSegment::symbolLine(SymId start, SymId fill, SymId end) { qreal x1 = 0; qreal x2 = pos2().x(); qreal w = x2 - x1; qreal mag = magS(); ScoreFont* f = score()->scoreFont(); _symbols.clear(); _symbols.push_back(start); qreal w1 = f->advance(start, mag); qreal w2 = f->advance(fill, mag); qreal w3 = f->advance(end, mag); int n = lrint((w - w1 - w3) / w2); for (int i = 0; i < n; ++i) _symbols.push_back(fill); _symbols.push_back(end); QRectF r(f->bbox(_symbols, mag)); setbbox(r); }
void TrillSegment::layout() { QRectF b1(symBbox(SymId::ornamentTrill)); QRectF rr(b1.translated(-b1.x(), 0.0)); rr |= QRectF(0.0, rr.y(), pos2().x(), rr.height()); setbbox(rr); if (parent()) rypos() += score()->styleS(ST_trillY).val() * spatium(); if (spannerSegmentType() == SEGMENT_SINGLE || spannerSegmentType() == SEGMENT_BEGIN) { Accidental* a = trill()->accidental(); if (a) { a->layout(); a->setMag(a->mag() * .6); qreal _spatium = spatium(); a->setPos(_spatium*1.3, -2.2*_spatium); a->adjustReadPos(); } } adjustReadPos(); }
void TrillSegment::symbolLine(SymId start, SymId fill, SymId end) { qreal x1 = 0; qreal x2 = pos2().x(); qreal w = x2 - x1; qreal mag = magS(); ScoreFont* f = score()->scoreFont(); _symbols.clear(); _symbols.append(f->toString(start)); _symbols.append(f->toString(end)); qreal w1 = f->bbox(start, mag).width(); qreal w2 = f->width(fill, mag); qreal w3 = f->width(end, mag); int n = lrint((w - w1 - w3) / w2); for (int i = 0; i < n; ++i) _symbols.insert(1, f->toString(fill)); QRectF r(f->bbox(_symbols, mag)); setbbox(r); }
void Spacer::layout0() { qreal _spatium = spatium(); path = QPainterPath(); qreal w = _spatium; qreal b = w * .5; qreal h = _gap; switch (spacerType()) { case SpacerType::DOWN: path.lineTo(w, 0.0); path.moveTo(b, 0.0); path.lineTo(b, h); path.lineTo(0.0, h-b); path.moveTo(b, h); path.lineTo(w, h-b); break; case SpacerType::UP: path.moveTo(b, 0.0); path.lineTo(0.0, b); path.moveTo(b, 0.0); path.lineTo(w, b); path.moveTo(b, 0.0); path.lineTo(b, h); path.moveTo(0.0, h); path.lineTo(w, h); break; case SpacerType::FIXED: path.lineTo(w, 0.0); path.moveTo(b, 0.0); path.lineTo(b, h); path.moveTo(0.0, h); path.lineTo(w, h); break; } qreal lw = _spatium * 0.4; QRectF bb(0, 0, w, h); bb.adjust(-lw, -lw, lw, lw); setbbox(bb); }
void Symbol::layout() { // foreach(Element* e, leafs()) done in BSymbol::layout() ? // e->layout(); setbbox(_scoreFont ? _scoreFont->bbox(_sym, magS()) : symBbox(_sym)); QPointF o(offset()); qreal w = width(); QPointF p; if (align() & Align::BOTTOM) p.setY(- height()); else if (align() & Align::VCENTER) p.setY((- height()) * .5); else if (align() & Align::BASELINE) p.setY(-baseLine()); if (align() & Align::RIGHT) p.setX(-w); else if (align() & Align::HCENTER) p.setX(-(w * .5)); setPos(p); BSymbol::layout(); }
void Stem::layout() { qreal l = _len + _userLen; if (up()) l = -l; Staff* st = staff(); qreal lw5 = point(score()->styleS(ST_stemWidth)) * .5; QPointF p1(0.0, 0.0); QPointF p2(0.0, l); if (st) { // if TAB, use simplified positioning if (st->isTabStaff()) { p1.rx() = -lw5; p2.rx() = -lw5; } // for any other staff type, use standard positioning else if (chord()) { // adjust P1 for note head Chord* c = chord(); if (c->up()) { Note* n = c->downNote(); p1 = symbols[score()->symIdx()][n->noteHead()].attach(n->magS()); p1.rx() = -lw5; p2.rx() = -lw5; } else { Note* n = c->upNote(); p1 = -symbols[score()->symIdx()][n->noteHead()].attach(n->magS()); p1.rx() = lw5; p2.rx() = lw5; } } } line.setP1(p1); line.setP2(p2); // compute bounding rectangle QRectF r(line.p1(), line.p2()); setbbox(r.normalized().adjusted(-lw5, -lw5, lw5, lw5)); }
void Stem::layout() { qreal l = _len + _userLen; qreal _up = up() ? -1.0 : 1.0; l *= _up; qreal y1 = 0.0; // vertical displacement to match note attach point Staff* st = staff(); if (chord() && st ) { if (st->isTabStaff() ) { // TAB staves if ( ((StaffTypeTablature*)st->staffType())->stemThrough()) { // if stems through staves, gets Y pos. of stem-side note relative to chord other side qreal lineDist = st->lineDistance() * spatium(); y1 = (chord()->downString() - chord()->upString() ) * _up * lineDist; // if fret marks above lines, raise stem beginning by 1/2 line distance if ( !((StaffTypeTablature*)st->staffType())->onLines() ) y1 -= lineDist * 0.5; // shorten stem by 1/2 lineDist to clear the note and a little more to keep 'air' betwen stem and note lineDist *= 0.7 * mag(); y1 += _up * lineDist; } // in other TAB types, no correction } else { // non-TAB // move stem start to note attach point Note* n = up() ? chord()->downNote() : chord()->upNote(); const Sym& sym = symbols[score()->symIdx()][n->noteHead()]; if (n->mirror()) _up *= -1; y1 -= sym.attach(n->magS()).y() * _up; } } line.setLine(0.0, y1, 0.0, l); // compute bounding rectangle QRectF r(line.p1(), line.p2()); qreal lw5 = lineWidth() * .5; setbbox(r.normalized().adjusted(-lw5, -lw5, lw5, lw5)); }
void RepeatMeasure::layout() { qreal sp = spatium(); qreal y = sp; qreal w = sp * 2.0; qreal h = sp * 2.0; qreal lw = sp * .30; // line width qreal r = sp * .15; // dot radius path = QPainterPath(); path.moveTo(w - lw, y); path.lineTo(w, y); path.lineTo(lw, h+y); path.lineTo(0.0, h+y); path.closeSubpath(); path.addEllipse(QRectF(w * .25 - r, y+h * .25 - r, r * 2.0, r * 2.0 )); path.addEllipse(QRectF(w * .75 - r, y+h * .75 - r, r * 2.0, r * 2.0 )); setbbox(path.boundingRect()); }
void Stem::layout() { qreal l = _len + _userLen; qreal _up = up() ? -1.0 : 1.0; l *= _up; qreal y1 = 0.0; Staff* st = staff(); if (chord() && st && !st->isTabStaff()) { Note* n = up() ? chord()->downNote() : chord()->upNote(); const Sym& sym = symbols[score()->symIdx()][n->noteHead()]; if (n->mirror()) _up *= -1; y1 -= sym.attach(n->magS()).y() * _up; } line.setLine(0.0, y1, 0.0, l); // compute bounding rectangle QRectF r(line.p1(), line.p2()); qreal lw5 = lineWidth() * .5; setbbox(r.normalized().adjusted(-lw5, -lw5, lw5, lw5)); }
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(); } }
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 Glissando::setSize(const QSizeF& s) { line = QLineF(0.0, s.height(), s.width(), 0.0); setbbox(QRectF(QPointF(), s)); }
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 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)); }
void Breath::layout() { setbbox(symBbox(symList[breathType()])); }
void Clef::layout() { // determine current number of lines and line distance int lines; qreal lineDist; Segment* clefSeg = segment(); // check clef visibility and type compatibility if (clefSeg && staff()) { StaffType* staffType = staff()->staffType(); bool show = staffType->genClef(); // check staff type allows clef display int tick = clefSeg->tick(); // check clef is compatible with staff type group: if (ClefInfo::staffGroup(clefType()) != staffType->group()) { if (tick > 0 && !generated()) // if clef is not generated, hide it show = false; else // if generated, replace with initial clef type // TODO : instead of initial staff clef (which is assumed to be compatible) // use the last compatible clef previously found in staff _clefTypes = staff()->clefType(0); } // if clef not to show or not compatible with staff group if (!show) { setbbox(QRectF()); qDebug("Clef::layout(): invisible clef at tick %d(%d) staff %d", segment()->tick(), segment()->tick()/1920, staffIdx()); return; } lines = staffType->lines(); // init values from staff type lineDist = staffType->lineDistance().val(); } else { lines = 5; lineDist = 1.0; } qreal _spatium = spatium(); qreal yoff = 0.0; if (clefType() != ClefType::INVALID && clefType() != ClefType::MAX) { symId = ClefInfo::symId(clefType()); yoff = lineDist * (lines - ClefInfo::line(clefType())); } switch (clefType()) { case ClefType::C_19C: // 19th C clef is like a G clef yoff = lineDist * 1.5; break; case ClefType::TAB: // TAB clef // on tablature, position clef at half the number of spaces * line distance yoff = lineDist * (lines - 1) * .5; break; case ClefType::TAB4: // TAB clef 4 strings // on tablature, position clef at half the number of spaces * line distance yoff = lineDist * (lines - 1) * .5; break; case ClefType::TAB_SERIF: // TAB clef alternate style // on tablature, position clef at half the number of spaces * line distance yoff = lineDist * (lines - 1) * .5; break; case ClefType::TAB4_SERIF: // TAB clef alternate style // on tablature, position clef at half the number of spaces * line distance yoff = lineDist * (lines - 1) * .5; break; case ClefType::PERC: // percussion clefs yoff = lineDist * (lines - 1) * 0.5; break; case ClefType::PERC2: yoff = lineDist * (lines - 1) * 0.5; break; case ClefType::INVALID: case ClefType::MAX: qDebug("Clef::layout: invalid type"); return; default: break; } // clefs are right aligned to Segment QRectF r(symBbox(symId)); // setPos(-r.right(), yoff * _spatium); setPos(0.0, yoff * _spatium); setbbox(r); }
void NoteDot::layout() { setbbox(symBbox(SymId::augmentationDot)); }
void Clef::clear() { setbbox(QRectF()); symId = SymId::noSym; }
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 Breath::layout() { setbbox(symbols[score()->symIdx()][symList[subtype()]].bbox(magS())); }
void TextLineSegment::layout1() { TextLine* tl = textLine(); if (!tl->diagonal()) _userOff2.setY(0); switch (subtype()) { case SEGMENT_SINGLE: case SEGMENT_BEGIN: if (tl->beginText()) { if (_text == 0) { _text = new Text(*tl->beginText()); _text->setFlag(ELEMENT_MOVABLE, false); _text->setParent(this); } } else { delete _text; _text = 0; } break; case SEGMENT_MIDDLE: case SEGMENT_END: if (tl->continueText()) { if (_text == 0) { _text = new Text(*tl->continueText()); _text->setFlag(ELEMENT_MOVABLE, false); _text->setParent(this); } } else { delete _text; _text = 0; } break; } if (_text) _text->layout(); QPointF pp1; QPointF pp2(pos2()); if (!_text && pp2.y() != 0) { setbbox(QRectF(pp1, pp2).normalized()); return; } qreal y1 = point(-textLine()->lineWidth()); qreal y2 = -y1; int sym = textLine()->beginSymbol(); if (_text) { qreal h = _text->height(); if (textLine()->beginTextPlace() == PLACE_ABOVE) y1 = -h; else if (textLine()->beginTextPlace() == PLACE_BELOW) y2 = h; else { y1 = -h * .5; y2 = h * .5; } } else if (sym != -1) { qreal hh = symbols[score()->symIdx()][sym].height(magS()) * .5; y1 = -hh; y2 = hh; } if (textLine()->endHook()) { qreal h = point(textLine()->endHookHeight()); if (h > y2) y2 = h; else if (h < y1) y1 = h; } if (textLine()->beginHook()) { qreal h = point(textLine()->beginHookHeight()); if (h > y2) y2 = h; else if (h < y1) y1 = h; } bbox().setRect(.0, y1, pp2.x(), y2 - y1); }
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(); }
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 Articulation::layout() { SymId sym = _up ? articulationList[articulationType()].upSym : articulationList[articulationType()].downSym; QRectF b(symBbox(sym)); setbbox(b.translated(-0.5 * b.width(), _up ? 0.0 : b.height())); }
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 Tremolo::layout() { qreal _spatium = spatium(); qreal w2 = _spatium * score()->styleS(ST_tremoloWidth).val() * .5; qreal h2 = _spatium * score()->styleS(ST_tremoloBoxHeight).val() * .5; qreal lw = _spatium * score()->styleS(ST_tremoloStrokeWidth).val(); qreal td = _spatium * score()->styleS(ST_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() == 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(); }