void NoteDot::layout() { setbbox(symBbox(SymId::augmentationDot)); }
void Arpeggio::draw(QPainter* p) const { qreal _spatium = spatium(); p->setPen(curColor()); qreal y1 = -_userLen1; qreal y2 = _height + _userLen2; p->setPen(QPen(curColor(), score()->styleS(ST_ArpeggioLineWidth).val() * _spatium, Qt::SolidLine, Qt::RoundCap)); switch (arpeggioType()) { case ArpeggioType::NORMAL: case ArpeggioType::UP: { QRectF r(symBbox(symbols)); p->rotate(-90.0); drawSymbols(symbols, p, QPointF(-r.right() - y1, -r.bottom() + r.height())); p->rotate(90.0); } break; case ArpeggioType::DOWN: { QRectF r(symBbox(symbols)); p->rotate(90.0); drawSymbols(symbols, p, QPointF(-r.left() + y1, -r.top() - r.height())); p->rotate(-90.0); } break; case ArpeggioType::UP_STRAIGHT: { QRectF r(symBbox(SymId::arrowheadBlackUp)); qreal x1 = _spatium * .5; drawSymbol(SymId::arrowheadBlackUp, p, QPointF(x1 - r.width() * .5, y1 - r.top())); y1 -= r.top() * .5; p->drawLine(QLineF(x1, y1, x1, y2)); } break; case ArpeggioType::DOWN_STRAIGHT: { QRectF r(symBbox(SymId::arrowheadBlackDown)); qreal x1 = _spatium * .5; drawSymbol(SymId::arrowheadBlackDown, p, QPointF(x1 - r.width() * .5, y2 - r.bottom())); y2 += r.top() * .5; p->drawLine(QLineF(x1, y1, x1, y2)); } break; case ArpeggioType::BRACKET: { 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)); } break; } }
void Articulation::layout() { SymId sym = _up ? articulationList[int(articulationType())].upSym : articulationList[int(articulationType())].downSym; QRectF b(symBbox(sym)); setbbox(b.translated(-0.5 * b.width(), 0.0)); }
void TimeSig::layout() { setPos(0.0, 0.0); qreal _spatium = spatium(); setbbox(QRectF()); // prepare for an empty time signature pointLargeLeftParen = QPointF(); pz = QPointF(); pn = QPointF(); pointLargeRightParen = QPointF(); qreal lineDist; int numOfLines; TimeSigType sigType = timeSigType(); Staff* _staff = staff(); if (_staff) { // if staff is without time sig, format as if no text at all if (!_staff->staffType(tick())->genTimesig() ) { // reset position and box sizes to 0 // qDebug("staff: no time sig"); pointLargeLeftParen.rx() = 0.0; pn.rx() = 0.0; pz.rx() = 0.0; pointLargeRightParen.rx() = 0.0; setbbox(QRectF()); // leave everything else as it is: // draw() will anyway skip any drawing if staff type has no time sigs return; } numOfLines = _staff->lines(tick()); lineDist = _staff->lineDistance(tick()); } else { // assume dimensions of a standard staff lineDist = 1.0; numOfLines = 5; } // if some symbol // compute vert. displacement to center in the staff height // determine middle staff position: qreal yoff = _spatium * (numOfLines-1) *.5 * lineDist; // C and Ccut are placed at the middle of the staff: use yoff directly if (sigType == TimeSigType::FOUR_FOUR) { pz = QPointF(0.0, yoff); setbbox(symBbox(SymId::timeSigCommon).translated(pz)); ns.clear(); ns.push_back(SymId::timeSigCommon); ds.clear(); } else if (sigType == TimeSigType::ALLA_BREVE) { pz = QPointF(0.0, yoff); setbbox(symBbox(SymId::timeSigCutCommon).translated(pz)); ns.clear(); ns.push_back(SymId::timeSigCutCommon); ds.clear(); } else { ns = toTimeSigString(_numeratorString.isEmpty() ? QString::number(_sig.numerator()) : _numeratorString); ds = toTimeSigString(_denominatorString.isEmpty() ? QString::number(_sig.denominator()) : _denominatorString); ScoreFont* font = score()->scoreFont(); QSizeF mag(magS() * _scale); QRectF numRect = font->bbox(ns, mag); QRectF denRect = font->bbox(ds, mag); // position numerator and denominator; vertical displacement: // number of lines is odd: 0.0 (strings are directly above and below the middle line) // number of lines even: 0.05 (strings are moved up/down to leave 1/10sp between them) qreal displ = (numOfLines & 1) ? 0.0 : (0.05 * _spatium); //align on the wider qreal pzY = yoff - (denRect.width() < 0.01 ? 0.0 : (displ + numRect.height() * .5)); qreal pnY = yoff + displ + denRect.height() * .5; if (numRect.width() >= denRect.width()) { // numerator: one space above centre line, unless denomin. is empty (if so, directly centre in the middle) pz = QPointF(0.0, pzY); // denominator: horiz: centred around centre of numerator | vert: one space below centre line pn = QPointF((numRect.width() - denRect.width())*.5, pnY); } else { // numerator: one space above centre line, unless denomin. is empty (if so, directly centre in the middle) pz = QPointF((denRect.width() - numRect.width())*.5, pzY); // denominator: horiz: centred around centre of numerator | vert: one space below centre line pn = QPointF(0.0, pnY); } // centering of parenthesis so the middle of the parenthesis is at the divisor marking level int centerY = yoff/2 + _spatium; int widestPortion = numRect.width() > denRect.width() ? numRect.width() : denRect.width(); pointLargeLeftParen = QPointF(-_spatium, centerY); pointLargeRightParen = QPointF(widestPortion + _spatium, centerY); setbbox(numRect.translated(pz)); // translate bounding boxes to actual string positions addbbox(denRect.translated(pn)); if (_largeParentheses) { addbbox(QRect(pointLargeLeftParen.x(), pointLargeLeftParen.y() - denRect.height(), _spatium / 2, numRect.height() + denRect.height())); addbbox(QRect(pointLargeRightParen.x(), pointLargeRightParen.y() - denRect.height(), _spatium / 2, numRect.height() + denRect.height())); } } }
qreal Rest::downPos() const { return symBbox(_sym).y() + symHeight(_sym); }
void TrillSegment::draw(QPainter* painter) const { QRectF b2(symBbox(SymId::wiggleTrill)); qreal w2 = symWidth(SymId::wiggleTrill); qreal x2 = pos2().x(); QColor color; if (flag(ELEMENT_DROP_TARGET)) color = MScore::dropColor; else if (selected() && !(score() && score()->printing())) color = MScore::selectColor[0]; else if (!visible()) color = Qt::gray; else { color = trill()->curColor(); } painter->setPen(color); if (spannerSegmentType() == SEGMENT_SINGLE || spannerSegmentType() == SEGMENT_BEGIN) { SymId sym = SymId::noSym; qreal x0 = 0.0, x1 = 0.0, y = 0.0; int n = 0; QRectF b1; switch(trill()->trillType()) { case Trill::TRILL_LINE: sym = SymId::ornamentTrill; b1 = symBbox(sym); x0 = -b1.x(); x1 = x0 + b1.width(); n = int(floor((x2-x1) / w2)); y = 0.0; break; #if 0 // TODO-smufl case Trill::UPPRALL_LINE: sym = SymId(upprallSym); b1 = score()->sym(sym).bbox(mag); x0 = -b1.x(); x1 = b1.width(); n = int(floor((x2-x1) / w2)); y = -b1.height(); break; case Trill::DOWNPRALL_LINE: sym = SymId(downprallSym); b1 = score()->sym(sym).bbox(mag); x0 = -b1.x(); x1 = b1.width(); n = int(floor((x2-x1) / w2)); y = -b1.height(); break; case Trill::PRALLPRALL_LINE: sym = SymId(prallprallSym); b1 = score()->sym(sym).bbox(mag); x0 = -b1.x(); x1 = b1.width(); n = int(floor((x2-x1) / w2)); y = -b1.height(); break; #endif case Trill::PURE_LINE: sym = SymId::noSym; x0 = 0; x1 = 0; n = int(floor((x2-x1) / w2)); y = 0.0; } if (n <= 0) n = 1; if (sym != SymId::noSym) drawSymbol(sym, painter, QPointF(x0, y)); drawSymbol(SymId::wiggleTrill, painter, QPointF(x1, b2.y() * .9), n); } else { qreal x1 = 0.0; int n = int(floor((x2-x1) / w2)); drawSymbol(SymId::wiggleTrill, painter, QPointF(x1, b2.y() * .9), n); } }
void Rest::layout() { _space.setLw(0.0); if (parent() && measure() && measure()->isMMRest()) { _space.setRw(point(score()->styleS(StyleIdx::minMMRestWidth))); static const qreal verticalLineWidth = .2; qreal _spatium = spatium(); qreal h = _spatium * (2 + verticalLineWidth); qreal w = _mmWidth + _spatium * verticalLineWidth*.5; bbox().setRect(-_spatium * verticalLineWidth*.5, -h * .5, w, h); // text qreal y = -_spatium * 2.5 - staff()->height() *.5; addbbox(QRectF(0, y, w, _spatium * 2)); // approximation return; } rxpos() = 0.0; if (staff() && staff()->isTabStaff()) { StaffType* tab = staff()->staffType(); // if rests are shown and note values are shown as duration symbols if (tab->showRests() && tab->genDurations()) { TDuration::DurationType type = durationType().type(); int dots = durationType().dots(); // if rest is whole measure, convert into actual type and dot values if (type == TDuration::DurationType::V_MEASURE) { int ticks = measure()->ticks(); TDuration dur = TDuration(Fraction::fromTicks(ticks)).type(); type = dur.type(); dots = dur.dots(); } // symbol needed; if not exist, create, if exists, update duration if (!_tabDur) _tabDur = new TabDurationSymbol(score(), tab, type, dots); else _tabDur->setDuration(type, dots, tab); _tabDur->setParent(this); // needed? _tabDur->setTrack(track()); _tabDur->layout(); setbbox(_tabDur->bbox()); setPos(0.0, 0.0); // no rest is drawn: reset any position might be set for it _space.setLw(0.0); _space.setRw(width()); return; } // if no rests or no duration symbols, delete any dur. symbol and chain into standard staff mngmt // this is to ensure horiz space is reserved for rest, even if they are not diplayed // Rest::draw() will skip their drawing, if not needed if(_tabDur) { delete _tabDur; _tabDur = 0; } } switch(durationType().type()) { case TDuration::DurationType::V_64TH: case TDuration::DurationType::V_32ND: dotline = -3; break; case TDuration::DurationType::V_1024TH: case TDuration::DurationType::V_512TH: case TDuration::DurationType::V_256TH: case TDuration::DurationType::V_128TH: dotline = -5; break; default: dotline = -1; break; } qreal _spatium = spatium(); int stepOffset = 0; if (staff()) stepOffset = staff()->staffType()->stepOffset(); int line = lrint(userOff().y() / _spatium); // + ((staff()->lines()-1) * 2); qreal lineDist = staff() ? staff()->staffType()->lineDistance().val() : 1.0; int lines = staff() ? staff()->lines() : 5; int lineOffset = computeLineOffset(); int yo; _sym = getSymbol(durationType().type(), line + lineOffset/2, lines, &yo); layoutArticulations(); rypos() = (qreal(yo) + qreal(lineOffset + stepOffset) * .5) * lineDist * _spatium; Spatium rs; if (dots()) { rs = Spatium(score()->styleS(StyleIdx::dotNoteDistance) + dots() * score()->styleS(StyleIdx::dotDotDistance)); } if (dots()) { rs = Spatium(score()->styleS(StyleIdx::dotNoteDistance) + dots() * score()->styleS(StyleIdx::dotDotDistance)); } setbbox(symBbox(_sym)); _space.setRw(width() + point(rs)); }
qreal Rest::upPos() const { return symBbox(_sym).y(); }
void Clef::layout() { // determine current number of lines and line distance int lines; qreal lineDist; Segment* clefSeg = segment(); int stepOffset; // check clef visibility and type compatibility if (clefSeg && staff()) { int tick = clefSeg->tick(); StaffType* staffType = staff()->staffType(tick); bool show = staffType->genClef(); // check staff type allows clef display // 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); } Measure* meas = clefSeg->measure(); if (meas && meas->system()) { auto ml = meas->system()->measures(); bool found = (std::find(ml.begin(), ml.end(), meas) != ml.end()); bool courtesy = (tick == meas->endTick() && (meas == meas->system()->lastMeasure() || !found)); if (courtesy && (!showCourtesy() || !score()->styleB(Sid::genCourtesyClef) || meas->isFinalMeasureOfSection())) show = false; } // 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(); stepOffset = staffType->stepOffset(); } else { lines = 5; lineDist = 1.0; stepOffset = 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(0.0, yoff * _spatium + (stepOffset * -_spatium)); setbbox(r); }
void Hook::layout() { ElementLayout::layout(this); setbbox(symBbox(_sym)); }
void Breath::layout() { setbbox(symBbox(symList[breathType()])); }
void Hook::layout() { setbbox(symBbox(_sym)); }
void KeySig::layout() { qreal _spatium = spatium(); setbbox(QRectF()); if (isCustom() && !isAtonal()) { for (KeySym& ks: _sig.keySymbols()) { ks.pos = ks.spos * _spatium; addbbox(symBbox(ks.sym).translated(ks.pos)); } return; } _sig.keySymbols().clear(); if (staff() && !staff()->genKeySig()) // no key sigs on TAB staves return; // determine current clef for this staff ClefType clef = ClefType::G; if (staff()) clef = staff()->clef(segment()->tick()); int accidentals = 0, naturals = 0; int t1 = int(_sig.key()); switch (qAbs(t1)) { case 7: accidentals = 0x7f; break; case 6: accidentals = 0x3f; break; case 5: accidentals = 0x1f; break; case 4: accidentals = 0xf; break; case 3: accidentals = 0x7; break; case 2: accidentals = 0x3; break; case 1: accidentals = 0x1; break; case 0: accidentals = 0; break; default: qDebug("illegal t1 key %d", t1); break; } // manage display of naturals: // naturals are shown if there is some natural AND prev. measure has no section break // AND style says they are not off // OR key sig is CMaj/Amin (in which case they are always shown) bool naturalsOn = false; Measure* prevMeasure = measure() ? measure()->prevMeasure() : 0; // If we're not force hiding naturals (Continuous panel), use score style settings if (!_hideNaturals) naturalsOn = (prevMeasure && !prevMeasure->sectionBreak() && (score()->styleI(StyleIdx::keySigNaturals) != int(KeySigNatural::NONE))) || (t1 == 0); // Don't repeat naturals if shown in courtesy if (prevMeasure && prevMeasure->findSegment(Segment::Type::KeySigAnnounce, segment()->tick()) && !segment()->isKeySigAnnounceType()) naturalsOn = false; if (track() == -1) naturalsOn = false; int coffset = 0; Key t2 = Key::C; if (naturalsOn) { t2 = staff()->key(segment()->tick() - 1); if (t2 == Key::C) naturalsOn = false; else { switch (qAbs(int(t2))) { case 7: naturals = 0x7f; break; case 6: naturals = 0x3f; break; case 5: naturals = 0x1f; break; case 4: naturals = 0xf; break; case 3: naturals = 0x7; break; case 2: naturals = 0x3; break; case 1: naturals = 0x1; break; case 0: naturals = 0; break; default: qDebug("illegal t2 key %d", int(t2)); break; } // remove redundant naturals if (!((t1 > 0) ^ (t2 > 0))) naturals &= ~accidentals; if (t2 < 0) coffset = 7; } } // naturals should go BEFORE accidentals if style says so // OR going from sharps to flats or vice versa (i.e. t1 & t2 have opposite signs) bool prefixNaturals = naturalsOn && (score()->styleI(StyleIdx::keySigNaturals) == int(KeySigNatural::BEFORE) || t1 * int(t2) < 0); // naturals should go AFTER accidentals if they should not go before! bool suffixNaturals = naturalsOn && !prefixNaturals; const signed char* lines = ClefInfo::lines(clef); // add prefixed naturals, if any qreal xo = 0.0; if (prefixNaturals) { for (int i = 0; i < 7; ++i) { if (naturals & (1 << i)) { addLayout(SymId::accidentalNatural, xo, lines[i + coffset]); xo += 1.0; } } } // add accidentals static const qreal sspread = 1.0; static const qreal fspread = 1.0; switch(t1) { case 7: addLayout(SymId::accidentalSharp, xo + 6.0 * sspread, lines[6]); case 6: addLayout(SymId::accidentalSharp, xo + 5.0 * sspread, lines[5]); case 5: addLayout(SymId::accidentalSharp, xo + 4.0 * sspread, lines[4]); case 4: addLayout(SymId::accidentalSharp, xo + 3.0 * sspread, lines[3]); case 3: addLayout(SymId::accidentalSharp, xo + 2.0 * sspread, lines[2]); case 2: addLayout(SymId::accidentalSharp, xo + 1.0 * sspread, lines[1]); case 1: addLayout(SymId::accidentalSharp, xo, lines[0]); break; case -7: addLayout(SymId::accidentalFlat, xo + 6.0 * fspread, lines[13]); case -6: addLayout(SymId::accidentalFlat, xo + 5.0 * fspread, lines[12]); case -5: addLayout(SymId::accidentalFlat, xo + 4.0 * fspread, lines[11]); case -4: addLayout(SymId::accidentalFlat, xo + 3.0 * fspread, lines[10]); case -3: addLayout(SymId::accidentalFlat, xo + 2.0 * fspread, lines[9]); case -2: addLayout(SymId::accidentalFlat, xo + 1.0 * fspread, lines[8]); case -1: addLayout(SymId::accidentalFlat, xo, lines[7]); case 0: break; default: qDebug("illegal t1 key %d", t1); break; } // add suffixed naturals, if any if (suffixNaturals) { xo += qAbs(t1); // skip accidentals if (t1 > 0) { // after sharps, add a little more space xo += 0.15; // if last sharp (t1) is above next natural (t1+1)... if (lines[t1] < lines[t1+1]) xo += 0.2; // ... add more space } for (int i = 0; i < 7; ++i) { if (naturals & (1 << i)) { addLayout(SymId::accidentalNatural, xo, lines[i + coffset]); xo += 1.0; } } } // compute bbox for (KeySym& ks : _sig.keySymbols()) { ks.pos = ks.spos * _spatium; addbbox(symBbox(ks.sym).translated(ks.pos)); } }