Esempio n. 1
0
bool Playback::Order::Prev( int & iCur, int iMax )
{
	switch( iCurOrder )
	{
	case ORDER_SINGLE:          return false;
	case ORDER_SINGLE_REPEAT:   return true;
	case ORDER_NORMAL:          return NextInverse( iCur, iMax );
	case ORDER_NORMAL_REPEAT:   return NextInverseRepeat( iCur, iMax );
	case ORDER_INVERSE:         return NextNormal( iCur, iMax );
	case ORDER_INVERSE_REPEAT:  return NextNormalRepeat( iCur, iMax );
	case ORDER_RANDOM:          return NextRandom( iCur, iMax );
	default:                    return false;
	}
}
Esempio n. 2
0
BOOL TrapEdgeList::ProcessEdgeNormals(ProcessPathToTrapezoids *pProcessor)
{
	if (Used < 2)							// Sanity check
	{
		ERROR3("Not enough coordinates in trapezoid list!");
		return(FALSE);
	}

	TrapEdge *pPrevEdge	= NULL;
	TrapEdge *pEdge		= NULL;
	NormCoord PrevNormal(1.0, 0.0);
	BOOL CompletingAMitre = FALSE;

	// --- First, scan the trapezoid list, and calculate the normal of each edge
	for (UINT32 Index = 0; Index < Used; Index++)
	{
		// Start by finding a pointer to the edge record and previous record (if any)
		pPrevEdge = pEdge;
		pEdge = &(pEdges[Index]);

		// Calculate the path normal for this trapezoid edge.
		if (pPrevEdge == NULL)
		{
			// It's the very first point. The normal is just the normal to the first segment
			TrapEdge *pNextEdge = &(pEdges[Index+1]);
			pEdge->Normal.SetNormalToLine(pEdge->Centre, pNextEdge->Centre);

			PrevNormal = pEdge->Normal;		// Remember this edge's normal for the next pass
		}
		else if (pEdge->Centre == pPrevEdge->Centre)
		{
			// Two points are coincident. That means a joint (or a degenerate source path element).
			//
			// The following cases can apply:
			//	if (the next point is ALSO coincident)
			//		* We have a mitred join. The normal is the average of the previous and next normals
			//		  with some jiggery-pokery to make the normal also have a length which will get the
			//		  outline out to the mitre intersection point (rather than being normalised)
			//	else
			//		* We have the last 2 points of the 3-point mitred join, or
			//		* We have a simple bevelled or rounded join
			//			(both of which are treated in the same manner)

			// Find the "next" edge. Care must be taken for the last join to make sure
			// that the first edge is treated as "next". Note that we don't use point 0
			// in this case, as that is coincident! We use point 1 which is the point
			// at the end of that first line.
			TrapEdge *pNextEdge = &pEdges[1];
			if (Index < Used-1)
				pNextEdge = &pEdges[Index+1];

			if (pNextEdge->Centre == pEdge->Centre)
			{
				// We have found 3 coincident points, so we've hit a mitred join.
				// The middle Edge of the mitred join has a normal which is in the direction
				// of the average of the preceeding/next edge normals (i.e. points towards the
				// mitre intersection), but it has a non-unit-length, so as to stretch the
				// outline out to the mitre point.

				// In this case, we don't bother to do anything yet, as we'll calculate
				// the next normal on the next pass, so we just flag the case and let
				// the next pass come back and fix up our normal once it has all the facts.
				CompletingAMitre = TRUE;

				// NOTE that we leave PrevNormal containing the previous normal - we'll need it
				// on the next pass.
			}
			else
			{
				// The completing trap of any join simply uses the normal of the "next" edge,
				// so we simply calculate this for all cases.
				if (Index >= Used-1)
				{
					// At the end of the curve - we can just copy the normal from the first point
					pEdge->Normal = pEdges[0].Normal;
				}
				else
				{
					// Inside the path - just use the next edge to generate a normal
					pEdge->Normal.SetNormalToLine(pEdge->Centre, pNextEdge->Centre);
				}

				// However, now we must check if we've just completed a mitred join, in
				// which case we have to go back to fill in the previous edge normal
				if (CompletingAMitre)
				{
					// Find the vector pointing towards the mitre point
					pPrevEdge->Normal.Average(PrevNormal, pEdge->Normal);

					// We now know the direction the mitre intersection (pointy bit) lies in.
					// Now, we will "stretch" that normal by the ratio of the distance to
					// the intersection over the stroke width. 
					// We pass in the point before the join, the join centre, and the point
					// after the join. (Note that the join centre point occupies 3 edge entries)
					double MitreChordRatio = 1.0;
					pProcessor->CalculateMitreIntersection(	&pEdges[Index-3].Centre,
															&pEdge->Centre,
															&pNextEdge->Centre,
													/*TO*/	&MitreChordRatio);

					pPrevEdge->Normal.x *= MitreChordRatio;
					pPrevEdge->Normal.y *= MitreChordRatio;
				}

				CompletingAMitre = FALSE;		// Clear the mitre flag
				PrevNormal = pEdge->Normal;		// Remember this edge's normal for the next pass
			}
		}
		else
		{
			// This isn't the first point. It also is not "inside" a joint (although it could be
			// the last edge preceeding a join)
			if (Index >= Used-1)
			{
				// Last point - the normal is merely at right-angles to last line, so = (lineY,-lineX)
				// NOTE that this is not true if this is a closed path, but we will fix that after
				// the loop if it needs fixing
				pEdge->Normal = PrevNormal;
			}
			else
			{
				// Find normal to next line
				NormCoord NextNormal(pEdge->Centre.y - pEdges[Index+1].Centre.y, -(pEdge->Centre.x - pEdges[Index+1].Centre.x));

				if (NextNormal.x == 0.0 && NextNormal.y == 0.0)
				{
					// This point and the next point are coincident, so we must have hit a cusp join
					// (or rampant discontinuity) The normal is simply perpendicular to the last line
					pEdge->Normal = PrevNormal;
				}
				else
				{
					// This point lies between 2 flattened source path segments, so we simply average
					// their normals to get the path normal at the point.
					NextNormal.Normalise();
					pEdge->Normal.Average(PrevNormal, NextNormal);

					PrevNormal = NextNormal;		// Remember this normal for the next pass
				}
			}
		}
	}

	return(TRUE);
}