Red Stars Programming, food, and rambling

21Jul/090

System.Drawing.Drawing2D.PathPointType defined.

I had a project which involved raw access to the data stored inside of a System.Drawing.Drawing2D.GraphicsPath and found that the MSDN Document for PathPointType was rather lacking, but it's not too complex.

Inside of GraphicsPath is a byte array called PathTypes that contains PathPointType and a PointF array called PathPoints (the same data is also stored in GraphicsPath.PathData.Points and GraphicsPath.PathData.Types). They relate to each other by index, so PathTypes[n] is the PathPointTypes for PathPoints[n].

The reason PathTypes is stored as bytes and not PathPointType is because multiple values will be contained per byte. To separate the two, you must use a bitwise AND operation of your value against the bit mask PathPointType.PathTypeMask. The resulting value is either Start, Line or Bezier (Bezier3 is equal to Bezier).

You can NOT modify these collections directly. Instead, you must make a new instance of GraphicsPaths and pass modified collections to them via the (PointF[], byte[]) constructor.

PathPointType values
PathPointType Value Description
Start 0 Start of graphics path. Move cursor then put pen down.
Line 1 Move pen to given location.
Bezier 3 Draw curve.
Bezier3 3 Equal to Bezier.
PathTypeMask 7 Mask for extracting types from PathTypes.
DashMode 16 Draw in dashes, not solid lines.
PathMarker 32 Lift pen, move pen to new location, then if the pen was down before, place back down.
CloseSubpath 128 Move mouse to point from the last Start (closing the path) then lift pen.

Below is code which parses the PathTypes and PathPoints and causes actions in a class which renders the GraphicsPath as mouse output where the mouse is down when the pen should be down, and the mouse moves to the location the pen should be, etc. Please note this code renders Bezier curves as lines.

int index=0;
PointF firstPoint = new PointF(); // Used to store the starting position so closed paths can reposition here.
// Loop through all path data
foreach (PointF point in Path.PathPoints) {
	byte curType = Path.PathTypes[index];
				// Extract the item type by the bit mask
	byte itemType = (byte)(curType & (byte)PathPointType.PathTypeMask);

	// Draw the different object types
	if (itemType == (byte)PathPointType.Start) {
		firstPoint = point;
		input.MousePos(point);
		input.LeftButtonDown();
	} else if ((itemType == (byte)PathPointType.Line) || (itemType == (byte)PathPointType.Bezier) || (itemType == (byte)PathPointType.Bezier3))
		input.MousePos(point);

	// Handle all additional flags
	if (isType(curType, PathPointType.PathMarker)) {
		bool wasMouseDown = false;
		if (input.IsMouseDown) {
			wasMouseDown = true;
			input.LeftButtonUp();
		}
		input.MousePos(point);
		if (wasMouseDown)
			input.LeftButtonDown();
	}

	if (isType(curType, PathPointType.CloseSubpath)) {
		input.MousePos(firstPoint);
		input.LeftButtonUp();
	}
	index++;
}
input.LeftButtonUp();
private bool isType(byte type, PathPointType isType) {
	return (type & (byte)isType) != 0;
 }
Filed under: C# Leave a comment
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

You must be logged in to post a comment.

No trackbacks yet.