int LayerElement::SetDrawingXY( ArrayPtrVoid *params ) { // param 0: a pointer doc // param 1: a pointer to the current system (unused) // param 2: a pointer to the current measure // param 3: a pointer to the current staff // param 4: a pointer to the current layer // param 5: a pointer to the view // param 6: a bool indicating if we are processing layer elements or not Doc *doc = static_cast<Doc*>((*params).at(0)); Measure **currentMeasure = static_cast<Measure**>((*params).at(2)); Staff **currentStaff = static_cast<Staff**>((*params).at(3)); Layer **currentLayer = static_cast<Layer**>((*params).at(4)); View *view = static_cast<View*>((*params).at(5)); bool *processLayerElements = static_cast<bool*>((*params).at(6)); // First pass, only set the X position if ((*processLayerElements)==false) { // Here we set the appropriate x value to be used for drawing // With Raw documents, we use m_drawingXRel that is calculated by the layout algorithm // With Transcription documents, we use the m_xAbs if ( this->m_xAbs == VRV_UNSET ) { assert( doc->GetType() == Raw ); this->SetDrawingX( this->GetXRel() + (*currentMeasure)->GetDrawingX() ); // Grace notes, also take into account the GraceAlignment Note *note = dynamic_cast<Note*>(this); if (note && note->HasGraceAlignment() ) { this->SetDrawingX( this->GetDrawingX() - note->GetAlignment()->GetGraceAligner()->GetWidth() + note->GetGraceAlignment()->GetXRel() ); } } else { assert( doc->GetType() == Transcription ); this->SetDrawingX( this->m_xAbs ); } return FUNCTOR_CONTINUE; } LayerElement *layerElementY = this; // Look for cross-staff situations // If we have one, make is available in m_crossStaff DurationInterface *durElement = dynamic_cast<DurationInterface*>(this); if ( durElement && durElement->HasStaff()) { AttCommonNComparison comparisonFirst( STAFF, durElement->GetStaff() ); m_crossStaff = dynamic_cast<Staff*>((*currentMeasure)->FindChildByAttComparison(&comparisonFirst, 1)); if (m_crossStaff) { if (m_crossStaff == (*currentStaff)) LogWarning("The cross staff reference '%d' for element '%s' seems to be identical to the parent staff", durElement->GetStaff(), this->GetUuid().c_str()); // Now try to get the corresponding layer - for now look for the same layer @n int layerN = (*currentLayer)->GetN(); // When we will have allowed @layer in <note>, we will have to do: // int layerN = durElement->HasLayer() ? durElement->GetLayer() : (*currentLayer)->GetN(); AttCommonNComparison comparisonFirstLayer( LAYER, layerN ); m_crossLayer = dynamic_cast<Layer*>(m_crossStaff->FindChildByAttComparison(&comparisonFirstLayer, 1)); if (m_crossLayer) { // Now we need to yet the element at the same position in the cross-staff layer of getting the right clef layerElementY = m_crossLayer->GetAtPos( this->GetDrawingX() ); } else { LogWarning("Could not get the layer with cross-staff reference '%d' for element '%s'", durElement->GetStaff(), this->GetUuid().c_str()); } } else { LogWarning("Could not get the cross staff reference '%d' for element '%s'", durElement->GetStaff(), this->GetUuid().c_str()); } // If we have a @layer we probably also want to change the layer element (for getting the right clef if different) } else { m_crossStaff = NULL; m_crossLayer = NULL; } Staff *staffY = m_crossStaff ? m_crossStaff : (*currentStaff); Layer *layerY = m_crossLayer ? m_crossLayer : (*currentLayer); // Here we set the appropriate Y value to be used for drawing if ( this->m_xAbs == VRV_UNSET ) { assert( doc->GetType() == Raw ); this->SetDrawingY( staffY->GetDrawingY() ); } else { assert( doc->GetType() == Transcription ); this->SetDrawingY( staffY->GetDrawingY() ); } // Finally, adjust Y for notes and rests if (this->Is() == NOTE) { Note *note = dynamic_cast<Note*>(this); assert( note ); this->SetDrawingY( this->GetDrawingY() + view->CalculatePitchPosY( staffY, note->GetPname(), layerY->GetClefOffset( layerElementY ), note->GetOct() ) ); } else if (this->Is() == REST) { Rest *rest = dynamic_cast<Rest*>(this); assert( rest ); // Automatically calculate rest position, if so requested if (rest->GetPloc() == PITCHNAME_NONE) { this->SetDrawingY( this->GetDrawingY() + view->CalculateRestPosY( staffY, rest->GetActualDur()) ); } else { this->SetDrawingY( this->GetDrawingY() + view->CalculatePitchPosY( staffY, rest->GetPloc(), layerY->GetClefOffset( layerElementY ), rest->GetOloc()) ); } } return FUNCTOR_CONTINUE; }
int Artic::CalcArtic(FunctorParams *functorParams) { FunctorDocParams *params = dynamic_cast<FunctorDocParams *>(functorParams); assert(params); /************** Get the parent and the stem direction **************/ LayerElement *parent = NULL; Note *parentNote = NULL; Chord *parentChord = dynamic_cast<Chord *>(this->GetFirstParent(CHORD, 2)); data_STEMDIRECTION stemDir = STEMDIRECTION_NONE; data_STAFFREL place = STAFFREL_NONE; if (!parentChord) { parentNote = dynamic_cast<Note *>(this->GetFirstParent(NOTE)); parent = parentNote; } else { parent = parentChord; } if (!parentChord && !parentNote) { // no parent chord or note, nothing we can do... return FUNCTOR_CONTINUE; } Staff *staff = dynamic_cast<Staff *>(this->GetFirstParent(STAFF)); assert(staff); Layer *layer = dynamic_cast<Layer *>(this->GetFirstParent(LAYER)); assert(layer); stemDir = parentNote ? parentNote->GetDrawingStemDir() : parentChord->GetDrawingStemDir(); /************** placement **************/ bool allowAbove = true; // for now we ignore within @place if (this->HasPlace() && (this->GetPlace() != STAFFREL_within)) { place = this->GetPlace(); // If we have a place indication do not allow to be changed to above allowAbove = false; } else if (layer->GetDrawingStemDir() != STEMDIRECTION_NONE) { place = (layer->GetDrawingStemDir() == STEMDIRECTION_up) ? STAFFREL_above : STAFFREL_below; // If we have more than one layer do not allow to be changed to above allowAbove = false; } else if (stemDir == STEMDIRECTION_up) place = STAFFREL_below; else place = STAFFREL_above; /************** set it to both the inside and outside part **************/ ArticPart *insidePart = this->GetInsidePart(); ArticPart *outsidePart = this->GetOutsidePart(); if (insidePart) { insidePart->SetPlace(place); } if (outsidePart) { // If allowAbove is true it will place the above if the content requires so (even if place below if given) if (place == STAFFREL_below && allowAbove && outsidePart->AlwaysAbove()) place = STAFFREL_above; outsidePart->SetPlace(place); } /************** calculate the y position **************/ Staff *staffAbove = NULL; Staff *staffBelow = NULL; // Cross-staff handling of articulation will need to be re-thought. We can look at assiging a cross-staff to the // appropriate ArticPart // (see below) - For chords, we need to distinguish cross-staff chords and cross-staff chord notes if (parent->m_crossStaff && parent->m_crossLayer) { staff = parent->m_crossStaff; staffAbove = staff; staffBelow = staff; } else if (parentChord) { parentChord->GetCrossStaffExtremes(staffAbove, staffBelow); } int staffYBottom = -params->m_doc->GetDrawingStaffSize(staff->m_drawingStaffSize); // Avoid in artic to be in legder lines int yInAbove = std::max( parent->GetDrawingTop(params->m_doc, staff->m_drawingStaffSize, false) - staff->GetDrawingY(), staffYBottom); int yInBelow = std::min(parent->GetDrawingBottom(params->m_doc, staff->m_drawingStaffSize, false) - staff->GetDrawingY(), 0); int yOutAbove = std::max(yInAbove, 0); int yOutBelow = std::min(yInBelow, staffYBottom); // Does not work properly with chords, needs rethinking - It might be better to make artic or articPart relative to // notes // The problem is that in MEI artic are children of chord element and not of the notes if (insidePart) { if (insidePart->GetPlace() == STAFFREL_above) { insidePart->SetDrawingYRel(yInAbove); insidePart->m_crossStaff = staffAbove; } else { insidePart->SetDrawingYRel(yInBelow); insidePart->m_crossStaff = staffBelow; } } if (outsidePart) { if (outsidePart->GetPlace() == STAFFREL_above) { outsidePart->SetDrawingYRel(yOutAbove); outsidePart->m_crossStaff = staffAbove; } else { outsidePart->SetDrawingYRel(yOutBelow); outsidePart->m_crossStaff = staffBelow; } } // If we have both an inside and outside part we need to move the outside part away when they are both on the same // side if (insidePart && outsidePart) { int margin = params->m_doc->GetTopMargin(insidePart->GetClassId()) * params->m_doc->GetDrawingUnit(staff->m_drawingStaffSize) / PARAM_DENOMINATOR; if (insidePart->GetPlace() == outsidePart->GetPlace()) { if (insidePart->GetPlace() == STAFFREL_above) { int inTop = insidePart->GetContentTop(); int outBottom = outsidePart->GetContentBottom(); if (inTop > outBottom) outsidePart->SetDrawingYRel(outsidePart->GetDrawingYRel() + inTop - outBottom + margin); } else { int inBottom = insidePart->GetContentBottom(); int outTop = outsidePart->GetContentTop(); if (inBottom < outTop) outsidePart->SetDrawingYRel(outsidePart->GetDrawingYRel() + outTop - inBottom + margin); } } } return FUNCTOR_SIBLINGS; }