std::vector<Staff *> Measure::GetFirstStaffGrpStaves(ScoreDef *scoreDef) { assert(scoreDef); std::vector<Staff *> staves; std::vector<int>::iterator iter; std::vector<int> staffList; // First get all the staffGrps AttComparison matchType(STAFFGRP); ArrayOfObjects staffGrps; ArrayOfObjects::iterator staffGrpIter; scoreDef->FindAllChildByComparison(&staffGrps, &matchType); // Then the @n of each first staffDef for (staffGrpIter = staffGrps.begin(); staffGrpIter != staffGrps.end(); ++staffGrpIter) { StaffDef *staffDef = dynamic_cast<StaffDef *>((*staffGrpIter)->GetFirst(STAFFDEF)); if (staffDef) staffList.push_back(staffDef->GetN()); } // Get the corresponding staves in the measure for (iter = staffList.begin(); iter != staffList.end(); ++iter) { AttNIntegerComparison matchN(STAFF, *iter); Staff *staff = dynamic_cast<Staff *>(this->FindChildByComparison(&matchN, 1)); if (!staff) { // LogDebug("Staff with @n '%d' not found in measure '%s'", *iter, measure->GetUuid().c_str()); continue; } staves.push_back(staff); } if (staves.empty()) LogDebug("Empty @staff array"); return staves; }
void View::DrawSlurInitial(FloatingCurvePositioner *curve, Slur *slur, int x1, int x2, Staff *staff, char spanningType) { Beam *parentBeam = NULL; Chord *startParentChord = NULL; Chord *endParentChord = NULL; Note *startNote = NULL; Note *endNote = NULL; Chord *startChord = NULL; Chord *endChord = NULL; curvature_CURVEDIR drawingCurveDir = curvature_CURVEDIR_above; data_STEMDIRECTION startStemDir = STEMDIRECTION_NONE; data_STEMDIRECTION endStemDir = STEMDIRECTION_NONE; data_STEMDIRECTION stemDir = STEMDIRECTION_NONE; bool isGraceToNoteSlur = false; int y1 = staff->GetDrawingY(); int y2 = staff->GetDrawingY(); /************** parent layers **************/ LayerElement *start = dynamic_cast<LayerElement *>(slur->GetStart()); LayerElement *end = dynamic_cast<LayerElement *>(slur->GetEnd()); if (!start || !end) { // no start and end, obviously nothing to do... return; } if (start->Is(TIMESTAMP_ATTR) && end->Is(TIMESTAMP_ATTR)) { // for now ignore slur using 2 tstamps return; } if (start->Is(NOTE)) { startNote = dynamic_cast<Note *>(start); assert(startNote); startParentChord = startNote->IsChordTone(); startStemDir = startNote->GetDrawingStemDir(); } else if (start->Is(CHORD)) { startChord = dynamic_cast<Chord *>(start); assert(startChord); startStemDir = startChord->GetDrawingStemDir(); } if (end->Is(NOTE)) { endNote = dynamic_cast<Note *>(end); assert(endNote); endParentChord = endNote->IsChordTone(); endStemDir = endNote->GetDrawingStemDir(); } else if (end->Is(CHORD)) { endChord = dynamic_cast<Chord *>(end); assert(endChord); endStemDir = endChord->GetDrawingStemDir(); } if (startNote && endNote && startNote->IsGraceNote() && !endNote->IsGraceNote()) { isGraceToNoteSlur = true; } Layer *layer = NULL; LayerElement *layerElement = NULL; // For now, with timestamps, get the first layer. We should eventually look at the @layerident (not implemented) if (!start->Is(TIMESTAMP_ATTR)) { layer = dynamic_cast<Layer *>(start->GetFirstParent(LAYER)); layerElement = start; } else { layer = dynamic_cast<Layer *>(end->GetFirstParent(LAYER)); layerElement = end; } assert(layer); if (!start->Is(TIMESTAMP_ATTR) && !end->Is(TIMESTAMP_ATTR) && (spanningType == SPANNING_START_END)) { System *system = dynamic_cast<System *>(staff->GetFirstParent(SYSTEM)); assert(system); // If we have a start to end situation, then store the curvedir in the slur for mixed drawing stem dir // situations if (system->HasMixedDrawingStemDir(start, end)) { slur->SetDrawingCurvedir(curvature_CURVEDIR_above); } } /************** calculate the radius for adjusting the x position **************/ int startRadius = 0; if (!start->Is(TIMESTAMP_ATTR)) { startRadius = start->GetDrawingRadius(m_doc); } int endRadius = 0; if (!end->Is(TIMESTAMP_ATTR)) { endRadius = end->GetDrawingRadius(m_doc); } /************** note stem dir **************/ if (spanningType == SPANNING_START_END) { stemDir = startStemDir; } // This is the case when the tie is split over two system of two pages. // In this case, we are now drawing its beginning to the end of the measure (i.e., the last aligner) else if (spanningType == SPANNING_START) { stemDir = startStemDir; } // Now this is the case when the tie is split but we are drawing the end of it else if (spanningType == SPANNING_END) { stemDir = endStemDir; } // Finally, slur accross an entire system; use the staff position and up (see below) else { stemDir = STEMDIRECTION_down; } /************** direction **************/ data_STEMDIRECTION layerStemDir; // first should be the tie @curvedir if (slur->HasCurvedir()) { drawingCurveDir = (slur->GetCurvedir() == curvature_CURVEDIR_above) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } // grace notes - always below unless we have a drawing stem direction on the layer else if (isGraceToNoteSlur && (layer->GetDrawingStemDir(layerElement) == STEMDIRECTION_NONE)) { drawingCurveDir = curvature_CURVEDIR_below; } // the normal case else if (slur->HasDrawingCurvedir()) { drawingCurveDir = slur->GetDrawingCurvedir(); } // then layer direction trumps note direction else if (layer && ((layerStemDir = layer->GetDrawingStemDir(layerElement)) != STEMDIRECTION_NONE)) { drawingCurveDir = (layerStemDir == STEMDIRECTION_up) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } // look if in a chord else if (startParentChord) { if (startParentChord->PositionInChord(startNote) < 0) { drawingCurveDir = curvature_CURVEDIR_below; } else if (startParentChord->PositionInChord(startNote) > 0) { drawingCurveDir = curvature_CURVEDIR_above; } // away from the stem if odd number (center note) else { drawingCurveDir = (stemDir != STEMDIRECTION_up) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } } else if (stemDir == STEMDIRECTION_up) { drawingCurveDir = curvature_CURVEDIR_below; } else if (stemDir == STEMDIRECTION_NONE) { // no information from the note stem directions, look at the position in the notes int center = staff->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) * 2; drawingCurveDir = (start->GetDrawingY() > center) ? curvature_CURVEDIR_above : curvature_CURVEDIR_below; } /************** adjusting y position **************/ bool isShortSlur = false; if (x2 - x1 < 1 * m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize)) isShortSlur = true; int yChordMax, yChordMin; if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_START)) { // first get the min max of the chord (if any) if (startParentChord) { startParentChord->GetYExtremes(yChordMax, yChordMin); } else if (startChord) { startChord->GetYExtremes(yChordMax, yChordMin); } // slur is up if (drawingCurveDir == curvature_CURVEDIR_above) { // P(^) if (startStemDir == STEMDIRECTION_down) y1 = start->GetDrawingTop(m_doc, staff->m_drawingStaffSize); // d(^)d else if (isShortSlur) { y1 = start->GetDrawingTop(m_doc, staff->m_drawingStaffSize); } // same but in beam - adjust the x too else if ((parentBeam = start->IsInBeam()) && !parentBeam->IsLastInBeam(start)) { y1 = start->GetDrawingTop(m_doc, staff->m_drawingStaffSize); x1 += startRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // d(^) else { // put it on the side, move it left, but not if we have a @stamp if (!start->Is(TIMESTAMP_ATTR)) x1 += m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 4 / 2; if (startChord || startParentChord) y1 = yChordMin + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y1 = start->GetDrawingY() + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } // slur is down else { // d(_) if (startStemDir == STEMDIRECTION_up) y1 = start->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); // P(_)P else if (isShortSlur) { y1 = start->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); } // same but in beam else if ((parentBeam = start->IsInBeam()) && !parentBeam->IsLastInBeam(start)) { y1 = start->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); x1 -= startRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // P(_) else { // put it on the side, but no need to move it left if (startChord || startParentChord) y1 = yChordMin - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y1 = start->GetDrawingY() - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } } if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_END)) { // get the min max of the chord if any if (endParentChord) { endParentChord->GetYExtremes(yChordMax, yChordMin); } else if (endChord) { endChord->GetYExtremes(yChordMax, yChordMin); } // get the stem direction of the end // slur is up if (drawingCurveDir == curvature_CURVEDIR_above) { // (^)P if (endStemDir == STEMDIRECTION_down) y2 = end->GetDrawingTop(m_doc, staff->m_drawingStaffSize); // d(^)d else if (isShortSlur) { y2 = end->GetDrawingTop(m_doc, staff->m_drawingStaffSize); } // same but in beam - adjust the x too else if ((parentBeam = end->IsInBeam()) && !parentBeam->IsFirstInBeam(end)) { y2 = end->GetDrawingTop(m_doc, staff->m_drawingStaffSize); x2 += endRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // (^)d else { // put it on the side, no need to move it right if (endChord || endParentChord) y2 = yChordMin + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y2 = end->GetDrawingY() + m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } else { if (isGraceToNoteSlur) { if (endNote) { y2 = endNote->GetDrawingY(); x2 -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 2; isShortSlur = true; } else { y2 = y1; } } // (_)d else if (endStemDir == STEMDIRECTION_up) y2 = end->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); // P(_)P else if (isShortSlur) { y2 = end->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); } // same but in beam else if ((parentBeam = end->IsInBeam()) && !parentBeam->IsFirstInBeam(end)) { y2 = end->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); // x2 -= endRadius - m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); } // (_)P else { // put it on the side, move it right, but not if we have a @stamp2 if (!end->Is(TIMESTAMP_ATTR)) x2 -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 2; if (endChord || endParentChord) y2 = yChordMin - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; else y2 = end->GetDrawingY() - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * 3; } } } // Positions not attached to a note if (spanningType == SPANNING_START) { if (drawingCurveDir == curvature_CURVEDIR_above) y2 = std::max(staff->GetDrawingY(), y1); else y2 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y1); } if (end->Is(TIMESTAMP_ATTR)) { if (drawingCurveDir == curvature_CURVEDIR_above) y2 = std::max(staff->GetDrawingY(), y1); else y2 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y1); } if (spanningType == SPANNING_END) { if (drawingCurveDir == curvature_CURVEDIR_above) y1 = std::max(staff->GetDrawingY(), y2); else y1 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y2); } if (start->Is(TIMESTAMP_ATTR)) { if (drawingCurveDir == curvature_CURVEDIR_above) y1 = std::max(staff->GetDrawingY(), y2); else y1 = std::min(staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize), y2); } // slur accross an entire system; use the staff position else if (spanningType == SPANNING_MIDDLE) { // To be adjusted if (drawingCurveDir == curvature_CURVEDIR_above) y1 = staff->GetDrawingY(); else y1 = staff->GetDrawingY() - m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize); y2 = y1; } /************** y position **************/ if (drawingCurveDir == curvature_CURVEDIR_above) { y1 += 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 += 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); } else { y1 -= 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); y2 -= 1 * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); } Point points[4]; points[0] = Point(x1, y1); points[3] = Point(x2, y2); float angle = CalcInitialSlur(curve, slur, staff, layer->GetN(), drawingCurveDir, points); int thickness = m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * m_options->m_slurThickness.GetValue(); curve->UpdateCurveParams(points, angle, thickness, drawingCurveDir); /************** articulation **************/ // First get all artic children ClassIdComparison matchType(ARTIC); ArrayOfObjects artics; ArrayOfObjects::iterator articIter; // the normal case or start if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_START)) { start->FindAllChildByComparison(&artics, &matchType); // Then the @n of each first staffDef for (articIter = artics.begin(); articIter != artics.end(); ++articIter) { Artic *artic = dynamic_cast<Artic *>(*articIter); assert(artic); ArticPart *outsidePart = artic->GetOutsidePart(); if (outsidePart) { if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_above) && (drawingCurveDir == curvature_CURVEDIR_above)) { outsidePart->AddSlurPositioner(curve, true); } else if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_below) && (drawingCurveDir == curvature_CURVEDIR_below)) { outsidePart->AddSlurPositioner(curve, true); } } } } // normal case or end if ((spanningType == SPANNING_START_END) || (spanningType == SPANNING_END)) { end->FindAllChildByComparison(&artics, &matchType); // Then the @n of each first staffDef for (articIter = artics.begin(); articIter != artics.end(); ++articIter) { Artic *artic = dynamic_cast<Artic *>(*articIter); assert(artic); ArticPart *outsidePart = artic->GetOutsidePart(); if (outsidePart) { if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_above) && (drawingCurveDir == curvature_CURVEDIR_above)) { outsidePart->AddSlurPositioner(curve, false); } else if ((outsidePart->GetPlace().GetBasic() == STAFFREL_basic_below) && (drawingCurveDir == curvature_CURVEDIR_below)) { outsidePart->AddSlurPositioner(curve, false); } } } } return; }
void Object::Process(Functor *functor, ArrayPtrVoid params, Functor *endFunctor, ArrayOfAttComparisons *filters, int deepness, bool direction ) { if (functor->m_returnCode == FUNCTOR_STOP) { return; } EditorialElement *editorialElement = dynamic_cast<EditorialElement*>(this); if (functor->m_visibleOnly && editorialElement && ( editorialElement->m_visibility == Hidden ) ) { return; } functor->Call( this, params ); // do not go any deeper in this case if (functor->m_returnCode == FUNCTOR_SIBLINGS) { functor->m_returnCode = FUNCTOR_CONTINUE; return; } else if (dynamic_cast<EditorialElement*>(this)) { // since editorial object do not count, we re-increase the deepness limit deepness++; } if (deepness == 0) { // any need to change the functor m_returnCode? return; } deepness--; ArrayOfObjects::iterator iter; // We need a pointer to the array for the option to work on a reversed copy ArrayOfObjects *children = &this->m_children; ArrayOfObjects reversed; // For processing backward, we operated on a copied reversed version // Since we hold pointers, only addresses are copied if ( direction == BACKWARD ) { reversed = (*children); std::reverse( reversed.begin(), reversed.end() ); children = &reversed; } for (iter = children->begin(); iter != children->end(); ++iter) { if ( filters && !filters->empty() ) { bool hasAttComparison = false; // first we look if there is a comparison object for the object type (e.g., a Staff) ArrayOfAttComparisons::iterator attComparisonIter; for (attComparisonIter = filters->begin(); attComparisonIter != filters->end(); attComparisonIter++) { // if yes, we will use it (*attComparisonIter) for evaluating if the object matches // the attribute (see below) if ((*attComparisonIter)->GetType() == &typeid(**iter)) { hasAttComparison = true; break; } } if (hasAttComparison) { // use the operator of the AttComparison object to evaluate the attribute if ((**attComparisonIter)(*iter)) { // the attribute value matches, process the object //LogDebug("%s ", (*iter)->GetClassName().c_str() ); (*iter)->Process( functor, params, endFunctor, filters, deepness, direction ); break; } else { // the attribute value does not match, skip this child continue; } } } // we will end here if there is no filter at all or for the current child type (*iter)->Process( functor, params, endFunctor, filters, deepness, direction ); } if ( endFunctor ) { endFunctor->Call( this, params ); } }