Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}