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; }