Ejemplo n.º 1
0
/** \brief Gets another spring and then figures out, how much distance
	should be put inbetween this spring and nextspring. 
	
	It looks at GRSpringCollider to find those areas, where a collision
	might (or does) occur.
*/
float GRSpring::GetMaxDistance(GRSpring * nextspring)
{
	if (this->hasType(typeid(GRGlue)))
	{
		// the first spring is a glue-spring.
		// then we just need the maximum leftspace
		// of the second spring and thats it ...
		float max = 0;
		GuidoPos pos = nextspring->grolst.GetHeadPosition();
		while (pos)
		{
			GRNotationElement * el = nextspring->grolst.GetNext(pos);
			if (el->getLeftSpace() > max)
				max = el->getLeftSpace();
		}
		return max;
	}
	if (nextspring->hasType(typeid(GRGlue)))
	{
		// then the next is a glue, then we just need the maxrightspace
		// of this spring ....
		float max = 0;
		GuidoPos pos = grolst.GetHeadPosition();
		while (pos)
		{
			GRNotationElement * el = grolst.GetNext(pos);
			if (el->getRightSpace() > max)
				max = el->getRightSpace();
		}
		return max;
	}

	float maxright = 0;
	float maxleft = 0;
	float max = 0;
	int count = KF_VECTOR_MININDEX;
	if (sprcol && nextspring && nextspring->sprcol)
	{
		poslist * pl1 = NULL;
		poslist * pl2 = NULL;
		bool cont = true;
		do
		{
			maxright = maxleft = 0;
			sprcol->GetMatchingPoslists(count,nextspring->sprcol, &pl1, &pl2);
			if (pl1 && pl2)
			{
				// I have matching poslists ....
				GuidoPos pospl1 = pl1->GetHeadPosition();
				while (pospl1)
				{
					GuidoPos evpos = pl1->GetNext(pospl1);
					GRNotationElement * el = grolst.GetAt(evpos);
					if (el->getRightSpace() > maxright)
						maxright = el->getRightSpace();

				}
				GuidoPos pospl2 = pl2->GetHeadPosition();
				while (pospl2)
				{
					GuidoPos evpos = pl2->GetNext(pospl2);
					GRNotationElement * el = nextspring->grolst.GetAt(evpos);
					if (el->getLeftSpace() > maxleft)
						maxleft = el->getLeftSpace();
				}
			}
			if (count==KF_VECTOR_MININDEX) 
				cont = false;
			if (maxright + maxleft > max)
				max = maxright + maxleft;
		} 
		while (cont);
	}
	return max;
}
Ejemplo n.º 2
0
/** \brief Called just as createNewRods is called
	It updates the QP-Matrix for minimizing the Spring-
	energy. This is a first prototype.
*/
int GRVoice::updateMSCMatrix(GRSpaceForceFunction2 * sff,
							 GRSpacingMatrix * spm,
							 GRStaffManager * stfmgr,
							 ISpringVector * sprvect,
							int startspr, int endspr )
{
	double * mat = spm->getMSCMatrix();
	int n = spm->getMSCMatrixMemSize();

	// now even newer stuff; we distinguish between different
	// phases:
	// first voice just sets the maximum value for each spring
	// (this is the regular gourlay model)
	// we also take care of "neighbourhoods", telling the
	// SpacingMatrix, where same-notedurations occur.

	// this setting just remembers if it is the first run ....
	// for the first run, there must be a special handling (remembering
	// the first rod)
	//	int beginsAtHead = 0;
	GuidoPos pos;
	if (lastsprpos == NULL)
	{
		// there has been no previous rod, that
		// is there has been no element in this
		// voice yet, that is attached to a
		// string.
		if (mIsNewLine)
		{
			// then, there has been no element 
			// added yet!
			return -1;
		}
		pos = firstPositionInLine;
		//		beginsAtHead = 1;
	}
	else
	{
		// iterate to the next element....
		pos = lastsprpos;
		GetNext(pos);
	}
	
	GRNotationElement * el = NULL; 

	double prevvalue = 0;
	int   prevstartid = -1;
//	int   numneighbours = 0;

	KF_List<int> * neighbourlist = 0;
	while (pos)
	{
		el = GetNext(pos);
			
		// does this element have a spring;
		// if not, than there can't be a rod attached to it.
		if (!el->getNeedsSpring())
			continue;
		
		int start; // the spring where the current element starts
		int end; // the spring where the current element ends
		
		// this is done, as long as the NEXT element needs a spring ...
		while (pos)
		{
			GRNotationElement * next = GetCompositeElements().GetAt( pos );
			
			if (!next->getNeedsSpring())
			{
				GetNext(pos);
				continue;
			}
			
			start = el->getSpringID();

			end = next->getSpringID();

			// now we just determine the necessary value, depending
			// on duration alone ...
			float value = 0; 
			
			const TYPE_DURATION durel (el->getDuration());
//			const TYPE_DURATION &durnext = next->getDuration();
			
			if (durel > DURATION_0)
			{
				value = 1.0f / (float) durel;
				
				// now we fill the second entry in the msc-matrix
				// this is needed, so that we can make sure, that
				// spacing is somewhat controlled, when NO groups
				// have been found.
				
				// this is equivalent to the stuff that was calculated
				// before (see below)
				int cnt;
				for (cnt=start;cnt<end;cnt++)
				{	
					if (value > *(mat + cnt + n*3))
					{
						*(mat + cnt + n*3) = value;
					} 
				}
				
				if (prevvalue == value)
				{
					if (!neighbourlist)
					{
						neighbourlist = new KF_List<int>();
						neighbourlist->AddTail(prevstartid);
					}
					// then we have a neighboor 
					neighbourlist->AddTail(start);
				}
				else
				{
					if (neighbourlist)
					{
						neighbourlist->AddTail(start);
						spm->AddNeighbourList(neighbourlist);
						neighbourlist = NULL;
					}
					// then we just start a new group ...
				}
			}
			else
			{
				if (neighbourlist)
				{
					neighbourlist->AddTail(start);
					spm->AddNeighbourList(neighbourlist);
					neighbourlist = NULL;
				}
			}				
			
			// this means we are finished with finding the next event
			el = NULL;
			if (durel <= DURATION_4)
				prevvalue = value;
			else 
				prevvalue = -1.0f;

			prevstartid = start;
			
			break;
		}
	}

	if (el && el->getNeedsSpring())
	{
		int start;
		int end;
		
		start = el->getSpringID();
		end = endspr;
		
		//float mysconst = GRSpring::onlycalcconst(el);
		
		float value = 0; // mysconst;
		
		const TYPE_DURATION durel (el->getDuration());
		if (durel > DURATION_0)
		{
			value = 1.0f / (float) durel;
			
			int i;
			for (i=start;i<end;i++)
			{	
				if (value > *(mat + i + n*3))
				{
					*(mat + i + n*3) = value;
				}
			}
			// check for neighbours ....

			// maybe this is a hack, but one that makes sense:
			// neighbourhood is only important for durations of up to
			// a quarter note.

				if (prevvalue == value)
				{
					if (!neighbourlist)
					{
						neighbourlist = new KF_List<int>();
						neighbourlist->AddTail(prevstartid);
					}
					// then we have a neighboor 
					neighbourlist->AddTail(start);
					neighbourlist->AddTail(endspr);
					
					spm->AddNeighbourList(neighbourlist);
					neighbourlist = NULL;
				}
		}
		if (neighbourlist)
		{
			// the last element was not a neighbour 
			neighbourlist->AddTail(start);

			spm->AddNeighbourList(neighbourlist);
			neighbourlist = NULL;
		}
	}

	// if i have a neighbourlist that is still open, something 
	// went a little wrong?
	if (neighbourlist)
	{
		assert(false);
		neighbourlist->AddTail(endspr-1);
		spm->AddNeighbourList(neighbourlist);
		neighbourlist = NULL;
	}
	return 0;
}
Ejemplo n.º 3
0
/** \brief Creates all rods from the startspr until the endspr. 

It is called by the StaffManager (BuildSPF)
we have to make sure that firstrod and
lastrod is created correctly.
We do not need to take care of rods with
starting positions that are smaller than startspr
*/
int GRVoice::createNewRods(GRStaffManager * stfmgr, int & startspr, int & endspr)
{
	if (lastrod)
	{
		// so the calling function knows,
		// where the restretching must start.

		assert(lastrod->mSpr2 == startspr);

		// startspr = lastrod->spr1;

		// this removes the rod from the rod-list.
		// it is done, because the lastrod was 
		// a connection to the end, which is now
		// moved further....
		// no, no longer removal
		// stfmgr->deleteRod(lastrod);

		// this sets the startspr, so the staffmgr
		// knows, which offset needs to be restrechted.

		// will be really deleted by owner
		// (stfmgr or grsystem).
		lastrod = NULL;
	}

	if (firstrod)
	{
		// old firstrod ...
		// will be deleted by real owner ...
		// (which is stfmgr or grsystem)
		
		firstrod = NULL;
	}

	// this setting just remembers, if it is the first run ....
	// for the first run, there must be a special handling (remembering
	// the first rod position)
	GuidoPos pos;
	if (lastsprpos == NULL)
	{
		// there has been no previous rod, that
		// is there has been no element in this
		// voice yet, that is attached to a string.
		if (mIsNewLine)
		{
			// then, there has been no element 
			// added yet!
			return -1;
		}
		pos = firstPositionInLine;
	}
	else
	{
		// iterate to the next element....
		pos = lastsprpos;
		GetNext(pos);
	}

	GRNotationElement * el = 0; 
	float spacedistance = 0;
	bool spaceactive = false;

	while (pos)
	{
		lastsprpos = pos;
		el = GetNext( pos );

		// is this element a Space-Tag?
		GRSpace * spc = dynamic_cast<GRSpace *>(el);
		if (spc)
		{
			// this can only happen, if we are at the very start ..
			assert(!firstrod);
			spacedistance += spc->getARSpace()->getValue();
			spaceactive = true;
		}

		// does this element have a spring;
		// if not, than there can't be a rod
		// attached to it.
		if (!el->getNeedsSpring())
		{
			continue;
		}

		// if (beginsAtHead)
		// {

		if (!firstrod)
		{
			GRRod * rod;
			// this may need to change, so that
			// glue- elements get a chance as  well ...
			// maybe we have to create another rod somewhere ?
			// not only the glue, but this MUST
			// be the distance of the last element ....
			// otherwise, we do not get enough space ...
			float dist = (LSPACE * 0.5f);
			if (dynamic_cast<GRClef*>(el))
			{
				dist = 50; // the same as the begin glue
							// this is a wild hack ...
			}

			rod = new GRRod(
				dist + el->getLeftSpace(),
				el->getSpringID()-1,el->getSpringID());

			if (spaceactive)
			{
				// the space at the beginning is ignored completely. 
				// in the case of merging, the firstrod is removed,
				// otherwise, it is just  the regular space needed
				// in the case of no space-tag  at all.

				// old:
				// the space has been taken care of before (hopefully)
				// (if this is called in reaction to pbreak ...)
				spaceactive = 0;
				spacedistance = 0;				

				// space-active....
				rod->setIsSpaceRod( true );
				stfmgr->addRod(rod,1);
			}
			else
			{
				stfmgr->addRod(rod,0);
			}

			if (rod->getSpr1() < startspr)
				startspr = rod->getSpr1();

			// the very first rod is a copy of the one added to the stfmgr.
			firstrod = rod;
		}


		// this is done, as long as the NEXT
		// element needs a spring ...
		while (pos)
		{
			GRNotationElement * next = GetCompositeElements().GetAt(pos);

			GRSpace * spc = dynamic_cast<GRSpace *>(next);
			if (spc)
			{
				// then this element is a space-tag ...
				// all between is added ...
				spacedistance += spc->getARSpace()->getValue();
				spaceactive = true;
			}
			if (!next->getNeedsSpring())
			{
				GetNext(pos);
				continue;
			}
			// it needs a spring. Now we add a Rod ...
			GRRod * rod = 0;
			if (spaceactive)
			{
				rod = new GRRod( el, next, 0, spacedistance );
				rod->setIsSpaceRod( true );
				spaceactive = false;
				spacedistance = 0;
				// spaceactive!
				stfmgr->addRod( rod,1 );
			}
			else
			{
				rod = new GRRod( el, next, 0 );
				// no space active
				stfmgr->addRod(rod,0);
			}

			if( rod->getSpr1() < startspr )
				startspr = rod->getSpr1();

			lastrod = rod;

			// finish the inner cycle
			break;


		} // while (pos);

		// if we are moved out 


	} // while (pos);

	// there is an element ...
	// then we need to add a Rod from this 
	// to the end. This rod is going to
	// be the lastrod ...
	if (el && el->getNeedsSpring())
	{
		GRRod * rod;
		if (spaceactive)
		{
			// the rod is of the length of 
			// the following space tag...
			rod = new GRRod( spacedistance, el->getSpringID(), endspr );
			rod->setIsSpaceRod( true );

			// space active!
			stfmgr->addRod(rod,1);
		}
		else
		{
			rod = new GRRod(el->getRightSpace(), el->getSpringID(),endspr);
			// no space active
			stfmgr->addRod(rod,0);
		}

		if (rod->getSpr1() < startspr)
			startspr = rod->getSpr1();
		lastrod = rod;
	}

	return 0;
}
Ejemplo n.º 4
0
/** \brief cthis routine is called just as createNewRods is called
	It updates the QP-Matrix for minimizing the Spring-
	energy. This is a first prototype ...
*/
int GRVoice::updateQPMatrix(GRSpaceForceFunction * spf,
							ISpringVector * sprvect,
							int startspr, int endspr)
{
	double * mat = spf->getMatrix();
	int n = spf->getMatrixMemSize();

	int firstrun = 1;

	// this setting just remembers, if it is the first run ....
	// for the first run, there must
	// be a special handling (remembering the first rod)
//	int beginsAtHead = 0;
	GuidoPos pos;
	if (lastsprpos == NULL)
	{
		// there has been no previous rod, that
		// is there has been no element in this
		// voice yet, that is attached to a string.
		if (mIsNewLine)
		{
			// then, there has been no element 
			// added yet!
			return -1;
		}
		pos = firstPositionInLine;
//		beginsAtHead = 1;
	}
	else
	{
		// iterate to the next element....
		pos = lastsprpos;
		elements->GetNext(pos);
	}

	GRNotationElement * el = NULL; 
	float spacedistance = 0;
	bool spaceactive = false;

	while (pos)
	{

		el = elements->GetNext(pos);


		// is this element a Space-Tag?
		GRSpace * spc = dynamic_cast<GRSpace *>(el);
		if (spc)
		{
			spacedistance += spc->getARSpace()->getValue();
			spaceactive = true;
		}

		// does this element have a spring;
		// if not, than there can't be a rod attached to it.
		if (!el->getNeedsSpring())
		{
			continue;
		}

		// if (beginsAtHead)
		// {

		int start; // the spring where the current element starts
		int end; // the spring where the current element ends


		// this is done, as long as the NEXT
		// element needs a spring ...
		while (pos)
		{
			GRNotationElement * next = elements->GetAt(pos);

			GRSpace * spc = dynamic_cast<GRSpace *>(next);
			if (spc)
			{
				// then this element is a space-tag ...
				// all between is added ...
				spacedistance += spc->getARSpace()->getValue();
				spaceactive = true;
			}
			if (!next->getNeedsSpring())
			{
				elements->GetNext(pos);
				continue;
			}

			start = el->getSpringID();
			end = next->getSpringID();

			// then we need the "real" constant:

			float mysconst = GRSpring::onlycalcconst(el);

				// complex-rod ...
				int i,j;
				for (i=start;i<end;i++)
				{	
//					*(mat+i + n*i) += 0.5*mysconst;

					/* This version is one, which works
					   only with added constraints
					   (equality of subgroups in one voice
					   not yet clear, how to to this automatically
					   */
					for (j=i;j<end;j++)
					{
						*(mat + i + n*j) += 0.5*mysconst;

					}
				} 

			// it needs a spring. Now we add a Rod ...
			if (spaceactive)
			{

				spf->addConstraint(start,end,spacedistance);

				//rod = new GRRod(el,next,0,spacedistance);
				//rod->setIsSpaceRod(true);
				spaceactive = false;
				spacedistance = 0;
				// spaceactive!
				// stfmgr->addRod(rod,1);
			}
			else
			{
				double length = el->getRightSpace() + next->getLeftSpace();
				spf->addConstraint(start,end,length);
				// rod = new GRRod(el,next,0);
				// no space active
				// stfmgr->addRod(rod,0);
			}

			// finish the inner cycle
			break;

		} // while (pos);

		// if we are moved out 

	} // while (pos);

	// there is an element ...
	// then we need to add a Rod from this 
	// to the end. This rod is going to
	// be the lastrod ...
	if (el && el->getNeedsSpring())
	{
		int start;
		int end;

		start = el->getSpringID();
		end = endspr;

			float mysconst = GRSpring::onlycalcconst(el);

				// complex-rod ...
				int i,j;
				for (i=start;i<end;i++)
				{	
//					*(mat + i + n*i) += mysconst;
					for (j=start; j<end; j++)
					{
						*(mat+ i + n*j)+= 0.5 * mysconst;
					}
				}
			// }

		if (spaceactive)
		{
			spf->addConstraint(start,end,spacedistance);
			// the rod is of the length of 
			// the following space tag...
			//rod = new GRRod(spacedistance,
			//	el->getSpringID(),endspr);
			//rod->setIsSpaceRod(true);

			// space active!
			//stfmgr->addRod(rod,true);
		}
		else
		{
				double length = el->getRightSpace();
				spf->addConstraint(start,end,length);
			//rod = new GRRod(el->getRightSpace(),
			//	el->getSpringID(),endspr);
			// no space active
			//stfmgr->addRod(rod,0);
		}

	}
	return 0;
}
Ejemplo n.º 5
0
/** \brief Called just as createNewRods is called.

	It updates the QP-Matrix for minimizing the Spring-
	 energy. This is a first prototype.
*/
int GRVoice::updateMSCMatrix( GRSpaceForceFunction * spf,
							int startspr,int endspr)
{
	double * mat = spf->getMSCMatrix();
	int n = spf->getMSCMatrixMemSize();
	
	// this setting just remembers,
	// if it is the first run ....
	// for the first run, there must
	// be a special handling (remembering
	// the first rod)
	//	int beginsAtHead = 0;
	GuidoPos pos;
	if (lastsprpos == NULL)
	{
		// there has been no previous rod, that
		// is there has been no element in this
		// voice yet, that is attached to a
		// string.
		if (mIsNewLine)
		{
			// then, there has been no element 
			// added yet!
			return -1;
		}
		pos = firstPositionInLine;
		//		beginsAtHead = 1;
	}
	else
	{
		// iterate to the next element....
		pos = lastsprpos;
		elements->GetNext(pos);
	}
	
	GRNotationElement * el = NULL; 

	while (pos)
	{
		el = elements->GetNext(pos);

		// does this element have a spring;
		// if not, than there can't be a rod attached to it.
		if (!el->getNeedsSpring())
		{
			continue;
		}
		
		// if (beginsAtHead)
		// {
		
		int start; // the spring where the current element starts
		int end; // the spring where the current element ends
		
		// this is done, as long as the NEXT element needs a spring ...
		while (pos)
		{
			GRNotationElement * next = elements->GetAt(pos);
			if (!next->getNeedsSpring())
			{
				elements->GetNext(pos);
				continue;
			}
			
			start = el->getSpringID();
			end = next->getSpringID();
			
			// then we need the "real" constant:
			
			//float mysconst = GRSpring::onlycalcconst(el);
			
			double value = 0; // mysconst;
			
			const TYPE_DURATION & durel (el->getDuration());
			
			if (durel > DURATION_0)
			{
				value = 1.0 / (float) durel;
			}

			int i;
			for (i=start;i<end;i++)
			{
				if (value > *(mat + i + n*0))
				{
					*(mat + i + n*0) = value;
					*(mat + i + n*1) = durel.getNumerator();
					*(mat + i + n*2) = durel.getDenominator();
				}
			}
			
			// finish the inner cycle
			break;
			
		} // while (pos);
		
		// if we are moved out 
		
		
	} // while (pos);
	
	// there is an element ...
	// then we need to add a Rod from this 
	// to the end. This rod is going to
	// be the lastrod ...
	if (el && el->getNeedsSpring())
	{
		int start;
		int end;
		
		start = el->getSpringID();
		end = endspr;
		
		float mysconst = GRSpring::onlycalcconst(el);
		
		double value = mysconst;
		
		const TYPE_DURATION & durel (el->getDuration());
		if (durel > DURATION_0)
		{
			value = (1.0 / value) / durel;
		}
		int i;
		for (i=start;i<end;i++)
		{	
			if (value > *(mat + i + n*0))
				{
					*(mat + i + n*0) = value;
					*(mat + i + n*1) = durel.getNumerator();
					*(mat + i + n*2) = durel.getDenominator();
				}
			
		}
	}

	return 0;
}
Ejemplo n.º 6
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);
		}
	}
}
Ejemplo n.º 7
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;
	}
}
Ejemplo n.º 8
0
void GRBeam::RangeEnd(GRStaff * grstaff)
{
	assert(grstaff);

	GRPositionTag::RangeEnd(grstaff);

	if (error) return;
	if (!mAssociated) return;
	
	GRSystemStartEndStruct * sse = getSystemStartEndStruct(grstaff->getGRSystem());
	assert(sse);

	if (mAssociated && (mAssociated->GetCount() == 1) && isAutoBeam())
	{
		GREvent * ev = GREvent::cast(mAssociated->GetHead());
		if (ev)
		{
			ev->setFlagOnOff(true);
			ev->decBeamCount();
			if (sse->startElement)	// something did not work, if the starElement is a glue ... and not an event
				ev->removeAssociation(this);
			if (sse->endElement)
				ev->removeAssociation(this);
		}
		return;
	}

	GREvent * grn;
	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 && !(mAssociated->GetAt(syststpos)))
		{
			mAssociated->GetNext(syststpos);
		}
		int tststaffnum = mAssociated->GetNext(syststpos)->getStaffNumber(); 
		while (syststpos)
		{
			GRNotationElement * el = mAssociated->GetNext(syststpos);
			if (el)
			{
				if (el->getStaffNumber() != tststaffnum)
				{
					tagtype = GRTag::SYSTEMTAG;
					GRSystemTag * mysystag = new GRSystemTag(this);
					el->getGRSystemSlice()->addSystemTag(mysystag);
					break;
				}
			}		
		}
	}

	GuidoPos pos = sse->startpos;
	GRBeamSaveStruct * st = (GRBeamSaveStruct *) sse->p;
	bool first = true;

	GDirection mytmpdir = dirOFF;
	while (pos)
	{
		grn = GREvent::cast(mAssociated->GetNext(pos));
		if (grn)
		{
			if (!st->dirset)
			{
				if (first)
				{
					// get the stemdir of the first !? maybe it now has been set?
					mytmpdir = grn->getStemDirection();
				}
				if (mytmpdir != dirOFF)
					grn->setStemDirection(mytmpdir);
				else if (st->direction>=0)
					grn->setStemDirection(dirUP);
				else
					grn->setStemDirection(dirDOWN);
			}
			grn->setFlagOnOff(false);
			first = false;
		}
	}
}
Ejemplo n.º 9
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;
	}
}
Ejemplo n.º 10
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);
	}
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
0
// ----------------------------------------------------------------------------
void 
GRTuplet::manualPosition(GObject * caller, const NVPoint & inPos )
{
	GREvent * event = GREvent::cast( caller );
	if( event == 0 ) return;

	GRStaff * staff = event->getGRStaff();
	if( staff == 0 ) return;

	GRSystemStartEndStruct * sse = getSystemStartEndStruct(staff->getGRSystem());
	if( sse == 0 ) return;

	GRNotationElement * startElement = sse->startElement;
	GRNotationElement * endElement = sse->endElement;

	// if ( openLeftRange && openRightRange ) return;

	GRTupletSaveStruct * st = (GRTupletSaveStruct *)sse->p;

	const ARTuplet * arTuplet = getARTuplet();

	float dy1 = arTuplet->isDySet() ? arTuplet->getDy1() : 0;
	float dy2 = arTuplet->isDySet() ? arTuplet->getDy2() : 0;

	if(( dy1 > 0 ) || ( dy2 > 0 ))
		mDirection = dirUP;

	const float halfNoteWidth = LSPACE * float(0.65); // harcoded
	if (event == startElement)
	{
		st->p1 = startElement->getPosition();		
		st->p1.x -= halfNoteWidth; // to enclose all the element width
		st->p1.y -= dy1;
	}
	else if (event == endElement)
	{
		st->p2 = endElement->getPosition();
		st->p2.x += halfNoteWidth; // to enclose all the element width
		st->p2.y -= dy2;
	}
	
	if(event == endElement || (endElement == 0 && event == startElement))
	{
		if (startElement && endElement)
		{
			const float posx = (st->p2.x - st->p1.x) * 0.5f + st->p1.x;
            const float posy = st->p2.y > st->p1.y ? (st->p2.y - st->p1.y) * 0.5f + st->p1.y + 40 : (st->p1.y - st->p2.y) * 0.5f + st->p2.y + 40;
		
			st->textpos.x = posx;
            st->textpos.y = posy;
		}
		else
			st->textpos = inPos;
	}

//	if( arTuplet->isFormatSet())
//	{
		mShowLeftBrace = arTuplet->getLeftBrace();
		mShowRightBrace = arTuplet->getRightBrace();
//	}

}