示例#1
0
/** \brief Returns a page corresponding to a time position.

	It finds the musical element which time position is immediately before or equal to
	the input time position. Then it returns the page of that musical element.

	getPageForTimePos() always try to return a page, while getPageNum() only returns
	a page when the input time position match the time position of an existing
	musical element.

	TODO: Check if the page keeps track of both its start timepos and end timepos,
			therefore we could directly jump from one page to another


	\bug The last system of a page point to the next page instead of its parent page.

*/
GRPage * GRVoice::getPageForTimePos( int num, int denom ) const
{
    GRPage * outPage = 0;
    TYPE_TIMEPOSITION inTime ( num, denom );
    GuidoPos pos = First();

    // - Find the event which best match the input date
    GREvent * bestEv = 0;
    while (pos)
    {
        GRNotationElement * el = GetNext(pos);
        GREvent * ev = GREvent::cast(el);
        if( ev )
        {
            const TYPE_TIMEPOSITION & currTime = ev->getRelativeTimePosition();
            if( currTime <= inTime )
                bestEv = ev;
            else
                break;	// (JB) I suppose that all next elements have a greater time pos.
        }
    }

    // - Get the page corresponding to the event found

    if( bestEv )
    {
        GRStaff * staff = bestEv->getGRStaff();
        GRSystem * sys = staff->getGRSystem();
        outPage = sys->getGRPage();
    }

    return outPage;
}
示例#2
0
GRPage * GRVoice::getPageNum(int num,int denom)
{
    // I have to travers the voice and find the element
    // at the position num/denom. Then I have to find the
    // pagenumber of that element.

    const TYPE_TIMEPOSITION tpsearch ( num,denom );
    GuidoPos pos = First();
    while (pos)
    {
        GRNotationElement * el = GetNext(pos);
        GREvent * ev = GREvent::cast(el);
        if (ev)
        {
            if (ev->getRelativeTimePosition() == tpsearch)
            {
                GRStaff * stf = ev->getGRStaff();
                GRSystem * sys = stf->getGRSystem();
                GRPage * page = sys->getGRPage();
                return page;
            }
            else if (ev->getRelativeTimePosition() > tpsearch)
                return NULL;
        }
    }
    return NULL;
}
示例#3
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);
}
示例#4
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 );
	}
}
示例#5
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();
//	}

}
示例#6
0
/** Places the tuplet bracket and/or numeral, close to its group of notes.

	Calculates the positions of the two possible tuplet bracket (above 
	 and below) then choose the best one.

*/
void  GRTuplet::automaticPosition(GObject * caller, const NVPoint & inPos )
{
	GREvent * callerEv = GREvent::cast( caller );
	if( callerEv == 0 ) return;

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

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

	GRTupletSaveStruct * st = (GRTupletSaveStruct *)sse->p;
	if( st == 0 ) return;

	GREvent * startElement = GREvent::cast( sse->startElement );
	if( startElement == 0 ) return;

	GREvent * endElement = GREvent::cast( sse->endElement );
	if( endElement == 0 ) return;

	// - Accept being positioned only once, if possible by the last tuplet element.
	//if(( callerEv != endElement ) && ((callerEv != startElement) || (endElement != 0)))
	if( callerEv != endElement )
		return;
	
	// - Check for beams
	const bool firstBeamed = (startElement->getBeamCount() > 0);
	const bool lastBeamed = (endElement->getBeamCount() > 0);

	mShowLeftBrace = !(firstBeamed && lastBeamed );
	mShowRightBrace = mShowLeftBrace;

	// - Get first and last element positions to work with
	float startX, endX;
	endX = 0;
	float startUpY, startDownY, endUpY, endDownY;

		// x positions
	const float halfNoteWidth = LSPACE * float(0.65); // harcoded
	startX = startElement->getPosition().x;
	endX = endElement->getPosition().x;

//	if( endX == startX ) return;		// DF commented: results in strange vertical bars

	startX -= halfNoteWidth;
	endX += halfNoteWidth;
		
		// y positions
	const NVRect & leftBox = startElement->getBoundingBox();
	const NVRect & rightBox = endElement->getBoundingBox();
	const float elPos1y = startElement->getPosition().y;
	const float elPos2y = endElement->getPosition().y;

	startUpY = leftBox.top + elPos1y;
	endUpY = rightBox.top + elPos2y;

	startDownY = leftBox.bottom + elPos1y;
	endDownY = rightBox.bottom + elPos2y;

	// - Calculate a virtual line from the first to the last element,
	
	int stemStats = 0;
	const float deltaX = (endX - startX);

	float slopeUp = (endUpY - startUpY) / deltaX; // slope of the virtal line above
	float slopeDown = (endDownY - startDownY) / deltaX; // slope of the virtal line below

	float x, yUp, yDown, distUp, distDown;
	float mxUp = 0, myUp = 0, mxDown = 0, myDown = 0;	// 'extreme' middle point
	bool collideUp = false;
	bool collideDown = false;

	GuidoPos pos = mAssociated->GetHeadPosition();
	while( pos )
	{
		GREvent * el = GREvent::cast( mAssociated->GetNext(pos));
		if( el == 0 ) continue;

		// - Generate stats about stem directions
		GDirection stemDir = el->getStemDirection();
		if( stemDir == dirUP ) ++ stemStats;
		else if( stemDir == dirDOWN ) -- stemStats; 
		
		if(( el != startElement ) && ( el != endElement ))
		{
			// - Get the element box
			const NVRect & elBox = el->getBoundingBox();
			const NVPoint & elPos = el->getPosition();
			
			x = elPos.x;
			yUp = elBox.top + elPos.y;
			yDown = elBox.bottom + elPos.y;
			
			// - Calculate the y-distance between the element and the virtual line.
			// distY = startY - (y - slope * (x - startX)); 

			distUp = (startUpY - yUp) + (x - startX) * slopeUp;
			distDown = (startDownY - yDown) + (x - startX) * slopeDown;

			if( distUp > 0 )	// then the point is above the virtual line
			{
				mxUp = x;
				myUp = yUp; 
				collideUp = true;
				//startUpY -= distUp;	// TODO: better handling of this collision
				//endUpY -= distUp;
			}
		
			if( distDown < 0 )	// then the point is below the virtual line
			{
				mxDown = x;
				myDown = yDown; 
				collideDown = true;
				//startDownY -= distDown;
				//endDownY -= distDown;
			}
		}
	}

	// - Adjust the brace to avoid collisions. It must be above (or below) all elements, 
	// while remaining close to those elements, and avoid being in the staff.
	// brace 1 (upward)
	if( collideUp )
	{
		if(( myUp <= startUpY ) && ( myUp <= endUpY ))	// middle point above start and end points
		{
			// slopeUp = 0; // horizontal
			startUpY = myUp;
			endUpY = myUp;
		}
		else	
		{
			if( myUp <= endUpY ) // middle point above end point only: shift the end point up
			{
				slopeUp = (myUp - startUpY) / (mxUp - startX);
				endUpY = startUpY + (deltaX * slopeUp);
			}
			else // middle point above start point only: shift the start point up
			{
				slopeUp = (endUpY - myUp) / (endX - mxUp);
				startUpY = endUpY - (deltaX * slopeUp);
			}
		}
	}

	// brace 2 (downward)
	if( collideDown )
	{
		if(( myDown >= startDownY ) && ( myDown >= endDownY )) // middle point below start and end points
		{
			// slopeDown = 0; // horizontal
			startDownY = myDown;
			endDownY = myDown;
		}
		else
		{
			if( myDown >= endDownY ) // middle point below end point only: shift the end point down
			{
				slopeDown = (myDown - startDownY) / (mxDown - startX);
				endDownY = startDownY + (deltaX * slopeDown);
			}
			else // middle point below start point only: shift the start point down
			{
				slopeDown = (endDownY - myDown) / (endX - mxDown);
				startDownY = endDownY - (deltaX * slopeDown);
			}
		}
	}

	// - Avoid being inside staff
	if( startUpY > 0 )	startUpY = 0;	
	if( endUpY > 0 )	endUpY = 0;	

	const float staffHeight = staff->getDredgeSize();
	if( startDownY < staffHeight )	startDownY = staffHeight;	
	if( endDownY < staffHeight )	endDownY = staffHeight;	

	// - Tune
	float marginY = LSPACE * float(1.25);

	startUpY -= marginY;
	endUpY -= marginY;
	
	startDownY += marginY;
	endDownY += marginY;

	// - Choose the best solution (above or below)
	// We put the brace and the tuplet numeral on the stem side.

	float startY;
	float endY;
	
	if( stemStats >= 0 ) // stems tend to be up.
	{
		mDirection = dirUP;
		startY = startUpY;
		endY = endUpY;
	}
	else
	{
		mDirection = dirDOWN;
		startY = startDownY;
		endY = endDownY;
	}

	// - Store results
	const float textOffsetY = LSPACE;

	st->p1.x = startX;
	st->p1.y = startY;
	st->p2.x = endX;
	st->p2.y = endY;

	st->textpos.x = (startX + endX) * float(0.5);
	st->textpos.y = (startY + endY) * float(0.5) + textOffsetY - 9;
}