void GRDiminuendo::tellPosition(GObject *caller, const NVPoint & newPosition) { GRNotationElement * grel = dynamic_cast<GRNotationElement *>(caller); if (grel == 0) return; GRStaff * staff = grel->getGRStaff(); if (staff == 0) return; GRSystemStartEndStruct * sse = getSystemStartEndStruct(staff->getGRSystem()); if (sse == 0) return; const GRNotationElement * const endElement = sse->endElement; if (grel == endElement) updateDiminuendo(staff); }
// ----------------------------------------------------------------------------- void GRBowing::tellPosition(GObject * caller, const NVPoint & newPosition) { GRNotationElement * grel = dynamic_cast<GRNotationElement *>(caller); if (grel == 0 ) return; GRStaff * staff = grel->getGRStaff(); if (staff == 0 ) return; GRSystemStartEndStruct * sse = getSystemStartEndStruct( staff->getGRSystem()); if (sse == 0) return; const GRNotationElement * const startElement = sse->startElement; const GRNotationElement * const endElement = sse->endElement; // if ( openLeftRange && openRightRange ) return; // updateBow(); if( grel == endElement || ( endElement == 0 && grel == startElement)) { updateBow( staff ); } }
// (JB) \bug There is probably a bug somewhere: with map mode // different than "ISOTROPIC" (proportionnal), beamings polygons between "UP" stems // draw at an incorrect x position, while "DOWN" beams are always ok. // // Too long, needs some code-factorization, if possible. void GRBeam::tellPosition( GObject * gobj, const NVPoint & p_pos) { /* Beams are polygons made of four points: 0 2 ------------------ | | ------------------ 1 3 */ // a new test is performed: if it is a systemTag and // it is not a systemcall (checkpos), than we can just do nothing. if (error || !mAssociated || ( mAssociated->GetCount() == 0 ) || ( tagtype == GRTag::SYSTEMTAG && !mIsSystemCall )) return; GRNotationElement * el = dynamic_cast<GRNotationElement *>(gobj); if (!el || !el->getGRStaff()) return; GRSystemStartEndStruct * sse = getSystemStartEndStruct(el->getGRStaff()->getGRSystem()); assert(sse); if (el != sse->endElement) return; GRBeamSaveStruct * st = (GRBeamSaveStruct *)sse->p; GuidoPos pos; GREvent * startEl = GREvent::cast(sse->startElement); GREvent * endEl = GREvent::cast(sse->endElement); // this is the staff to which the beam belongs and who draws it. const GRStaff * beamstaff = sse->startElement->getGRStaff(); PosInfos infos = { dirUP, LSPACE, 1.0f, (endEl == startEl)}; ARBeam * arBeam = getARBeam(); const bool isSpecBeam = arBeam->isGuidoSpecBeam(); if(startEl) infos.stemdir = startEl->getStemDirection(); else if(endEl) infos.stemdir = endEl->getStemDirection(); if(level != 0) return; NVPoint offset = initp0 (sse, startEl, infos); initp1 (sse, infos); offset = initp2 (sse, endEl, infos); initp3 (sse, infos); // ----------------------------------------------------------- // Now, we adjust the stemlengths, according to beamslope ... // we have the start and end-position in st->p // We have to determine the slope and adjust the slope to minimum and maximum ... // ----------------------------------------------------------- float stemWidth = st->p[2].x - st->p[0].x; float slope = (st->p[2].y - st->p[0].y) / stemWidth; // another hack to control the slope when events are on different staves - DF sept 15 2009 if (startEl && endEl && (startEl->getGRStaff() != endEl->getGRStaff())) { while ((slope < -0.20) || (slope > 0.20)) { float shift = (slope < 0) ? -LSPACE/4 : LSPACE/4; st->p[0].y += shift; st->p[1].y += shift; st->p[2].y -= shift; st->p[3].y -= shift; slope = (st->p[2].y - st->p[0].y) / stemWidth; } } bool needsadjust = true; // we have to adjust the slope ONLY if the stemlength // of the first and last element has not been set automatically! // and if we are note in the case of a chained feather beam if ( (startEl && startEl->getStemLengthSet() && endEl && endEl->getStemLengthSet()) || tagtype == SYSTEMTAG || (arBeam && isSpecBeam) || (isFeathered && startEl && startEl->stemHasBeenChanged())) { needsadjust = false; } else slopeAdjust (sse, startEl, endEl, slope, infos); if (arBeam && isSpecBeam) { // then we have to set the length ... if it is not set otherwise ... GRSingleNote * nt = dynamic_cast<GRSingleNote *>(sse->startElement); if(nt && !nt->getStemLengthSet()) { const float myval = arBeam->dy1->getValue(); nt->setStemLength( myval); } nt = dynamic_cast<GRSingleNote *>(sse->endElement); if(nt && !nt->getStemLengthSet()) { float myval; if (arBeam->dy3 && arBeam->dy3->TagIsSet()) myval = arBeam->dy3->getValue(); else myval = arBeam->dy1->getValue(); nt->setStemLength( myval); } } float offsetbeam = 0; // nobeamoffset describes, if no beamoffset is valid: if notes ask for different beam-offsets // then, there is just no offset .... things must be changed manually then .... bool nobeamoffset = false; if(( startEl && startEl->getStemLengthSet()) || ( endEl && endEl->getStemLengthSet())) nobeamoffset = true; for (int counter = 0; counter < 2; ++counter ) { if (counter == 1) { if ((offsetbeam == 0) || nobeamoffset) break; else if (!nobeamoffset) { st->p[0].y -= offsetbeam; st->p[1].y -= offsetbeam; st->p[2].y -= offsetbeam; st->p[3].y -= offsetbeam; offsetbeam = 0; } } pos = sse->startpos; while (pos) { // now we calculate the stem-end-positions ... GuidoPos oldpos = pos; GREvent * sn = GREvent::cast(mAssociated->GetNext(pos)); if (sn) { float rx = sn->getStemStartPos().x - st->p[0].x; if (tagtype == SYSTEMTAG) rx += sn->getGRStaff()->getPosition().x; float disty = st->p[2].y - st->p[0].y; float distx = st->p[2].x - st->p[0].x; float ly = disty / distx * rx; ly += st->p[0].y; float diffy = (float)sn->getStemStartPos().y; GDirection adjustdir=dirAUTO; if (sn->getStemDirection() == dirUP) { diffy += (float)sn->getStemLength(); adjustdir = dirUP; } else if (sn->getStemDirection() == dirDOWN) { adjustdir = dirDOWN; diffy -= (float)sn->getStemLength(); } ly -= diffy; if (tagtype == SYSTEMTAG) ly -= (float)sn->getGRStaff()->getPosition().y; // if we have a beam between grace notes, we don't want an offbase that whould make the stems too long GRNote * gnote = dynamic_cast<GRNote*>(startEl); bool isGrace = gnote ? gnote->isGraceNote() : false; float offbase = isGrace ? 0 : 3.5f * infos.currentLSPACE; if (ly < 0) { if (needsadjust) { if (adjustdir == dirDOWN) { const float newoffs = ly - offbase; if (newoffs < offsetbeam) { if (offsetbeam > 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } ly = -offbase; } else if (ly > -offbase) { const float newoffs = ly + offbase; if (newoffs > offsetbeam) { if (offsetbeam < 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } } } ly = -ly; } else if (needsadjust) { if (adjustdir == dirUP) { const float newoffs = ly + offbase; if (newoffs > offsetbeam) { if (offsetbeam < 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } ly = offbase; } else if (ly < offbase) { const float newoffs = ly - offbase; if (newoffs < offsetbeam) { if (offsetbeam > 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } } } // sn->changeStemLength( ly ); // adjusted - DF sept 15 2009 sn->changeStemLength( ly - infos.currentLSPACE/20 ); // so that the possible next featherd beam knows that he is chained // (and musn't change its slope) sn->setStemChanged(); } if (oldpos == sse->endpos) break; } //endEl->setStemChanged(); } if(!smallerBeams.empty()) { for(std::vector<GRBeam *>::iterator it = smallerBeams.begin(); it < smallerBeams.end(); it++) { (*it)->decLevel(); (*it)->tellPosition((*it)->getEndElement(), (*it)->getEndElement()->getPosition()); } return; } // -- Now we need to add the simplebeams as simplebeamgroups ... NVPoint myp[4]; int dir = st->direction; if (st->dirset) { // then the direction was set explicitly by the user ... GREvent * sn = GREvent::cast(mAssociated->GetHead()); if (sn) dir = sn->getStemDirection(); } else dir = infos.stemdir; bool first = true; pos = sse->startpos; // - These constants define the space and the thickness of additionnal beams. const float yFact1 = 0.75f * infos.currentLSPACE; // was 0.7f const float yFact2 = 0.4f * infos.currentLSPACE; // if we have a feathered beam, we just have to draw the main beam (already done) // and the other simple beams will only depend on the begining and ending // points, regardless of the durations of the inner notes. if(isFeathered) { ARFeatheredBeam * ar = static_cast<ARFeatheredBeam *>(getARBeam()->isARFeatheredBeam()); int begin = 0; int end = 0; GREvent * stemNoteBegin = GREvent::cast(mAssociated->GetHead()); GDirection localDir = stemNoteBegin->getStemDirection(); float yLocalFact1 = yFact1 * localDir * infos.currentSize; float yLocalFact2 = yFact2 * localDir * infos.currentSize; // if the user hasn't set the durations as parameters, // we will take the first and last notes'durations if(!ar->isDurationsSet()) { ar->findDefaultPoints(); } end = ar->getLastBeaming(); begin = ar->getFirstBeaming(); for(int i=1;i<=begin; i++) { myp[0] = st->p[0]; myp[0].y += (i-1) * yLocalFact1; myp[1].x = myp[0].x; myp[1].y = myp[0].y + yLocalFact2; myp[2] = st->p[2]; if(end>i ||(end==i && i!=1)) // no need to draw the main beam again. myp[2].y += (i-1) * yLocalFact1; else myp[2].y += (end-1) * yLocalFact1; myp[3].x = myp[2].x; myp[3].y = myp[2].y + yLocalFact2; GRSimpleBeam * tmpbeam = new GRSimpleBeam(this,myp); if( st->simpleBeams == 0 ) st->simpleBeams = new SimpleBeamList(1); st->simpleBeams->AddTail(tmpbeam); } // if end > begin for(int i=begin; i<end; i++) { myp[0] = st->p[0]; myp[0].y += (begin-1) * yLocalFact1; myp[1].x = myp[0].x; myp[1].y = myp[0].y + yLocalFact2; myp[2] = st->p[2]; myp[2].y += i * yLocalFact1; myp[3].x = myp[2].x; myp[3].y = myp[2].y + yLocalFact2; GRSimpleBeam * tmpbeam = new GRSimpleBeam(this,myp); if( st->simpleBeams == 0 ) st->simpleBeams = new SimpleBeamList(1); st->simpleBeams->AddTail(tmpbeam); } // in order to draw the total duration of the beam if(drawDur) { TYPE_TIMEPOSITION begin = ar->getBeginTimePosition(); TYPE_TIMEPOSITION end = ar->getEndTimePosition(); TYPE_DURATION dur = end - begin; int num = dur.getNumerator(); int den = dur.getDenominator(); stringstream out; out << num << '/' << den; st->duration = out.str(); size_t n = st->duration.length(); GREvent * ev = dynamic_cast<GREvent *>(mAssociated->GetHead()); const NVPoint p1 = ev->getStemEndPos(); float xBegin = ev->getPosition().x; ev = dynamic_cast<GREvent *>(mAssociated->GetTail()); const NVPoint p2 = ev->getStemEndPos(); float xEnd = ev->getPosition().x + ev->getBoundingBox().Width()/2; int dir = ev->getStemDirection(); float Y1; float Y2; if(dir>0) { Y1 = min(p1.y, p2.y) - LSPACE; if(Y1>=getLastPositionOfBarDuration().first && Y1<getLastPositionOfBarDuration().second+LSPACE/2) Y1 -= LSPACE; Y2 = Y1 - LSPACE/2; getLastPositionOfBarDuration().first = Y2; getLastPositionOfBarDuration().second = Y1; } else { Y1 = max(p1.y, p2.y) + LSPACE; if(Y1>=getLastPositionOfBarDuration().first-LSPACE/2 && Y1<getLastPositionOfBarDuration().second) Y1 += LSPACE; Y2 = Y1 + LSPACE/2; getLastPositionOfBarDuration().first = Y1; getLastPositionOfBarDuration().second = Y2; } if (xBegin > xEnd) { if (sse->endflag == GRSystemStartEndStruct::OPENRIGHT) xEnd = sse->endElement->getPosition().x; if (sse->startflag == GRSystemStartEndStruct::OPENLEFT) xBegin = sse->startElement->getPosition().x; } float x = xBegin + (xEnd - xBegin) / 2; float X1 = x - (n - 0.5f) / 2 * LSPACE; float X2 = x + (n - 0.5f) / 2 * LSPACE; st->DurationLine[0] = NVPoint(xBegin, Y1); st->DurationLine[1] = NVPoint(xBegin, Y2); st->DurationLine[2] = NVPoint(X1, Y2); st->DurationLine[3] = NVPoint(X2, Y2); st->DurationLine[4] = NVPoint(xEnd, Y2); st->DurationLine[5] = NVPoint(xEnd, Y1); } } // for beam length adjustment - DF sept 15 2009 const float xadjust = infos.currentLSPACE/10; GDirection lastLocalDir = dirOFF; int previousBeamsCount = 0; while (pos && !isFeathered) { GuidoPos oldpos = pos; GREvent * stemNote = GREvent::cast(mAssociated->GetNext(pos)); if (stemNote) { GDirection localDir = stemNote->getStemDirection(); float yLocalFact1 = yFact1 * localDir * infos.currentSize; float yLocalFact2 = yFact2 * localDir * infos.currentSize; // now we check the number of beams ... if (stemNote->getBeamCount() < stemNote->getNumFaehnchen()) { float beamCount = (float)(stemNote->getBeamCount()); stemNote->incBeamCount(); if (first && (sse->startflag == GRSystemStartEndStruct::OPENLEFT)) { // the additional beam starts at the startElement (glue), we have more beams to draw myp[0] = sse->startElement->getPosition(); if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[1] = myp[0]; // first = false; // never read (according to clang :-) } else { // the additional beam starts at sn. We have more beams to draw myp[0] = stemNote->getStemStartPos(); if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[0].y += beamCount * yLocalFact1; if (localDir != dir) myp[0].y -= yLocalFact2; myp[1].x = myp[0].x; myp[1].y = myp[0].y + yLocalFact2; } // now we look for the endposition GREvent * sn2 = NULL; GuidoPos tmppos = pos; // partialbeam is set, if the new SimpleBeam only covers part of the masterBeam. int partialbeam = 0; while (tmppos) { GuidoPos oldpos2 = tmppos; GREvent * tmpsn = GREvent::cast(mAssociated->GetNext(tmppos)); if (tmpsn) { if (tmpsn->getBeamCount() < tmpsn->getNumFaehnchen()) { sn2 = tmpsn; sn2->incBeamCount(); continue; } else { partialbeam = 1; break; } } if (oldpos2 == sse->endpos) break; } if (sn2) { if (!partialbeam && sse->endflag == GRSystemStartEndStruct::OPENRIGHT) { // then the position is different ... myp[2] = sse->endElement->getPosition(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += sn2->getGRStaff()->getPosition(); myp[2].y = myp[0].y; } else { // we have an End-Position ... myp[2] = sn2->getStemEndPos(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += sn2->getGRStaff()->getPosition(); myp[2].y += beamCount * yLocalFact1; } if (localDir != dir) myp[2].y -= yLocalFact2; myp[3].x = myp[2].x; myp[3].y = myp[2].y + yLocalFact2; } else { // we do not have an End-Positon single beam ... (meaning a single straight flag) // but only, if it is not open on the left or the right hand side. const float slope = (float)(st->p[2].y - st->p[0].y ) / (float)(st->p[2].x - st->p[0].x); if (sse->startflag == GRSystemStartEndStruct::OPENLEFT) { // then we have to deal with the startposition of the glue-element .... // BUT, you can only set this, if the previous beam had this beamcount at the end .... // how do I know that? not now. // sn is the only element .... and we are open on the left ... if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[1] = myp[0]; myp[2] = stemNote->getStemEndPos(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += stemNote->getGRStaff()->getPosition(); myp[2].y += beamCount * yLocalFact1; if (localDir != dir) myp[2].y -= yLocalFact2; myp[3] = myp[2]; myp[3].y += yLocalFact2; } else if (sse->endflag == GRSystemStartEndStruct::OPENRIGHT) { myp[0] = stemNote->getStemEndPos(); if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[0].y += beamCount * yLocalFact1; if (localDir != dir) myp[0].y -= yLocalFact2; myp[1] = myp[0]; myp[1].y += yLocalFact2; myp[2] = sse->endElement->getPosition(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += sn2->getGRStaff()->getPosition(); myp[2].y = myp[0].y; myp[3].x = myp[2].x; myp[3].y = myp[1].y; } /* 26/11/03 Beaming bug: wrong direction for partial beam (beam-bug.gmn) can be tested but changing this test. startpos check added to correct problem with partial beam going outside a group like in [ _/16 c d/8 ] */ else if( oldpos == sse->endpos || pos == NULL || ((!stemNote->isSyncopated()) && (oldpos != sse->startpos))) { // Partial beams leftward ( using slope) myp[2] = stemNote->getStemEndPos(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += stemNote->getGRStaff()->getPosition(); if (localDir != dir) myp[2].y -= yLocalFact2; myp[2].y += beamCount * yLocalFact1; myp[3] = myp[2]; myp[3].y += yLocalFact2; myp[0] = myp[2]; myp[0].x -= infos.currentLSPACE; myp[0].y -= slope * infos.currentLSPACE; myp[1] = myp[0]; myp[1].y += yLocalFact2; // ? We are at the end, there is no valid event at the end ... so what do we do? // useless tests: the code was the same and is now outside the test (above) - DF sept 15 2009 /* if (sse->endflag == GRSystemStartEndStruct::OPENRIGHT) { } else { } */ } else { // Partial beams rightward ( using slope) myp[2] = myp[0]; myp[2].x += infos.currentLSPACE; myp[2].y += slope * infos.currentLSPACE; myp[3] = myp[2]; myp[3].y += yLocalFact2; } } // now we construct a SimpleBeam, we now have to "undo" the systemTag-stuff if (tagtype == SYSTEMTAG) { const NVPoint & offset = beamstaff->getPosition(); myp[0] -= offset; myp[1] -= offset; myp[2] -= offset; myp[3] -= offset; } if (sse->startflag == GRSystemStartEndStruct::OPENLEFT) { myp[0].y = myp[2].y; myp[1].y = myp[3].y; } GRSimpleBeam * tmpbeam = new GRSimpleBeam(this,myp); if( st->simpleBeams == 0 ) st->simpleBeams = new SimpleBeamList(1); st->simpleBeams->AddTail(tmpbeam); pos = sse->startpos; oldpos = pos; first = true; lastLocalDir = localDir; previousBeamsCount = stemNote->getBeamCount() - 1; } // a new hack, again to catch stems directions change - DF sept 15 2009 else if (localDir != dir) { // check for stems length NVPoint stemloc = stemNote->getStemStartPos(); if (tagtype == SYSTEMTAG) stemloc += stemNote->getGRStaff()->getPosition(); int beamscount = stemNote->getBeamCount() - 1; if ((beamscount > 0) && (previousBeamsCount > beamscount) && (lastLocalDir != localDir)) { if (localDir == dirUP) stemNote->changeStemLength(stemNote->getStemLength() + (yLocalFact1 * beamscount)); else if (localDir == dirDOWN) stemNote->changeStemLength(stemNote->getStemLength() - (yLocalFact1 * beamscount)); } } } if (oldpos == sse->endpos) break; } GuidoPos stemPos = sse->startpos; while(stemPos) { GREvent * stemNote = GREvent::cast(mAssociated->GetNext(stemPos)); if(stemNote) { GuidoPos tagpos = NULL; if (stemNote->getAssociations()) tagpos = stemNote->getAssociations()->GetHeadPosition(); while(tagpos) { GRNotationElement * tag = stemNote->getAssociations()->GetNext(tagpos); GRTremolo * trem = dynamic_cast<GRTremolo*>(tag); if(trem) { trem->tellPosition(stemNote,stemNote->getPosition()); if(trem->isTwoNotesTremolo()) // in order to force the second pitch (especially the chords) to update { GREvent * secondPitch = dynamic_cast<GREvent*>(mAssociated->GetNext(stemPos)); if(secondPitch) trem->tellPosition(secondPitch, secondPitch->getPosition()); } } } } } // now we have to make sure, that the original positions // for the beam are set for the right staff if (tagtype == SYSTEMTAG) { const NVPoint &offset = beamstaff->getPosition(); st->p[0] -= offset; st->p[1] -= offset; st->p[2] -= offset; st->p[3] -= offset; } }
void GRBeam::StaffFinished(GRStaff * grstaff) { assert(false); assert(grstaff); // first, all the BASIC stuff is handled ... GRPositionTag::StaffFinished(grstaff); if (error) return; GRSystemStartEndStruct * sse = getSystemStartEndStruct(grstaff->getGRSystem()); assert(sse); GuidoPos syststpos = sse->startpos; if (syststpos) { // this is all done so that I really get a correct first staff to // test my stuff ... while (syststpos && !/*ynamic_cast<GRNotationElement *>*/(mAssociated->GetAt(syststpos))) { mAssociated->GetNext(syststpos); } const GRStaff *tststaff = mAssociated->GetNext(syststpos)->getGRStaff(); while (syststpos) { GRNotationElement * el = mAssociated->GetNext(syststpos); if (el) { if (el->getGRStaff() != tststaff) { tagtype = GRTag::SYSTEMTAG; GRSystemTag * mysystag = new GRSystemTag(this); el->getGRSystemSlice()->addSystemTag(mysystag); break; } } } } GRBeamSaveStruct * st = (GRBeamSaveStruct *)sse->p; GREvent * grn; checkNotes(grstaff); if (error) return; GuidoPos pos = sse->startpos; while (pos) { grn = GREvent::cast(mAssociated->GetNext(pos)); if (grn) { if (!st->dirset) { if (st->direction > 0) grn->setStemDirection(dirUP); else grn->setStemDirection(dirDOWN); } grn->setFlagOnOff(false); } } }
// (JB) \bug There is probably a bug somewhere: with map mode // different than "ISOTROPIC" (proportionnal), beamings polygons between "UP" stems // draw at an incorrect x position, while "DOWN" beams are always ok. // // Too long, needs some code-factorization, if possible. void GRBeam::tellPosition( GObject * gobj, const NVPoint & p_pos) { /* Beams are polygons made of four points: 0 2 ------------------ | | ------------------ 1 3 */ // a new test is performed: if it is a systemTag and // it is not a systemcall (checkpos), than we can just do nothing. if (error || !mAssociated || ( mAssociated->GetCount() == 0 ) || ( tagtype == GRTag::SYSTEMTAG && !mIsSystemCall )) return; GRNotationElement * el = dynamic_cast<GRNotationElement *>(gobj); if (!el || !el->getGRStaff()) return; GRSystemStartEndStruct * sse = getSystemStartEndStruct(el->getGRStaff()->getGRSystem()); assert(sse); if (el != sse->endElement) return; GRBeamSaveStruct * st = (GRBeamSaveStruct *)sse->p; GuidoPos pos; GREvent * startEl = GREvent::cast(sse->startElement); GREvent * endEl = GREvent::cast(sse->endElement); // this is the staff to which the beam belongs and who draws it. const GRStaff * beamstaff = sse->startElement->getGRStaff(); PosInfos infos = { dirUP, LSPACE, 1.0f, (endEl == startEl)}; ARBeam * arBeam = getARBeam(); const bool isSpecBeam = arBeam->isGuidoSpecBeam(); NVPoint offset = initp0 (sse, startEl, infos); initp1 (sse, infos); offset = initp2 (sse, endEl, infos); initp3 (sse, infos); // ----------------------------------------------------------- // Now, we adjust the stemlengths, according to beamslope ... // we have the start and end-position in st->p // We have to determine the slope and adjust the slope to minimum and maximum ... // ----------------------------------------------------------- float stemWidth = st->p[2].x - st->p[0].x; float slope = (st->p[2].y - st->p[0].y) / stemWidth; // another hack to control the slope when events are on different staves - DF sept 15 2009 if (startEl && endEl && (startEl->getGRStaff() != endEl->getGRStaff())) { while ((slope < -0.20) || (slope > 0.20)) { float shift = (slope < 0) ? -LSPACE/4 : LSPACE/4; st->p[0].y += shift; st->p[1].y += shift; st->p[2].y -= shift; st->p[3].y -= shift; slope = (st->p[2].y - st->p[0].y) / stemWidth; } } bool needsadjust = true; // we have to adjust the slope ONLY, if the stemlength // of the first and last element has not been set automatically! if ( (startEl && startEl->getStemLengthSet() && endEl && endEl->getStemLengthSet()) || tagtype == SYSTEMTAG || (arBeam && isSpecBeam)) { needsadjust = false; } else slopeAdjust (sse, startEl, endEl, slope, infos); if (arBeam && isSpecBeam) { // then we have to set the length ... if it is not set otherwise ... GRSingleNote * nt = dynamic_cast<GRSingleNote *>(sse->startElement); if(nt && !nt->getStemLengthSet()) { const float myval = arBeam->dy1->getValue(); nt->setStemLength( myval); } nt = dynamic_cast<GRSingleNote *>(sse->endElement); if(nt && !nt->getStemLengthSet()) { float myval; if (arBeam->dy3 && arBeam->dy3->TagIsSet()) myval = arBeam->dy3->getValue(); else myval = arBeam->dy1->getValue(); nt->setStemLength( myval); } } float offsetbeam = 0; // nobeamoffset describes, if no beamoffset is valid: if notes ask for different beam-offsets // then, there is just no offset .... things must be changed manually then .... bool nobeamoffset = false; if(( startEl && startEl->getStemLengthSet()) || ( endEl && endEl->getStemLengthSet())) nobeamoffset = true; for (int counter = 0; counter < 2; ++counter ) { if (counter == 1) { if ((offsetbeam == 0) || nobeamoffset) break; else if (!nobeamoffset) { st->p[0].y -= offsetbeam; st->p[1].y -= offsetbeam; st->p[2].y -= offsetbeam; st->p[3].y -= offsetbeam; offsetbeam = 0; } } pos = sse->startpos; while (pos) { // now we calculate the stem-end-positions ... GuidoPos oldpos = pos; GREvent * sn = GREvent::cast(mAssociated->GetNext(pos)); if (sn) { float rx = sn->getStemStartPos().x - st->p[0].x; if (tagtype == SYSTEMTAG) rx += sn->getGRStaff()->getPosition().x; float disty = st->p[2].y - st->p[0].y; float distx = st->p[2].x - st->p[0].x; float ly = disty / distx * rx; ly += st->p[0].y; float diffy = (float)sn->getStemStartPos().y; GDirection adjustdir=dirAUTO; if (sn->getStemDirection() == dirUP) { diffy += (float)sn->getStemLength(); adjustdir = dirUP; } else if (sn->getStemDirection() == dirDOWN) { adjustdir = dirDOWN; diffy -= (float)sn->getStemLength(); } ly -= diffy; if (tagtype == SYSTEMTAG) ly -= (float)sn->getGRStaff()->getPosition().y; float offbase = 3.5f * infos.currentLSPACE; if (ly < 0) { if (needsadjust) { if (adjustdir == dirDOWN) { const float newoffs = ly - offbase; if (newoffs < offsetbeam) { if (offsetbeam > 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } ly = -offbase; } else if (ly > -offbase) { const float newoffs = ly + offbase; if (newoffs > offsetbeam) { if (offsetbeam < 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } } } ly = -ly; } else if (needsadjust) { if (adjustdir == dirUP) { const float newoffs = ly + offbase; if (newoffs > offsetbeam) { if (offsetbeam < 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } ly = offbase; } else if (ly < offbase) { const float newoffs = ly - offbase; if (newoffs < offsetbeam) { if (offsetbeam > 0) { GuidoTrace("WARNING: different beam adjustments!"); nobeamoffset = true; } else offsetbeam = newoffs; } } } // sn->changeStemLength( ly ); // adjusted - DF sept 15 2009 sn->changeStemLength( ly - infos.currentLSPACE/20 ); } if (oldpos == sse->endpos) break; } } // -- Now we need to add the simplebeams as simplebeamgroups ... NVPoint myp[4]; int dir = st->direction; if (st->dirset) { // then the direction was set explicitly by the user ... GREvent * sn = GREvent::cast(mAssociated->GetHead()); if (sn) dir = sn->getStemDirection(); } else dir = infos.stemdir; bool first = true; pos = sse->startpos; // - These constants defines the space and the thickness of additionnal beams. const float yFact1 = 0.75f * infos.currentLSPACE; // was 0.7f const float yFact2 = 0.4f * infos.currentLSPACE; // for beam length adjustment - DF sept 15 2009 const float xadjust = infos.currentLSPACE/10; GDirection lastLocalDir = dirOFF; int previousBeamsCount = 0; while (pos) { GuidoPos oldpos = pos; GREvent * stemNote = GREvent::cast(mAssociated->GetNext(pos)); if (stemNote) { GDirection localDir = stemNote->getStemDirection(); float yLocalFact1 = yFact1 * localDir; float yLocalFact2 = yFact2 * localDir; // now we check the number of beams ... if (stemNote->getBeamCount() < stemNote->getNumFaehnchen()) { float beamCount = (float)(stemNote->getBeamCount()); stemNote->incBeamCount(); if (first && (sse->startflag == GRSystemStartEndStruct::OPENLEFT)) { // the additional beam starts at the startElement (glue), we have more beams to draw myp[0] = sse->startElement->getPosition(); if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[1] = myp[0]; // first = false; // never read (according to clang :-) } else { // the additional beam starts at sn. We have more beams to draw myp[0] = stemNote->getStemStartPos(); if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[0].y += beamCount * yLocalFact1; if (localDir != dir) myp[0].y -= yLocalFact2; myp[1].x = myp[0].x; myp[1].y = myp[0].y + yLocalFact2; } // now we look for the endposition GREvent * sn2 = NULL; GuidoPos tmppos = pos; // partialbeam is set, if the new SimpleBeam only covers part of the masterBeam. int partialbeam = 0; while (tmppos) { GuidoPos oldpos2 = tmppos; GREvent * tmpsn = GREvent::cast(mAssociated->GetNext(tmppos)); if (tmpsn) { if (tmpsn->getBeamCount() < tmpsn->getNumFaehnchen()) { sn2 = tmpsn; sn2->incBeamCount(); continue; } else { partialbeam = 1; break; } } if (oldpos2 == sse->endpos) break; } if (sn2) { if (!partialbeam && sse->endflag == GRSystemStartEndStruct::OPENRIGHT) { // then the position is different ... myp[2] = sse->endElement->getPosition(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += sn2->getGRStaff()->getPosition(); myp[2].y = myp[0].y; } else { // we have an End-Position ... myp[2] = sn2->getStemEndPos(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += sn2->getGRStaff()->getPosition(); myp[2].y += beamCount * yLocalFact1; } if (localDir != dir) myp[2].y -= yLocalFact2; myp[3].x = myp[2].x; myp[3].y = myp[2].y + yLocalFact2; } else { // we do not have an End-Positon single beam ... (meaning a single straight flag) // but only, if it is not open on the left or the right hand side. const float slope = (float)(st->p[2].y - st->p[0].y ) / (float)(st->p[2].x - st->p[0].x); if (sse->startflag == GRSystemStartEndStruct::OPENLEFT) { // then we have to deal with the startposition of the glue-element .... // BUT, you can only set this, if the previous beam had this beamcount at the end .... // how do I know that? not now. // sn is the only element .... and we are open on the left ... if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[1] = myp[0]; myp[2] = stemNote->getStemEndPos(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += stemNote->getGRStaff()->getPosition(); myp[2].y += beamCount * yLocalFact1; if (localDir != dir) myp[2].y -= yLocalFact2; myp[3] = myp[2]; myp[3].y += yLocalFact2; } else if (sse->endflag == GRSystemStartEndStruct::OPENRIGHT) { myp[0] = stemNote->getStemEndPos(); if (tagtype == SYSTEMTAG) myp[0] += stemNote->getGRStaff()->getPosition(); myp[0].y += beamCount * yLocalFact1; if (localDir != dir) myp[0].y -= yLocalFact2; myp[1] = myp[0]; myp[1].y += yLocalFact2; myp[2] = sse->endElement->getPosition(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += sn2->getGRStaff()->getPosition(); myp[2].y = myp[0].y; myp[3].x = myp[2].x; myp[3].y = myp[1].y; } /* 26/11/03 Beaming bug: wrong direction for partial beam (beam-bug.gmn) can be tested but changing this test. startpos check added to correct problem with partial beam going outside a group like in [ _/16 c d/8 ] */ else if( oldpos == sse->endpos || pos == NULL || ((!stemNote->isSyncopated()) && (oldpos != sse->startpos))) { // Partial beams leftward ( using slope) myp[2] = stemNote->getStemEndPos(); myp[2].x += xadjust; if (tagtype == SYSTEMTAG) myp[2] += stemNote->getGRStaff()->getPosition(); if (localDir != dir) myp[2].y -= yLocalFact2; myp[2].y += beamCount * yLocalFact1; myp[3] = myp[2]; myp[3].y += yLocalFact2; myp[0] = myp[2]; myp[0].x -= infos.currentLSPACE; myp[0].y -= slope * infos.currentLSPACE; myp[1] = myp[0]; myp[1].y += yLocalFact2; // ? We are at the end, there is no valid event at the end ... so what do we do? // useless tests: the code was the same and is now outside the test (above) - DF sept 15 2009 /* if (sse->endflag == GRSystemStartEndStruct::OPENRIGHT) { } else { } */ } else { // Partial beams rightward ( using slope) myp[2] = myp[0]; myp[2].x += infos.currentLSPACE; myp[2].y += slope * infos.currentLSPACE; myp[3] = myp[2]; myp[3].y += yLocalFact2; } } // now we construct a SimpleBeam, we now have to "undo" the systemTag-stuff if (tagtype == SYSTEMTAG) { const NVPoint & offset = beamstaff->getPosition(); myp[0] -= offset; myp[1] -= offset; myp[2] -= offset; myp[3] -= offset; } if (sse->startflag == GRSystemStartEndStruct::OPENLEFT) { myp[0].y = myp[2].y; myp[1].y = myp[3].y; } GRSimpleBeam * tmpbeam = new GRSimpleBeam(this,myp); if( st->simpleBeams == 0 ) st->simpleBeams = new SimpleBeamList(1); st->simpleBeams->AddTail(tmpbeam); pos = sse->startpos; oldpos = pos; first = true; lastLocalDir = localDir; previousBeamsCount = stemNote->getBeamCount() - 1; } // a new hack, again to catch stems directions change - DF sept 15 2009 else if (localDir != dir) { // check for stems length NVPoint stemloc = stemNote->getStemStartPos(); if (tagtype == SYSTEMTAG) stemloc += stemNote->getGRStaff()->getPosition(); int beamscount = stemNote->getBeamCount() - 1; if ((beamscount > 0) && (previousBeamsCount > beamscount) && (lastLocalDir != localDir)) { if (localDir == dirUP) stemNote->changeStemLength(stemNote->getStemLength() + (yLocalFact1 * beamscount)); else if (localDir == dirDOWN) stemNote->changeStemLength(stemNote->getStemLength() - (yLocalFact1 * beamscount)); } } } if (oldpos == sse->endpos) break; } // now we have to make sure, that the original positions // for the beam are set for the right staff if (tagtype == SYSTEMTAG) { const NVPoint &offset = beamstaff->getPosition(); st->p[0] -= offset; st->p[1] -= offset; st->p[2] -= offset; st->p[3] -= offset; } }
void GRGlobalStem::tellPosition(GObject * obj, const NVPoint & pt) { if (error) return; if (dynamic_cast<GRNotationElement *>(obj) == mFirstEl) // useless cast ? { if (mIsSystemCall) { // this is the staff, to which the stem belongs .... const GRStaff * stemstaff = mFirstEl->getGRStaff(); // update the position of the stem and of the flag .... // determine the lowest and highest position ... GRNotationElement * el = mAssociated->GetTail(); NVPoint offset; if (el) { offset = el->getGRStaff()->getPosition(); mLowestY = el->getPosition().y + offset.y; mHighestY = mLowestY; } else { mLowestY = 0; mHighestY = 0; } GuidoPos pos = mAssociated->GetHeadPosition(); while (pos) { GRNotationElement * el = mAssociated->GetNext(pos); if (el && !dynamic_cast<GREmpty *>(el)) { offset = el->getGRStaff()->getPosition(); if (mLowestY > el->getPosition().y + offset.y) mLowestY = el->getPosition().y + offset.y; if (mHighestY < el->getPosition().y + offset.y) mHighestY = el->getPosition().y + offset.y; } } offset = stemstaff->getPosition(); mLowestY -= offset.y; mHighestY -= offset.y; GDirection stemdir = theStem->getStemDir(); // now we have the position of the lowest or highest note ... if (stemdir == dirUP) { theStem->setPosition(NVPoint(0, (GCoord)mHighestY)); } else if (stemdir == dirDOWN) { theStem->setPosition(NVPoint(0, (GCoord)mLowestY)); } // now we have to deal with the length ... if (stemstate && stemstate->getLength()->TagIsSet()) { // we have a length, that was definitly set .... theStem->setStemLength( stemstate->getLength()->getValue()); stemlengthset = true; } else { // length was not set .... const float theLength = (float)(mHighestY - mLowestY + stemstaff->getStaffLSPACE() * 3.5f); theStem->setStemLength(theLength); } // here we have to add the flags ... // theFlag = new GRFlag(this, // dispdur,stemdir,theStem->getStemLength()); if (stemdir == dirUP) { theFlag->setPosition(NVPoint(0, (GCoord)mHighestY)); } else if (stemdir == dirDOWN) { theFlag->setPosition(NVPoint(0, (GCoord)mLowestY)); } GRNotationElement * tmpel = mAssociated->GetHead(); if (tmpel) updateGlobalStem(tmpel->getGRStaff()); } setHPosition(pt.x); } }
void GRGlobalStem::RangeEnd( GRStaff * inStaff) { if (error || mFirstEl == 0) return; GRPTagARNotationElement::RangeEnd(inStaff); if (inStaff == 0) return; GRSystemStartEndStruct * sse = getSystemStartEndStruct(inStaff->getGRSystem()); // this checks, wether all associated elements are // on the same staff. If not, we build a new // GRSystemTag that gets added to the system // so that an update on all positions can be made .... // (this is taken from GRBeam) GuidoPos syststpos = sse->startpos; if (tagtype != GRTag::SYSTEMTAG && syststpos) { // this is all done so that I really get a correct first staff to // test my stuff ... while (syststpos && !/*ynamic_cast<GRNotationElement *>*/(mAssociated->GetAt(syststpos))) { mAssociated->GetNext(syststpos); } // const GRStaff *tststaff = mAssociated->GetNext(syststpos)->getGRStaff(); int tststaffnum = mAssociated->GetNext(syststpos)->getStaffNumber(); while (syststpos) { GRNotationElement * el = mAssociated->GetNext(syststpos); if (el) { if (el->getStaffNumber() != tststaffnum) // el->getGRStaff() != tststaff) { tagtype = GRTag::SYSTEMTAG; GRSystemTag * mysystag = new GRSystemTag(this); // sse->grsystem->addSystemTag(mysystag); el->getGRSystemSlice()->addSystemTag(mysystag); break; } } } } if (tagtype != GRTag::SYSTEMTAG) { // check, whether firstel is on the same staff? if (mFirstEl && mAssociated && mAssociated->GetHead()) { if (mFirstEl->getStaffNumber() != mAssociated->GetHead()->getStaffNumber() ) // getGRStaff() != mAssociated->GetHead()->getGRStaff()) { tagtype = GRTag::SYSTEMTAG; GRSystemTag * mysystag = new GRSystemTag(this); // sse->grsystem->addSystemTag(mysystag); mFirstEl->getGRSystemSlice()->addSystemTag(mysystag); } } } GRNotationElement * el = /*dynamic cast<GRNotationElement *>*/(this); const NEPointerList * associated = el ? el->getAssociations() : 0; if (associated == 0) return; // now I have the associations ... // I have to build the stem .... delete theStem; theStem = new GRStem(this); if (mColRef) theStem->setColRef( mColRef ); // the Vertical position of the Notes that share a stem // must be already set .... // mHighestY = mLowestY = -32767; int highestlowestset = 0; // only if the stemdir has not been set .... if (stemdir == dirOFF) { stemdir = dirUP; if (stemstate) { if (stemstate->getStemState() == ARTStem::UP) { // we have to determine the direction ourselves. stemdir = dirUP; } else if (stemstate->getStemState() == ARTStem::DOWN) { // we have to determine the direction ourselves. stemdir = dirDOWN; } else if (stemstate->getStemState() == ARTStem::OFF) { // we have to determine the direction ourselves. stemdir = dirOFF; } } if ( ( stemstate && stemstate->getStemState() == ARTStem::AUTO ) || !stemstate) { // we have to determine the direction ourselves. // this needs to be done with // the direction of notes ... GCoord middle = 0; int count = 0; // determine the lowest and highest position ... el = associated->GetTail(); if (el) { middle = el->getPosition().y; if (tagtype == GRTag::SYSTEMTAG && el->getGRStaff()) { middle += (GCoord)el->getGRStaff()->getPosition().y; } mHighestY = middle; mLowestY = middle; ++ count; } GuidoPos pos = associated->GetHeadPosition(); while (pos && pos != associated->GetTailPosition()) { GRNotationElement * el = associated->GetNext(pos); if (el && !dynamic_cast<GREmpty *>(el)) { GCoord ypos = el->getPosition().y; if (el->getGRStaff() && tagtype == GRTag::SYSTEMTAG) ypos += el->getGRStaff()->getPosition().y; middle += ypos; ++count ; if (mLowestY > ypos) mLowestY = ypos; if (mHighestY < ypos) mHighestY = ypos; } } highestlowestset = 1; if (count > 0) middle /= count; const float curLSPACE = (float)(inStaff->getStaffLSPACE()); const float mylowesty = 2 * curLSPACE - mLowestY; const float myhighesty = mHighestY - 2 * curLSPACE; if (mylowesty > myhighesty) { stemdir = dirDOWN; } else if (myhighesty > mylowesty) stemdir = dirUP; else { if (middle >= curLSPACE * 2) { stemdir = dirUP; } else if (middle < curLSPACE * 2) { stemdir = dirDOWN; } } } } if (dispdur >= DURATION_1) { stemdir = dirOFF; } theStem->setStemDir(stemdir); // otherwise it has been set because of auto-stem. if (!highestlowestset) { // determine the lowest and highest position ... el = associated->GetTail(); if (el) { mLowestY = el->getPosition().y; if (tagtype == GRTag::SYSTEMTAG && el->getGRStaff()) { mLowestY += el->getGRStaff()->getPosition().y; } mHighestY = mLowestY; } GuidoPos pos = associated->GetHeadPosition(); while (pos) { GRNotationElement * el = associated->GetNext(pos); if (el && !dynamic_cast<GREmpty *>(el)) { NVPoint elpos (el->getPosition()); if (tagtype == GRTag::SYSTEMTAG && el->getGRStaff()) { elpos += el->getGRStaff()->getPosition(); } if (mLowestY > elpos.y) mLowestY = elpos.y; if (mHighestY < elpos.y) mHighestY = elpos.y; } } } // now we have the position of the lowest or highest note ... if (stemdir == dirUP) { theStem->setPosition(NVPoint(0, (GCoord)mHighestY)); } else if (stemdir == dirDOWN) { theStem->setPosition(NVPoint(0, (GCoord)mLowestY)); } // now we have to deal with the length... const TagParameterFloat * taglength = 0; if (stemstate) taglength = stemstate->getLength(); if (stemstate && taglength && taglength->TagIsSet()) { // we have a length, that was definitly set... theStem->setStemLength((float)(stemstate->getLength()->getValue())); stemlengthset = true; } else { // length was not set .... float length = (float)(mHighestY - mLowestY + inStaff->getStaffLSPACE() * 3.5f * mTagSize); theStem->setStemLength( length ); } delete theFlag; // here we have to add the flags ... theFlag = new GRFlag(this, dispdur,stemdir,theStem->getStemLength()); if (mColRef) theFlag->setColRef(mColRef); if (!mFlagOnOff) theFlag->setFlagOnOff(mFlagOnOff); if (stemdir == dirUP) { theFlag->setPosition(NVPoint(0, (GCoord)mHighestY)); } else if (stemdir == dirDOWN) { theFlag->setPosition(NVPoint(0, (GCoord)mLowestY)); } if (tagtype != GRTag::SYSTEMTAG) updateGlobalStem(inStaff); }