void BarLine::layout() { qreal y1, y2; getY(&y1, &y2); qreal _spatium = spatium(); qreal dw = layoutWidth(score(), barLineType(), magS()); QRectF r(0.0, y1, dw, y2-y1); if (score()->styleB(ST_repeatBarTips)) { qreal mags = magS(); int si = score()->symIdx(); switch (barLineType()) { case START_REPEAT: r |= symbols[si][brackettipsRightUp].bbox(mags).translated(0, y1); r |= symbols[si][brackettipsRightDown].bbox(mags).translated(0, y2); break; case END_REPEAT: r |= symbols[si][brackettipsLeftUp].bbox(mags).translated(0, y1); r |= symbols[si][brackettipsLeftDown].bbox(mags).translated(0, y2); break; case END_START_REPEAT: { qreal lw = point(score()->styleS(ST_barWidth)); qreal lw2 = point(score()->styleS(ST_endBarWidth)); qreal d1 = point(score()->styleS(ST_endBarDistance)); const Sym& dotsym = symbols[score()->symIdx()][dotSym]; qreal dotw = dotsym.width(mags); qreal x = dotw + 2 * d1 + lw + lw2 * .5; // thick bar r |= symbols[si][brackettipsRightUp].bbox(mags).translated(x, y1); r |= symbols[si][brackettipsRightDown].bbox(mags).translated(x, y2); r |= symbols[si][brackettipsLeftUp].bbox(mags).translated(x, y1); r |= symbols[si][brackettipsLeftDown].bbox(mags).translated(x, y2); } break; default: break; } } foreach(Element* e, _el) { e->layout(); if (e->type() == ARTICULATION) { Articulation* a = static_cast<Articulation*>(e); MScore::Direction dir = a->direction(); qreal distance = 0.5 * _spatium; qreal x = width() * .5; if (dir == MScore::DOWN) { qreal botY = y2 + distance; a->setPos(QPointF(x, botY)); } else { qreal topY = y1 - distance; a->setPos(QPointF(x, topY)); } } }
void ChordRest::layoutArticulations() { if (parent() == 0 || _articulations.isEmpty()) return; qreal _spatium = spatium(); qreal _spStaff = _spatium * staff()->lineDistance(); // scaled to staff line distance for vert. pos. within a staff if (type() == Element::Type::CHORD) { if (_articulations.size() == 1) { static_cast<Chord*>(this)->layoutArticulation(_articulations[0]); return; } if (_articulations.size() == 2) { // // staccato | tenuto + marcato // Articulation* a1 = _articulations[0]; Articulation* a2 = _articulations[1]; ArticulationType st1 = a1->articulationType(); ArticulationType st2 = a2->articulationType(); if ((st2 == ArticulationType::Tenuto || st2 == ArticulationType::Staccato) && (st1 == ArticulationType::Marcato)) { qSwap(a1, a2); qSwap(st1, st2); } if ((st1 == ArticulationType::Tenuto || st1 == ArticulationType::Staccato) && (st2 == ArticulationType::Marcato)) { QPointF pt = static_cast<Chord*>(this)->layoutArticulation(a1); pt.ry() += a1->up() ? -_spStaff * .5 : _spStaff * .5; a2->layout(); a2->setUp(a1->up()); a2->setPos(pt); a2->adjustReadPos(); return; } // // staccato | tenuto + sforzato // if ((st2 == ArticulationType::Tenuto || st2 == ArticulationType::Staccato) && (st1 == ArticulationType::Sforzatoaccent)) { qSwap(a1, a2); qSwap(st1, st2); } if ((st1 == ArticulationType::Tenuto || st1 == ArticulationType::Staccato) && (st2 == ArticulationType::Sforzatoaccent)) { QPointF pt = static_cast<Chord*>(this)->layoutArticulation(a1); pt.ry() += a1->up() ? -_spStaff * .7 : _spStaff * .7; a2->layout(); a2->setUp(a1->up()); a2->setPos(pt); a2->adjustReadPos(); return; } } } qreal x = centerX(); qreal distance0 = score()->styleS(StyleIdx::propertyDistance).val() * _spatium; qreal distance1 = score()->styleS(StyleIdx::propertyDistanceHead).val() * _spatium; qreal distance2 = score()->styleS(StyleIdx::propertyDistanceStem).val() * _spatium; qreal chordTopY = upPos(); // note position of highest note qreal chordBotY = downPos(); // note position of lowest note qreal staffTopY = -distance2; qreal staffBotY = staff()->height() + distance2; // avoid collisions of staff articulations with chord notes: // gap between note and staff articulation is distance0 + 0.5 spatium if (type() == Element::Type::CHORD) { Chord* chord = static_cast<Chord*>(this); Stem* stem = chord->stem(); if (stem) { qreal y = stem->pos().y() + pos().y(); if (up() && stem->stemLen() < 0.0) y += stem->stemLen(); else if (!up() && stem->stemLen() > 0.0) y -= stem->stemLen(); if (beam()) { qreal bw = score()->styleS(StyleIdx::beamWidth).val() * _spatium; y += up() ? -bw : bw; } if (up()) staffTopY = qMin(staffTopY, qreal(y - 0.5 * _spatium)); else staffBotY = qMax(staffBotY, qreal(y + 0.5 * _spatium)); } } staffTopY = qMin(staffTopY, qreal(chordTopY - distance0 - 0.5 * _spatium)); staffBotY = qMax(staffBotY, qreal(chordBotY + distance0 + 0.5 * _spatium)); qreal dy = 0.0; int n = _articulations.size(); for (int i = 0; i < n; ++i) { Articulation* a = _articulations.at(i); // // determine MScore::Direction // if (a->direction() != MScore::Direction::AUTO) { a->setUp(a->direction() == MScore::Direction::UP); } else { if (a->anchor() == ArticulationAnchor::CHORD) a->setUp(!up()); else a->setUp(a->anchor() == ArticulationAnchor::TOP_STAFF || a->anchor() == ArticulationAnchor::TOP_CHORD); } } // // pass 1 // place tenuto and staccato // for (int i = 0; i < n; ++i) { Articulation* a = _articulations.at(i); a->layout(); ArticulationAnchor aa = a->anchor(); if ((a->articulationType() != ArticulationType::Tenuto) && (a->articulationType() != ArticulationType::Staccato)) continue; if (aa != ArticulationAnchor::CHORD && aa != ArticulationAnchor::TOP_CHORD && aa != ArticulationAnchor::BOTTOM_CHORD) continue; bool bottom; if ((aa == ArticulationAnchor::CHORD) && measure()->hasVoices(a->staffIdx())) bottom = !up(); else bottom = (aa == ArticulationAnchor::BOTTOM_CHORD) || (aa == ArticulationAnchor::CHORD && up()); bool headSide = bottom == up(); dy += distance1; qreal y; Chord* chord = static_cast<Chord*>(this); if (bottom) { int line = downLine(); y = chordBotY + dy; if (!headSide && type() == Element::Type::CHORD && chord->stem()) { Stem* stem = chord->stem(); y = chordTopY + stem->stemLen(); if (chord->beam()) y += score()->styleS(StyleIdx::beamWidth).val() * _spatium * .5; x = stem->pos().x(); int line = lrint((y+0.5*_spatium) / _spatium); if (line <= 4) // align between staff lines y = line * _spatium + _spatium * .5; else y += _spatium; } else { int lines = (staff()->lines() - 1) * 2; if (line < lines) y = (line & ~1) + 3; else y = line + 2; y *= _spatium * .5; } } else { int line = upLine(); y = chordTopY - dy; if (!headSide && type() == Element::Type::CHORD && chord->stem()) { Stem* stem = chord->stem(); y = chordBotY + stem->stemLen(); if (chord->beam()) y -= score()->styleS(StyleIdx::beamWidth).val() * _spatium * .5; x = stem->pos().x(); int line = lrint((y-0.5*_spatium) / _spatium); if (line >= 0) // align between staff lines y = line * _spatium - _spatium * .5; else y -= _spatium; } else { if (line > 0) y = ((line+1) & ~1) - 3; else y = line - 2; y *= _spatium * .5; } } dy += _spatium * .5; a->setPos(x, y); } // reserve space for slur bool botGap = false; bool topGap = false; #if 0 // TODO-S: optimize for (Spanner* sp = _spannerFor; sp; sp = sp->next()) { if (sp->type() != SLUR) continue; Slur* s = static_cast<Slur*>(sp); if (s->up()) topGap = true; else botGap = true; } for (Spanner* sp = _spannerBack; sp; sp = sp->next()) { if (sp->type() != SLUR) continue; Slur* s = static_cast<Slur*>(sp); if (s->up()) topGap = true; else botGap = true; } #endif if (botGap) chordBotY += _spatium; if (topGap) chordTopY -= _spatium; // // pass 2 // place all articulations with anchor at chord/rest // n = _articulations.size(); for (int i = 0; i < n; ++i) { Articulation* a = _articulations.at(i); a->layout(); ArticulationAnchor aa = a->anchor(); if ((a->articulationType() == ArticulationType::Tenuto) || (a->articulationType() == ArticulationType::Staccato)) continue; if (aa != ArticulationAnchor::CHORD && aa != ArticulationAnchor::TOP_CHORD && aa != ArticulationAnchor::BOTTOM_CHORD) continue; // for tenuto and staccate check for staff line collision bool staffLineCT = a->articulationType() == ArticulationType::Tenuto || a->articulationType() == ArticulationType::Staccato; // qreal sh = a->bbox().height() * mag(); bool bottom = (aa == ArticulationAnchor::BOTTOM_CHORD) || (aa == ArticulationAnchor::CHORD && up()); dy += distance1; if (bottom) { qreal y = chordBotY + dy; if (staffLineCT && (y <= staffBotY -.1 - dy)) { qreal l = y / _spatium; qreal delta = fabs(l - round(l)); if (delta < 0.4) { y += _spatium * .5; dy += _spatium * .5; } } a->setPos(x, y); // - a->bbox().y() + a->bbox().height() * .5); } else { qreal y = chordTopY - dy; if (staffLineCT && (y >= (staffTopY +.1 + dy))) { qreal l = y / _spatium; qreal delta = fabs(l - round(l)); if (delta < 0.4) { y -= _spatium * .5; dy += _spatium * .5; } } a->setPos(x, y); // + a->bbox().y() - a->bbox().height() * .5); } } // // pass 3 // now place all articulations with staff top or bottom anchor // qreal dyTop = staffTopY; qreal dyBot = staffBotY; /* if ((upPos() - _spatium) < dyTop) dyTop = upPos() - _spatium; if ((downPos() + _spatium) > dyBot) dyBot = downPos() + _spatium; */ for (int i = 0; i < n; ++i) { Articulation* a = _articulations.at(i); ArticulationAnchor aa = a->anchor(); if (aa == ArticulationAnchor::TOP_STAFF || aa == ArticulationAnchor::BOTTOM_STAFF) { if (a->up()) { a->setPos(x, dyTop); dyTop -= distance0; } else { a->setPos(x, dyBot); dyBot += distance0; } } a->adjustReadPos(); } }
void BarLine::layout() { qreal y1, y2; getY(&y1, &y2); // if bar line does not belong to a system, has a staff and staff is set to hide bar lines, set null bbox if (parent() && parent()->type() != Element::Type::SYSTEM && staff() && !staff()->staffType()->showBarlines()) setbbox(QRectF()); // bar lines not hidden else { qreal dw = layoutWidth(score(), barLineType(), magS()); QRectF r(0.0, y1, dw, y2-y1); if (score()->styleB(StyleIdx::repeatBarTips)) { switch (barLineType()) { case BarLineType::START_REPEAT: r |= symBbox(SymId::bracketTop).translated(0, y1); r |= symBbox(SymId::bracketBottom).translated(0, y2); break; case BarLineType::END_REPEAT: { qreal w1 = symBbox(SymId::reversedBracketTop).width(); r |= symBbox(SymId::reversedBracketTop).translated(dw - w1, y1); r |= symBbox(SymId::reversedBracketBottom).translated(dw - w1, y2); break; } case BarLineType::END_START_REPEAT: { qreal lw = point(score()->styleS(StyleIdx::barWidth)); qreal lw2 = point(score()->styleS(StyleIdx::endBarWidth)); qreal d1 = point(score()->styleS(StyleIdx::endBarDistance)); qreal dotw = symWidth(SymId::repeatDot); qreal x = dotw + 2 * d1 + lw + lw2 * .5; // thick bar qreal w1 = symBbox(SymId::reversedBracketTop).width(); r |= symBbox(SymId::bracketTop).translated(x, y1); r |= symBbox(SymId::bracketBottom).translated(x, y2); r |= symBbox(SymId::reversedBracketTop).translated(x - w1 , y1); r |= symBbox(SymId::reversedBracketBottom).translated(x - w1, y2); } break; default: break; } } setbbox(r); } // in any case, lay out attached elements foreach(Element* e, _el) { e->layout(); if (e->type() == Element::Type::ARTICULATION) { Articulation* a = static_cast<Articulation*>(e); MScore::Direction dir = a->direction(); qreal distance = 0.5 * spatium(); qreal x = width() * .5; if (dir == MScore::Direction::DOWN) { qreal botY = y2 + distance; a->setPos(QPointF(x, botY)); } else { qreal topY = y1 - distance; a->setPos(QPointF(x, topY)); } } }
void BarLine::layout() { qreal y1, y2; getY(&y1, &y2); qreal _spatium = spatium(); qreal dw = score()->styleS(ST_barWidth).val() * _spatium; qreal dotwidth = symbols[score()->symIdx()][dotSym].width(magS()); switch(subtype()) { case DOUBLE_BAR: dw = (score()->styleS(ST_doubleBarWidth) * 2 + score()->styleS(ST_doubleBarDistance)).val() * _spatium; break; case START_REPEAT: dw += dotwidth + (score()->styleS(ST_endBarWidth) + 2 * score()->styleS(ST_endBarDistance)).val() * _spatium; break; case END_REPEAT: dw += dotwidth + (score()->styleS(ST_endBarWidth) + 2 * score()->styleS(ST_endBarDistance)).val() * _spatium; break; case END_BAR: dw += (score()->styleS(ST_endBarWidth) + score()->styleS(ST_endBarDistance)).val() * _spatium; break; case END_START_REPEAT: dw += 2 * dotwidth + (score()->styleS(ST_barWidth) + score()->styleS(ST_endBarWidth) + 4 * score()->styleS(ST_endBarDistance)).val() * _spatium; break; case BROKEN_BAR: case NORMAL_BAR: break; default: qDebug("illegal bar line type\n"); break; } QRectF r(0.0, y1, dw, y2-y1); if (score()->styleB(ST_repeatBarTips)) { // qreal mags = magS(); switch (subtype()) { case START_REPEAT: //r |= symbols[brackettipsRightUp].bbox(mags).translated(0, y1); //r |= symbols[brackettipsRightDown].bbox(mags).translated(0, y2); break; case END_REPEAT: //r |= symbols[brackettipsLeftUp].bbox(mags).translated(0, y1); //r |= symbols[brackettipsLeftDown].bbox(mags).translated(0, y2); break; default: break; } } foreach(Element* e, _el) { e->layout(); if (e->type() == ARTICULATION) { Articulation* a = static_cast<Articulation*>(e); ArticulationAnchor aa = a->anchor(); qreal distance = 0.5 * _spatium; qreal topY = y1 - distance; qreal botY = y2 + distance; qreal x = width() - (a->width() * .5); if (aa == A_TOP_STAFF) a->setPos(QPointF(x, topY)); else if (aa == A_BOTTOM_STAFF) a->setPos(QPointF(x, botY)); } }