📄 notationhlayout.cpp
字号:
// the only text events of interest are lyrics, which // contribute to a fixed area following the next chord if (el->event()->has(Text::TextTypePropertyName) && el->event()->get<String>(Text::TextTypePropertyName) == Text::Lyric) { lyricWidth = std::max (lyricWidth, float(m_npf->getTextWidth(Text(*el->event())))); NOTATION_DEBUG << "Setting lyric width to " << lyricWidth << " for text " << el->event()->get<String>(Text::TextPropertyName) << endl; } chunks.push_back(Chunk(el->event()->getSubOrdering(), 0)); } else if (el->isNote()) { scanChord(notes, itr, clef, key, accTable, lyricWidth, chunks, graceCount, ottavaShift, to); } else if (el->isRest()) { chunks.push_back(Chunk(el->getViewDuration(), el->event()->getSubOrdering(), 0, getLayoutWidth(*el, key))); } else if (el->event()->isa(Indication::EventType)) { // NOTATION_DEBUG << "Found indication" << endl; chunks.push_back(Chunk(el->event()->getSubOrdering(), 0)); try { Indication indication(*el->event()); if (indication.isOttavaType()) { ottavaShift = indication.getOttavaShift(); ottavaEnd = el->event()->getAbsoluteTime() + indication.getIndicationDuration(); m_haveOttavaSomewhere[&staff] = true; } } catch (...) { NOTATION_DEBUG << "Bad indication!" << endl; } } else {// NOTATION_DEBUG << "Found something I don't know about (type is " << el->event()->getType() << ")" << endl; chunks.push_back(Chunk(el->event()->getSubOrdering(), getLayoutWidth(*el, key))); } actualBarEnd = el->getViewAbsoluteTime() + el->getViewDuration(); } if (actualBarEnd == barTimes.first) actualBarEnd = barTimes.second; barCorrect = (actualBarEnd == barTimes.second); setBarSizeData(staff, barNo, fixedWidth, actualBarEnd - barTimes.first); if ((endTime > startTime) && (barNo % 20 == 0)) { emit setProgress((barTimes.second - startTime) * 95 / (endTime - startTime)); ProgressDialog::processEvents(); } throwIfCancelled(); } /* BarDataList::iterator ei(barList.end()); while (ei != barList.begin() && (--ei)->first > endBarNo) { barList.erase(ei); ei = barList.end(); } */}voidNotationHLayout::clearBarList(Staff &staff){ BarDataList &bdl = m_barData[&staff]; bdl.clear();}voidNotationHLayout::setBarBasicData(Staff &staff, int barNo, NotationElementList::iterator start, bool correct, TimeSignature timeSig, bool newTimeSig){ // NOTATION_DEBUG << "setBarBasicData for " << barNo << endl; BarDataList &bdl(m_barData[&staff]); BarDataList::iterator i(bdl.find(barNo)); if (i == bdl.end()) { NotationElementList::iterator endi = staff.getViewElementList()->end(); bdl.insert(BarDataPair(barNo, BarData(endi, true, TimeSignature(), false))); i = bdl.find(barNo); } i->second.basicData.start = start; i->second.basicData.correct = correct; i->second.basicData.timeSignature = timeSig; i->second.basicData.newTimeSig = newTimeSig;}voidNotationHLayout::setBarSizeData(Staff &staff, int barNo, float fixedWidth, timeT actualDuration){ // NOTATION_DEBUG << "setBarSizeData for " << barNo << endl; BarDataList &bdl(m_barData[&staff]); BarDataList::iterator i(bdl.find(barNo)); if (i == bdl.end()) { NotationElementList::iterator endi = staff.getViewElementList()->end(); bdl.insert(BarDataPair(barNo, BarData(endi, true, TimeSignature(), false))); i = bdl.find(barNo); } i->second.sizeData.actualDuration = actualDuration; i->second.sizeData.idealWidth = 0.0; i->second.sizeData.reconciledWidth = 0.0; i->second.sizeData.clefKeyWidth = 0; i->second.sizeData.fixedWidth = fixedWidth;}voidNotationHLayout::scanChord(NotationElementList *notes, NotationElementList::iterator &itr, const Clef &clef, const ::Rosegarden::Key &key, AccidentalTable &accTable, float &lyricWidth, ChunkList &chunks, int &graceCount, int ottavaShift, NotationElementList::iterator &to){ NotationChord chord(*notes, itr, m_notationQuantizer, m_properties); Accidental someAccidental = Accidentals::NoAccidental; bool someCautionary = false; bool barEndsInChord = false; bool grace = false; /* NOTATION_DEBUG << "NotationHLayout::scanChord: " << chord.size() << "-voice chord at " << (*itr)->event()->getAbsoluteTime() << " unquantized, " << (*itr)->getViewAbsoluteTime() << " quantized" << endl; NOTATION_DEBUG << "Contents:" << endl; for (NotationElementList::iterator i = chord.getInitialElement(); i != notes->end(); ++i) { (*i)->event()->dump(std::cerr); if (i == chord.getFinalElement()) break; } */ // We don't need to get the chord's notes in pitch order here, // but we do need to ensure we see any random non-note events // that may crop up in the middle of it. for (NotationElementList::iterator i = chord.getInitialElement(); i != notes->end(); ++i) { NotationElement *el = static_cast<NotationElement*>(*i); if (el->isRest()) { el->event()->setMaybe<Bool>(m_properties.REST_TOO_SHORT, true); if (i == chord.getFinalElement()) break; continue; } if (el->isGrace()) grace = true; long pitch = 64; if (!el->event()->get<Int>(PITCH, pitch)) { NOTATION_DEBUG << "WARNING: NotationHLayout::scanChord: couldn't get pitch for element, using default pitch of " << pitch << endl; } Accidental explicitAccidental = Accidentals::NoAccidental; (void)el->event()->get<String>(ACCIDENTAL, explicitAccidental); Pitch p(pitch, explicitAccidental); int h = p.getHeightOnStaff(clef, key); Accidental acc = p.getDisplayAccidental(key); h -= 7 * ottavaShift; el->event()->setMaybe<Int>(NotationProperties::OTTAVA_SHIFT, ottavaShift); el->event()->setMaybe<Int>(NotationProperties::HEIGHT_ON_STAFF, h); el->event()->setMaybe<String>(m_properties.CALCULATED_ACCIDENTAL, acc); // update display acc for note according to the accTable // (accidentals in force when the last chord ended) and tell // accTable about accidentals from this note. bool cautionary = false; if (el->event()->has(m_properties.USE_CAUTIONARY_ACCIDENTAL)) { cautionary = el->event()->get<Bool>(m_properties.USE_CAUTIONARY_ACCIDENTAL); } Accidental dacc = accTable.processDisplayAccidental(acc, h, cautionary); el->event()->setMaybe<String>(m_properties.DISPLAY_ACCIDENTAL, dacc); el->event()->setMaybe<Bool>(m_properties.DISPLAY_ACCIDENTAL_IS_CAUTIONARY, cautionary); if (cautionary) { someCautionary = true; } if (someAccidental == Accidentals::NoAccidental) someAccidental = dacc; if (i == to) barEndsInChord = true; if (i == chord.getFinalElement()) break; } // tell accTable the chord has ended, so to bring its accidentals // into force for future chords accTable.update(); chord.applyAccidentalShiftProperties(); float extraWidth = 0; if (someAccidental != Accidentals::NoAccidental) { bool extraShift = false; int shift = chord.getMaxAccidentalShift(extraShift); int e = m_npf->getAccidentalWidth(someAccidental, shift, extraShift); if (someAccidental != Accidentals::Sharp) { e = std::max(e, m_npf->getAccidentalWidth(Accidentals::Sharp, shift, extraShift)); } if (someCautionary) { e += m_npf->getNoteBodyWidth(); } extraWidth += e; } float layoutExtra = 0; if (chord.hasNoteHeadShifted()) { if (chord.hasStemUp()) { layoutExtra += m_npf->getNoteBodyWidth(); } else { extraWidth = std::max(extraWidth, float(m_npf->getNoteBodyWidth())); } } if (grace) { chunks.push_back(Chunk( -10 + graceCount, extraWidth + m_npf->getNoteBodyWidth())); if (graceCount < 9) ++graceCount; return ; } else { graceCount = 0; } NotationElementList::iterator myLongest = chord.getLongestElement(); if (myLongest == notes->end()) { NOTATION_DEBUG << "WARNING: NotationHLayout::scanChord: No longest element in chord!" << endl; } timeT d = (*myLongest)->getViewDuration(); NOTATION_DEBUG << "Lyric width is " << lyricWidth << endl; chunks.push_back(Chunk(d, 0, extraWidth, std::max(layoutExtra + getLayoutWidth(**myLongest, key), lyricWidth))); lyricWidth = 0; itr = chord.getFinalElement(); if (barEndsInChord) { to = itr; ++to; } return ;}struct ChunkLocation { timeT time; short subordering; ChunkLocation(timeT t, short s) : time(t), subordering(s) { }};bool operator<(const ChunkLocation &l0, const ChunkLocation &l1) { return ((l0.time < l1.time) || ((l0.time == l1.time) && (l0.subordering < l1.subordering)));}voidNotationHLayout::preSquishBar(int barNo){ typedef std::vector<Chunk *> ChunkRefList; typedef std::map<ChunkLocation, ChunkRefList> ColumnMap; static ColumnMap columns; bool haveSomething = false; columns.clear(); for (BarDataMap::iterator mi = m_barData.begin(); mi != m_barData.end(); ++mi) { BarDataList &bdl = mi->second; BarDataList::iterator bdli = bdl.find(barNo); if (bdli != bdl.end()) { haveSomething = true; ChunkList &cl(bdli->second.chunks); timeT aggregateTime = 0; for (ChunkList::iterator cli = cl.begin(); cli != cl.end(); ++cli) { // Subordering is typically zero for notes, positive // for rests and negative for other stuff. We want to // handle notes and rests together, but not the others. int subordering = cli->subordering; if (subordering > 0) subordering = 0; columns[ChunkLocation(aggregateTime, subordering)].push_back(&(*cli)); aggregateTime += cli->duration; } } } if (!haveSomething) return ; // now modify chunks in-place // What we want to do here is idle along the whole set of chunk // lists, inspecting all the chunks that occur at each moment in // turn and choosing a "rate" from the "slowest" of these // (i.e. most space per time) float x = 0.0; timeT prevTime = 0; double prevRate = 0.0; float maxStretchy = 0.0; NOTATION_DEBUG << "NotationHLayout::preSquishBar(" << barNo << "): have " << columns.size() << " columns" << endl; for (ColumnMap::iterator i = columns.begin(); i != columns.end(); ++i) { timeT time = i->first.time; ChunkRefList &list = i->second; NOTATION_DEBUG << "NotationHLayout::preSquishBar: " << "column at " << time << " : " << i->first.subordering << endl; double minRate = -1.0; float totalFixed = 0.0; maxStretchy = 0.0; for (ChunkRefList::iterator j = list.begin(); j != list.end(); ++j) { if ((*j)->stretchy > 0.0) { double rate = (*j)->duration / (*j)->stretchy; // time per px
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -