📄 notationgroup.cpp
字号:
// // For the rest of the notes in the chord, we just need to // indicate that they aren't part of the beam-drawing process and // don't need to draw a stem. NELIterator prev = getContainer().end(), prevprev = getContainer().end(); double gradient = (double)beam.gradient / 100.0; // NOTATION_DEBUG << "NotationGroup::applyBeam starting for group "<< this << endl; for (NELIterator i = getInitialNote(); i != getContainer().end(); ++i) { NotationElement* el = static_cast<NotationElement*>(*i); // Clear tuplingness for all events in the group, to be // reinstated by any subsequent call to applyTuplingLine. We // do this because applyTuplingLine doesn't clear these // properties from notes that don't need them; it only applies // them to notes that do. el->event()->unset(m_properties.TUPLING_LINE_MY_Y); if (el->isNote() && el->event()->has(BaseProperties::NOTE_TYPE) && el->event()->get <Int>(BaseProperties::NOTE_TYPE) < Note::Crotchet && el->event()->has(BaseProperties::BEAMED_GROUP_ID) && el->event()->get<Int>(BaseProperties::BEAMED_GROUP_ID) == m_groupNo) { NotationChord chord(getContainer(), i, &getQuantizer(), m_properties, m_clef, m_key); unsigned int j; // NOTATION_DEBUG << "NotationGroup::applyBeam: Found chord" << endl; bool hasShifted = chord.hasNoteHeadShifted(); for (j = 0; j < chord.size(); ++j) { NotationElement *el = static_cast<NotationElement*>(*chord[j]); el->event()->setMaybe<Bool> (m_properties.CHORD_PRIMARY_NOTE, false); el->event()->setMaybe<Bool> (m_properties.DRAW_FLAG, false); el->event()->setMaybe<Bool> (NotationProperties::BEAMED, true); el->event()->setMaybe<Bool> (NotationProperties::BEAM_ABOVE, beam.aboveNotes); el->event()->setMaybe<Bool> (m_properties.VIEW_LOCAL_STEM_UP, beam.aboveNotes); bool shifted = chord.isNoteHeadShifted(chord[j]); el->event()->setMaybe<Bool> (m_properties.NOTE_HEAD_SHIFTED, shifted); long dots = 0; (void)el->event()->get <Int>(BaseProperties::NOTE_DOTS, dots); el->event()->setMaybe<Bool> (m_properties.NOTE_DOT_SHIFTED, false); if (hasShifted && beam.aboveNotes) { long dots = 0; (void)el->event()->get <Int>(BaseProperties::NOTE_DOTS, dots); if (dots > 0) { el->event()->setMaybe<Bool> (m_properties.NOTE_DOT_SHIFTED, true); } } el->event()->setMaybe<Bool> (m_properties.NEEDS_EXTRA_SHIFT_SPACE, chord.hasNoteHeadShifted() && !beam.aboveNotes); } if (beam.aboveNotes) j = 0; else j = chord.size() - 1; NotationElement *el = static_cast<NotationElement*>(*chord[j]); el->event()->setMaybe<Bool>(NotationProperties::BEAMED, false); // set later el->event()->setMaybe<Bool>(m_properties.DRAW_FLAG, true); // set later int x = (int)el->getLayoutX(); int myY = (int)(gradient * (x - initialX)) + beam.startY; int beamCount = NoteStyleFactory::getStyleForEvent(el->event())-> getFlagCount(el->event()->get <Int>(BaseProperties::NOTE_TYPE)); // If THIS_PART_BEAMS is true, then when drawing the // chord, if it requires more beams than the following // chord then they should be added as partial beams to the // right of the stem. // If NEXT_PART_BEAMS is true, then when drawing the // chord, if it requires fewer beams than the following // chord then the difference should be added as partial // beams to the left of the following chord's stem. // Procedure for setting these: If we have more beams than // the preceding chord, then the preceding chord should // have NEXT_PART_BEAMS set, until possibly unset again on // the next iteration. If we have at least as many beams // as the preceding chord, then the preceding chord should // have THIS_PART_BEAMS unset and the one before it should // have NEXT_PART_BEAMS unset. The first chord should // have THIS_PART_BEAMS set, until possibly unset again on // the next iteration. if (prev != getContainer().end()) { NotationElement *prevEl = static_cast<NotationElement*>(*prev); int secWidth = x - (int)prevEl->getLayoutX(); // prevEl->event()->setMaybe<Int>(BEAM_NEXT_Y, myY); prevEl->event()->setMaybe<Int> (m_properties.BEAM_SECTION_WIDTH, secWidth); prevEl->event()->setMaybe<Int> (m_properties.BEAM_NEXT_BEAM_COUNT, beamCount); int prevBeamCount = NoteStyleFactory::getStyleForEvent(prevEl->event())-> getFlagCount(prevEl->event()->get <Int>(BaseProperties::NOTE_TYPE)); if ((beamCount > 0) && (prevBeamCount > 0)) { el->event()->setMaybe<Bool>(m_properties.BEAMED, true); el->event()->setMaybe<Bool>(m_properties.DRAW_FLAG, false); prevEl->event()->setMaybe<Bool>(m_properties.BEAMED, true); prevEl->event()->setMaybe<Bool>(m_properties.DRAW_FLAG, false); } if (beamCount >= prevBeamCount) { prevEl->event()->setMaybe<Bool> (m_properties.BEAM_THIS_PART_BEAMS, false); if (prevprev != getContainer().end()) { (*prevprev)->event()->setMaybe<Bool> (m_properties.BEAM_NEXT_PART_BEAMS, false); } } if (beamCount > prevBeamCount) { prevEl->event()->setMaybe<Bool> (m_properties.BEAM_NEXT_PART_BEAMS, true); } } else { el->event()->setMaybe<Bool>(m_properties.BEAM_THIS_PART_BEAMS, true); } el->event()->setMaybe<Bool>(m_properties.CHORD_PRIMARY_NOTE, true); el->event()->setMaybe<Int>(m_properties.BEAM_MY_Y, myY); el->event()->setMaybe<Int>(m_properties.BEAM_GRADIENT, beam.gradient); // until they're set next time around the loop, as (*prev)->... // el->event()->setMaybe<Int>(m_properties.BEAM_NEXT_Y, myY); el->event()->setMaybe<Int>(m_properties.BEAM_SECTION_WIDTH, 0); el->event()->setMaybe<Int>(m_properties.BEAM_NEXT_BEAM_COUNT, 1); prevprev = prev; prev = chord[j]; i = chord.getFinalElement(); } else if (el->isNote()) { //!!! should we really be setting these here as well as in // applyStemProperties? /* if (i == initialNote || i == finalNote) { (*i)->event()->setMaybe<Bool>(m_properties.VIEW_LOCAL_STEM_UP, beam.aboveNotes); } else { (*i)->event()->setMaybe<Bool>(m_properties.VIEW_LOCAL_STEM_UP, !beam.aboveNotes); } */ } if (i == finalNote || el->getViewAbsoluteTime() > finalTime) break; }}voidNotationGroup::applyTuplingLine(NotationStaff &staff){ // NOTATION_DEBUG << "NotationGroup::applyTuplingLine, group no is " << m_groupNo << ", group type is " << m_type << endl; if (m_type != Tupled) return ; // NOTATION_DEBUG << "NotationGroup::applyTuplingLine: line is necessary" << endl; Beam beam(calculateBeam(staff)); NELIterator initialNote(getInitialNote()), finalNote( getFinalNote()), initialElement(getInitialElement()), finalElement( getFinalElement()); NELIterator initialNoteOrRest(initialElement); NotationElement* initialNoteOrRestEl = static_cast<NotationElement*>(*initialNoteOrRest); while (initialNoteOrRest != finalElement && !(initialNoteOrRestEl->isNote() || initialNoteOrRestEl->isRest())) { ++initialNoteOrRest; initialNoteOrRestEl = static_cast<NotationElement*>(*initialNoteOrRest); } if (!initialNoteOrRestEl->isRest()) { initialNoteOrRest = initialNote; initialNoteOrRestEl = static_cast<NotationElement*>(*initialNoteOrRest); } if (initialNoteOrRest == staff.getViewElementList()->end()) return ; // NOTATION_DEBUG << "NotationGroup::applyTuplingLine: first element is " << (initialNoteOrRestEl->isNote() ? "Note" : "Non-Note") << ", last is " << (static_cast<NotationElement*>(*finalElement)->isNote() ? "Note" : "Non-Note") << endl; int initialX = (int)(*initialNoteOrRest)->getLayoutX(); int finalX = (int)(*finalElement)->getLayoutX(); if (initialNote == staff.getViewElementList()->end() && finalNote == staff.getViewElementList()->end()) { Event *e = (*initialNoteOrRest)->event(); e->setMaybe<Int>(m_properties.TUPLING_LINE_MY_Y, staff.getLayoutYForHeight(12)); e->setMaybe<Int>(m_properties.TUPLING_LINE_WIDTH, finalX - initialX); e->setMaybe<Int>(m_properties.TUPLING_LINE_GRADIENT, 0); } else { // only notes have height int initialY = staff.getLayoutYForHeight(height(initialNote)); int finalY = staff.getLayoutYForHeight(height( finalNote)); // if we have a beam and both end-points of it are notes, // place the tupling number over it (that is, make the tupling // line follow the beam and say so); otherwise make the line // follow the gradient a beam would have, but on the other // side of the notes bool followBeam = (beam.necessary && (*initialNoteOrRest)->event()->isa(Note::EventType) && (finalNote == finalElement)); int startY = (followBeam ? beam.startY : initialY - (beam.startY - initialY)); int endY = startY + (int)((finalX - initialX) * ((double)beam.gradient / 100.0)); // NOTATION_DEBUG << "applyTuplingLine: beam.startY is " << beam.startY << ", initialY is " << initialY << " so my startY is " << startY << ", endY " << endY << ", beam.gradient " << beam.gradient << endl; int nh = staff.getNotePixmapFactory(m_type == Grace).getNoteBodyHeight(); if (followBeam) { // adjust to move text slightly away from beam int maxEndBeamCount = 1; long bc; if ((*initialNoteOrRest)->event()->get <Int> (m_properties.BEAM_NEXT_BEAM_COUNT, bc)) { if (bc > maxEndBeamCount) maxEndBeamCount = bc; } if ((*finalNote)->event()->get <Int> (m_properties.BEAM_NEXT_BEAM_COUNT, bc)) { if (bc > maxEndBeamCount) maxEndBeamCount = bc; } int extraBeamSpace = maxEndBeamCount * nh + nh / 2; if (beam.aboveNotes) { startY -= extraBeamSpace; endY -= extraBeamSpace; finalX += nh; } else { startY += extraBeamSpace; endY += extraBeamSpace; finalX -= nh; } } else { // adjust to place close to note heads if (startY < initialY) { if (initialY - startY > nh * 3) startY = initialY - nh * 3; if ( finalY - endY < nh * 2) startY -= nh * 2 - (finalY - endY); } else { if (startY - initialY > nh * 3) startY = initialY + nh * 3; if ( endY - finalY < nh * 2) startY += nh * 2 - (endY - finalY); } } Event *e = (*initialNoteOrRest)->event(); e->setMaybe<Int>(m_properties.TUPLING_LINE_MY_Y, startY); e->setMaybe<Int>(m_properties.TUPLING_LINE_WIDTH, finalX - initialX); e->setMaybe<Int>(m_properties.TUPLING_LINE_GRADIENT, beam.gradient); e->setMaybe<Bool>(m_properties.TUPLING_LINE_FOLLOWS_BEAM, followBeam); }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -