📄 notationhlayout.cpp
字号:
for (NotationGroupMap::iterator mi = m_groupsExtant.begin(); mi != m_groupsExtant.end(); ++mi) { mi->second->applyBeam(notationStaff); mi->second->applyTuplingLine(notationStaff); delete mi->second; } m_groupsExtant.clear(); bdi->second.layoutData.needsLayout = false; }}voidNotationHLayout::sampleGroupElement(Staff &staff, const Clef &clef, const ::Rosegarden::Key &key, const NotationElementList::iterator &itr){ NotationElement *el = static_cast<NotationElement *>(*itr); if (el->event()->has(BEAMED_GROUP_ID)) { //!!! Gosh. We need some clever logic to establish whether // one group is happening while another has not yet ended -- // perhaps we decide one has ended if we see another, and then // re-open the case of the first if we meet another note that // claims to be in it. Then we need to hint to both of the // groups that they should choose appropriate stem directions // -- we could just use HEIGHT_ON_STAFF of their first notes // to determine this, as if that doesn't work, nothing will long groupId = el->event()->get<Int>(BEAMED_GROUP_ID); NOTATION_DEBUG << "group id: " << groupId << endl; if (m_groupsExtant.find(groupId) == m_groupsExtant.end()) { NOTATION_DEBUG << "(new group)" << endl; m_groupsExtant[groupId] = new NotationGroup(*staff.getViewElementList(), m_notationQuantizer, m_properties, clef, key); } m_groupsExtant[groupId]->sample(itr, true); }}timeTNotationHLayout::getSpacingDuration(Staff &staff, const NotationElementList::iterator &i){ SegmentNotationHelper helper(staff.getSegment()); timeT t((*i)->getViewAbsoluteTime()); timeT d((*i)->getViewDuration()); NotationElementList::iterator j(i), e(staff.getViewElementList()->end()); while (j != e && ((*j)->getViewAbsoluteTime() == t || (*j)->getViewDuration() == 0)) { ++j; } if (j == e) return d; else return (*j)->getViewAbsoluteTime() - (*i)->getViewAbsoluteTime();}timeTNotationHLayout::getSpacingDuration(Staff &staff, const NotationChord &chord){ SegmentNotationHelper helper(staff.getSegment()); NotationElementList::iterator i = chord.getShortestElement(); timeT d((*i)->getViewDuration()); NotationElementList::iterator j(i), e(staff.getViewElementList()->end()); while (j != e && (chord.contains(j) || (*j)->getViewDuration() == 0)) ++j; if (j != e) { d = (*j)->getViewAbsoluteTime() - (*i)->getViewAbsoluteTime(); } return d;}voidNotationHLayout::positionChord(Staff &staff, NotationElementList::iterator &itr, const Clef &clef, const ::Rosegarden::Key &key, TieMap &tieMap, NotationElementList::iterator &to){ NotationChord chord(*staff.getViewElementList(), itr, m_notationQuantizer, m_properties, clef, key); double baseX, delta; (static_cast<NotationElement *>(*itr))->getLayoutAirspace(baseX, delta); bool barEndsInChord = false; NOTATION_DEBUG << "NotationHLayout::positionChord: x = " << baseX << endl; // #938545 (Broken notation: Duplicated note can float outside // stave) -- We need to iterate over all elements in the chord // range here, not just the ordered set of notes actually in the // chord. They all have the same x-coord, so there's no // particular complication here. for (NotationElementList::iterator citr = chord.getInitialElement(); citr != staff.getViewElementList()->end(); ++citr) { if (citr == to) barEndsInChord = true; // #704958 (multiple tuplet spanners created when entering // triplet chord) -- layout() updates the beamed group data // for non-notes, but we have to do it for notes so as to // ensure every note in the chord is accounted for sampleGroupElement(staff, clef, key, citr); NotationElement *elt = static_cast<NotationElement*>(*citr); double displacedX = 0.0; long dxRaw = 0; elt->event()->get<Int>(DISPLACED_X, dxRaw); displacedX = double(dxRaw * m_npf->getNoteBodyWidth()) / 1000.0; elt->setLayoutX(baseX + displacedX); elt->setLayoutAirspace(baseX, delta); NOTATION_DEBUG << "NotationHLayout::positionChord: assigned x to elt at " << elt->getViewAbsoluteTime() << endl; if (citr == chord.getFinalElement()) break; } // Check for any ties going back, and if so work out how long they // must have been and assign accordingly. for (NotationElementList::iterator citr = chord.getInitialElement(); citr != staff.getViewElementList()->end(); ++citr) { NotationElement *note = static_cast<NotationElement*>(*citr); if (!note->isNote()) { if (citr == chord.getFinalElement()) break; continue; } bool tiedForwards = false; bool tiedBack = false; note->event()->get<Bool>(TIED_FORWARD, tiedForwards); note->event()->get<Bool>(TIED_BACKWARD, tiedBack); if (!note->event()->has(PITCH)) continue; int pitch = note->event()->get<Int>(PITCH); if (tiedBack) { TieMap::iterator ti(tieMap.find(pitch)); if (ti != tieMap.end()) { NotationElementList::iterator otherItr(ti->second); if ((*otherItr)->getViewAbsoluteTime() + (*otherItr)->getViewDuration() == note->getViewAbsoluteTime()) { NOTATION_DEBUG << "Second note in tie at " << note->getViewAbsoluteTime() << ": found first note, it matches" << endl; (*otherItr)->event()->setMaybe<Int> (m_properties.TIE_LENGTH, (int)(baseX - (*otherItr)->getLayoutX())); } else { NOTATION_DEBUG << "Second note in tie at " << note->getViewAbsoluteTime() << ": found first note but it ends at " << ((*otherItr)->getViewAbsoluteTime() + (*otherItr)->getViewDuration()) << endl; tieMap.erase(pitch); } } } if (tiedForwards) { note->event()->setMaybe<Int>(m_properties.TIE_LENGTH, 0); tieMap[pitch] = citr; } else { note->event()->unset(m_properties.TIE_LENGTH); } if (citr == chord.getFinalElement()) break; } itr = chord.getFinalElement(); if (barEndsInChord) { to = itr; ++to; }}floatNotationHLayout::getLayoutWidth(ViewElement &ve, const ::Rosegarden::Key &previousKey) const{ NotationElement& e = static_cast<NotationElement&>(ve); if ((e.isNote() || e.isRest()) && e.event()->has(NOTE_TYPE)) { long noteType = e.event()->get<Int>(NOTE_TYPE); long dots = 0; (void)e.event()->get<Int>(NOTE_DOTS, dots); double bw = 0; if (e.isNote()) { bw = m_npf->getNoteBodyWidth(noteType) + m_npf->getDotWidth() * dots; } else { bw = m_npf->getRestWidth(Note(noteType, dots)); } double multiplier = double(Note(noteType, dots).getDuration()) / double(Note(Note::Quaver) .getDuration()); multiplier -= 1.0; multiplier *= m_proportion / 100.0; multiplier += 1.0; double gap = m_npf->getNoteBodyWidth(noteType) * multiplier; NOTATION_DEBUG << "note type " << noteType << ", isNote " << e.isNote() << ", dots " << dots << ", multiplier " << multiplier << ", gap " << gap << ", result " << (bw + gap * m_spacing / 100.0) << endl; gap = gap * m_spacing / 100.0; return bw + gap; } else { double w = getFixedItemSpacing(); if (e.event()->isa(Clef::EventType)) { w += m_npf->getClefWidth(Clef(*e.event())); } else if (e.event()->isa(::Rosegarden::Key::EventType)) { ::Rosegarden::Key key(*e.event()); ::Rosegarden::Key cancelKey = previousKey; if (m_keySigCancelMode == 0) { // only when entering C maj / A min if (key.getAccidentalCount() != 0) cancelKey = ::Rosegarden::Key(); } else if (m_keySigCancelMode == 1) { // only when reducing acc count if (!(key.isSharp() == cancelKey.isSharp() && key.getAccidentalCount() < cancelKey.getAccidentalCount())) { cancelKey = ::Rosegarden::Key(); } } w += m_npf->getKeyWidth(key, cancelKey); } else if (e.event()->isa(Indication::EventType) || e.event()->isa(Text::EventType)) { w = 0; } else { // NOTATION_DEBUG << "NotationHLayout::getLayoutWidth(): no case for event type " << e.event()->getType() << endl; // w += 24; w = 0; } return w; }}int NotationHLayout::getBarMargin() const{ return (int)(m_npf->getBarMargin() * m_spacing / 100.0);}int NotationHLayout::getPreBarMargin() const{ return getBarMargin() / 3;}int NotationHLayout::getPostBarMargin() const{ return getBarMargin() - getPreBarMargin();}int NotationHLayout::getFixedItemSpacing() const{ return (int)((m_npf->getNoteBodyWidth() * 2.0 / 3.0) * m_spacing / 100.0);}voidNotationHLayout::reset(){ for (BarDataMap::iterator i = m_barData.begin(); i != m_barData.end(); ++i) { clearBarList(*i->first); } m_barData.clear(); m_barPositions.clear(); m_totalWidth = 0;}voidNotationHLayout::resetStaff(Staff &staff, timeT startTime, timeT endTime){ if (startTime == endTime) { getBarData(staff).clear(); m_totalWidth = 0; }}intNotationHLayout::getFirstVisibleBar() const{ int bar = 0; bool haveBar = false; for (BarDataMap::const_iterator i = m_barData.begin(); i != m_barData.end(); ++i) { if (i->second.begin() == i->second.end()) continue; int barHere = i->second.begin()->first; if (barHere < bar || !haveBar) { bar = barHere; haveBar = true; } } // NOTATION_DEBUG << "NotationHLayout::getFirstVisibleBar: returning " << bar << endl; return bar;}intNotationHLayout::getFirstVisibleBarOnStaff(Staff &staff){ BarDataList &bdl(getBarData(staff)); int bar = 0; if (bdl.begin() != bdl.end()) bar = bdl.begin()->first; // NOTATION_DEBUG << "NotationHLayout::getFirstVisibleBarOnStaff: returning " << bar << endl; return bar;}intNotationHLayout::getLastVisibleBar() const{ int bar = 0; bool haveBar = false; for (BarDataMap::const_iterator i = m_barData.begin(); i != m_barData.end(); ++i) { if (i->second.begin() == i->second.end()) continue; int barHere = getLastVisibleBarOnStaff(*i->first); if (barHere > bar || !haveBar) { bar = barHere; haveBar = true; } } // NOTATION_DEBUG << "NotationHLayout::getLastVisibleBar: returning " << bar << endl; return bar;}intNotationHLayout::getLastVisibleBarOnStaff(Staff &staff) const{ const Ba
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -