Пример #1
0
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);
}
Пример #2
0
// -----------------------------------------------------------------------------
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 );
	}
}
Пример #3
0
// (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;
	}
}
Пример #4
0
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);
		}
	}
}
Пример #5
0
// (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;
	}
}
Пример #6
0
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);
	}
}
Пример #7
0
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);
}