📄 notationvlayout.cpp
字号:
el->setLayoutY(staff.getLayoutYForHeight(12)); } else if (el->event()->isa(Text::EventType)) { std::string type = Text::UnspecifiedType; el->event()->get<String>(Text::TextTypePropertyName, type); if (type == Text::Dynamic || type == Text::LocalDirection || type == Text::UnspecifiedType) { el->setLayoutY(staff.getLayoutYForHeight(-7) + displacedY); } else if (type == Text::Lyric) { long verse = 0; el->event()->get<Int>(Text::LyricVersePropertyName, verse); el->setLayoutY(staff.getLayoutYForHeight(-10 - 3 * verse) + displacedY); } else if (type == Text::Annotation) { el->setLayoutY(staff.getLayoutYForHeight(-13) + displacedY); } else { el->setLayoutY(staff.getLayoutYForHeight(22) + displacedY); } } else if (el->event()->isa(Indication::EventType)) { try { std::string indicationType = el->event()->get <String>(Indication::IndicationTypePropertyName); if (indicationType == Indication::Slur || indicationType == Indication::PhrasingSlur) { getSlurList(staff).push_back(i); } if (indicationType == Indication::OttavaUp || indicationType == Indication::QuindicesimaUp) { el->setLayoutY(staff.getLayoutYForHeight(15) + displacedY); } else { el->setLayoutY(staff.getLayoutYForHeight( -9) + displacedY); } } catch (...) { el->setLayoutY(staff.getLayoutYForHeight( -9) + displacedY); } } else if (el->event()->isa(Guitar::Chord::EventType)) { el->setLayoutY(staff.getLayoutYForHeight(22) + displacedY); } } } PRINT_ELAPSED("NotationVLayout::scanStaff");}voidNotationVLayout::finishLayout(timeT, timeT){ START_TIMING; for (SlurListMap::iterator mi = m_slurs.begin(); mi != m_slurs.end(); ++mi) { for (SlurList::iterator si = mi->second.begin(); si != mi->second.end(); ++si) { NotationElementList::iterator i = *si; NotationStaff &staff = dynamic_cast<NotationStaff &>(*(mi->first)); positionSlur(staff, i); } } PRINT_ELAPSED("NotationVLayout::finishLayout");}voidNotationVLayout::positionSlur(NotationStaff &staff, NotationElementList::iterator i){ bool phrasing = ((*i)->event()->get <String>(Indication::IndicationTypePropertyName) == Indication::PhrasingSlur); NotationElementList::iterator scooter = i; timeT slurDuration = (*i)->event()->getDuration(); if (slurDuration == 0 && (*i)->event()->has("indicationduration")) { slurDuration = (*i)->event()->get <Int>("indicationduration"); // obs property } timeT endTime = (*i)->getViewAbsoluteTime() + slurDuration; bool haveStart = false; int startTopHeight = 4, endTopHeight = 4, startBottomHeight = 4, endBottomHeight = 4, maxTopHeight = 4, minBottomHeight = 4, maxCount = 0, minCount = 0; int startX = (int)(*i)->getLayoutX(), endX = startX + 10; bool startStemUp = false, endStemUp = false; long startMarks = 0, endMarks = 0; bool startTied = false, endTied = false; bool beamAbove = false, beamBelow = false; bool dynamic = false; std::vector<Event *> stemUpNotes, stemDownNotes; // Scan the notes spanned by the slur, recording the top and // bottom heights of the first and last chords, plus the presence // of any troublesome beams and high or low notes in the body. while (scooter != staff.getViewElementList()->end()) { if ((*scooter)->getViewAbsoluteTime() >= endTime) break; Event *event = (*scooter)->event(); if (event->isa(Note::EventType)) { long h = 0; if (!event->get <Int>(m_properties.HEIGHT_ON_STAFF, h)) { KMessageBox::sorry ((QWidget *)parent(), i18n("Spanned note at %1 has no HEIGHT_ON_STAFF property!\nThis is a bug (the program would previously have crashed by now)").arg((*scooter)->getViewAbsoluteTime())); event->dump(std::cerr); } bool stemUp = (h <= 4); event->get <Bool>(m_properties.VIEW_LOCAL_STEM_UP, stemUp); bool beamed = false; event->get <Bool>(m_properties.BEAMED, beamed); bool primary = false; if (event->get <Bool> (m_properties.CHORD_PRIMARY_NOTE, primary) && primary) { NotationChord chord(*(staff.getViewElementList()), scooter, m_notationQuantizer, m_properties); if (beamed) { if (stemUp) beamAbove = true; else beamBelow = true; } if (!haveStart) { startBottomHeight = chord.getLowestNoteHeight(); startTopHeight = chord.getHighestNoteHeight(); minBottomHeight = startBottomHeight; maxTopHeight = startTopHeight; startX = (int)(*scooter)->getLayoutX(); startStemUp = stemUp; startMarks = chord.getMarkCountForChord(); bool tied = false; if ((event->get <Bool>(TIED_FORWARD, tied) && tied) || (event->get<Bool>(TIED_BACKWARD, tied) && tied)) { startTied = true; } haveStart = true; } else { if (chord.getLowestNoteHeight() < minBottomHeight) { minBottomHeight = chord.getLowestNoteHeight(); ++minCount; } if (chord.getHighestNoteHeight() > maxTopHeight) { maxTopHeight = chord.getHighestNoteHeight(); ++maxCount; } } endBottomHeight = chord.getLowestNoteHeight(); endTopHeight = chord.getHighestNoteHeight(); endX = (int)(*scooter)->getLayoutX(); endStemUp = stemUp; endMarks = chord.getMarkCountForChord(); bool tied = false; if ((event->get <Bool>(TIED_FORWARD, tied) && tied) || (event->get<Bool>(TIED_BACKWARD, tied) && tied)) { endTied = true; } } if (!beamed) { if (stemUp) stemUpNotes.push_back(event); else stemDownNotes.push_back(event); } } else if (event->isa(Indication::EventType)) { try { std::string indicationType = event->get <String>(Indication::IndicationTypePropertyName); if (indicationType == Indication::Crescendo || indicationType == Indication::Decrescendo) dynamic = true; } catch (...) { } } ++scooter; } bool above = true; if ((*i)->event()->has(NotationProperties::SLUR_ABOVE) && (*i)->event()->isPersistent<Bool>(NotationProperties::SLUR_ABOVE)) { (*i)->event()->get <Bool>(NotationProperties::SLUR_ABOVE, above); } else if (phrasing) { int score = 0; // for "above" if (dynamic) score += 2; if (startStemUp == endStemUp) { if (startStemUp) score -= 2; else score += 2; } else if (beamBelow != beamAbove) { if (beamAbove) score -= 2; else score += 2; } if (maxTopHeight < 6) score += 1; else if (minBottomHeight > 2) score -= 1; if (stemUpNotes.size() != stemDownNotes.size()) { if (stemUpNotes.size() < stemDownNotes.size()) score += 1; else score -= 1; } above = (score >= 0); } else { if (startStemUp == endStemUp) { above = !startStemUp; } else if (beamBelow) { above = true; } else if (beamAbove) { above = false; } else if (stemUpNotes.size() != stemDownNotes.size()) { above = (stemUpNotes.size() < stemDownNotes.size()); } else { above = ((startTopHeight - 4) + (endTopHeight - 4) + (4 - startBottomHeight) + (4 - endBottomHeight) <= 8); } } // now choose the actual y-coord of the slur based on the side // we've decided to put it on int startHeight, endHeight; int startOffset = 2, endOffset = 2; if (above) { if (!startStemUp) startOffset += startMarks * 2; else startOffset += 5; if (!endStemUp) endOffset += startMarks * 2; else endOffset += 5; startHeight = startTopHeight + startOffset; endHeight = endTopHeight + endOffset; bool maxRelevant = ((maxTopHeight != endTopHeight) || (maxCount > 1)); if (maxRelevant) { int midHeight = (startHeight + endHeight) / 2; if (maxTopHeight > midHeight - 1) { startHeight += maxTopHeight - midHeight + 1; endHeight += maxTopHeight - midHeight + 1; } } } else { if (startStemUp) startOffset += startMarks * 2; else startOffset += 5; if (endStemUp) endOffset += startMarks * 2; else endOffset += 5; startHeight = startBottomHeight - startOffset; endHeight = endBottomHeight - endOffset; bool minRelevant = ((minBottomHeight != endBottomHeight) || (minCount > 1)); if (minRelevant) { int midHeight = (startHeight + endHeight) / 2; if (minBottomHeight < midHeight + 1) { startHeight -= midHeight - minBottomHeight + 1; endHeight -= midHeight - minBottomHeight + 1; } } } int y0 = staff.getLayoutYForHeight(startHeight), y1 = staff.getLayoutYForHeight(endHeight); int dy = y1 - y0; int length = endX - startX; int diff = staff.getLayoutYForHeight(0) - staff.getLayoutYForHeight(3); if (length < diff*10) diff /= 2; if (length > diff*3) length -= diff / 2; startX += diff; (*i)->event()->setMaybe<Bool>(NotationProperties::SLUR_ABOVE, above); (*i)->event()->setMaybe<Int>(m_properties.SLUR_Y_DELTA, dy); (*i)->event()->setMaybe<Int>(m_properties.SLUR_LENGTH, length); double displacedX = 0.0, displacedY = 0.0; long dxRaw = 0; (*i)->event()->get<Int>(DISPLACED_X, dxRaw); displacedX = double(dxRaw * m_npf->getNoteBodyWidth()) / 1000.0; long dyRaw = 0; (*i)->event()->get<Int>(DISPLACED_Y, dyRaw); displacedY = double(dyRaw * m_npf->getLineSpacing()) / 1000.0; (*i)->setLayoutX(startX + displacedX); (*i)->setLayoutY(y0 + displacedY);}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -