Sign in to follow this  
Followers 0
BoltBait

How to make custom shapes for paint.net 4.0.6+

9 posts in this topic

They are 2 different ways to create custom shapes:

The Easy Way - Shape Maker

The Hard Way - Explained below

Most of the shapes in my plugin pack were created the "hard way", that is coded by hand using the Kaxaml editor.

Before we begin, visit the Kaxaml web site and install Kaxaml: http://www.kaxaml.com/

There are 2 ways to hand code an XAML shape for paint.net:

  • Simple PathGeometry - House
  • GeometryGroup - Smart Phone / Cube

Both ways have their good points. However, you should know that there are things you can do in the GeometryGroup method that you can't do with the Simple PathGeometry. I'll explain both and you can choose which method to use.

 

 

Simple PathGeometry

Here is a template / example you can use right in Kaxaml:

<Page
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Grid>  
		<Canvas>
			<Path Fill="#D2E9F6" Stroke="#5894C1" StrokeThickness="1"
				Data="F1 M 21,142 L 160,22 L 300,142 L 300,318 L 21,318 Z"
			/>
		</Canvas>
	</Grid>
</Page>

 

You just need to replace the data "F1 M 21,142 ... Z" etc. with the instructions to draw your own shape.

Here is the language reference: Language Reference for XAML Mini-Language

The string starts with either F0 (default if not specified) or F1 indicating fill mode 0 (even odd) or fill mode 1 (non-zero).

The M command moves to the specified point, the L command draws a line to the specified end point, and the Z command closes a shape by drawing a line back to the last M command.

Check the reference page for more commands, like curves, etc.

Once you are happy with the shape in Kaxaml, take the data string and drop it into the template for a paint.net shape:

<ps:SimpleGeometryShape xmlns="clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework"
	xmlns:ps="clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"
	DisplayName="House"
	Geometry="F1 M 21,142 L 160,22 L 300,142 L 300,318 L 21,318 Z" />

 

The "DisplayName" field is where you specify the shape name that will appear when you hover over the shape in the shape menu. The "Geometry" field is where you put your drawing instructions.

Once you've saved this file onto your Desktop, copy it to your shapes directory: C:\Program Files\paint.net\Shapes

Restart paint.net and check to see if it appears in the menu. If it doesn't appear, click the gear icon in the upper right corner of the paint.net screen and check in the plugin errors tab.

 

 

GeometryGroup

Here is a template / example you can use right in Kaxaml:

<Page
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Grid>
		<Path Fill="#D2E9F6" Stroke="#5894C1" StrokeThickness="1">
			<Path.Data>
				<GeometryGroup>
					<RectangleGeometry Rect="10,10,184,307" RadiusX="10" RadiusY="10" />
					<RectangleGeometry Rect="15,40,174,227" RadiusX="10" RadiusY="10" />
					<RectangleGeometry Rect="74,21,60,7" RadiusX="10" RadiusY="10" />
					<EllipseGeometry Center="103,290" RadiusX="15" RadiusY="15" />
				</GeometryGroup>
			</Path.Data>
		</Path>
	</Grid>
</Page>

 

I chose to use basic shapes to create the cell phone because I needed to use rounded rectangles. These are easy here as you can specify RadiusX and RadiusY for rectangle corners... something you can't do using the mini-language.

And, here is how it would look as a paint.net shape:

<ps:SimpleGeometryShape xmlns="clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework"
	xmlns:ps="clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"
	DisplayName="Smart Phone">
		<GeometryGroup>
			<RectangleGeometry Rect="10,10,184,307" RadiusX="10" RadiusY="10" />
			<RectangleGeometry Rect="15,40,174,227" RadiusX="10" RadiusY="10" />
			<RectangleGeometry Rect="74,21,60,7" RadiusX="10" RadiusY="10" />
			<EllipseGeometry Center="103,290" RadiusX="15" RadiusY="15" />
		</GeometryGroup>
</ps:SimpleGeometryShape>

Notice the simple copy-and-paste needed. Then, don't forget to specify a Display Name.

Note: paint.net shapes are limited to one path data or one GeometryGroup.

 

 

Another Example

Here is an example of using a GeometryGroup that looks very similar to the Simple PathGeometry we learned first:

<Page
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<Grid>  
		<Path Fill="#D2E9F6" Stroke="#5894C1" StrokeThickness="1">
			<Path.Data>
				<PathGeometry FillRule="Nonzero">
					<PathFigure IsClosed="True" IsFilled="True" StartPoint="0,22">
						<LineSegment Point="58,0" IsSmoothJoin="True" />
						<LineSegment Point="116,22" IsSmoothJoin="True" />
						<LineSegment Point="116,93" IsSmoothJoin="True" />
						<LineSegment Point="58,116" IsSmoothJoin="True" />
						<LineSegment Point="0,93" IsSmoothJoin="True" />
						<LineSegment Point="0,22" IsSmoothJoin="True" />
					</PathFigure>
					<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
						<LineSegment Point="0,22" />
					</PathFigure>
					<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
						<LineSegment Point="58,116" />
					</PathFigure>
					<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
						<LineSegment Point="116,22" />
					</PathFigure>
				</PathGeometry>
			</Path.Data>
		</Path>
	</Grid>
</Page>

 

Here I chose to use the expanded syntax because I can control the shape of the line endings to make the drawing look better.

Here's how it looks as a paint.net shape:

<ps:SimpleGeometryShape xmlns="clr-namespace:PaintDotNet.UI.Media;assembly=PaintDotNet.Framework"
	xmlns:ps="clr-namespace:PaintDotNet.Shapes;assembly=PaintDotNet.Framework"
	DisplayName="Cube">
	<PathGeometry FillRule="Nonzero">
		<PathFigure IsClosed="True" IsFilled="True" StartPoint="0,22">
			<LineSegment Point="58,0" IsSmoothJoin="True" />
			<LineSegment Point="116,22" IsSmoothJoin="True" />
			<LineSegment Point="116,93" IsSmoothJoin="True" />
			<LineSegment Point="58,116" IsSmoothJoin="True" />
			<LineSegment Point="0,93" IsSmoothJoin="True" />
			<LineSegment Point="0,22" IsSmoothJoin="True" />
		</PathFigure>
		<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
			<LineSegment Point="0,22" />
		</PathFigure>
		<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
			<LineSegment Point="58,116" />
		</PathFigure>
		<PathFigure IsClosed="False" IsFilled="False" StartPoint="58,46">
			<LineSegment Point="116,22" />
		</PathFigure>
	</PathGeometry>
</ps:SimpleGeometryShape>

 

Just copy all of the PathGeometry tag into the paint.net template. Don't forget to specify a Display Name.

GeometryGroup and PathFigure are really the same method. You can combine them by putting a PathGeometry inside of a GeometryGroup at the same level as the RectangleGeometry or EllipseGeometry in the first example above.

____________________

4

Share this post


Link to post
Share on other sites

Useful thanks - I.O.U +1 ;)

0

Share this post


Link to post
Share on other sites

The child element of SimpleGeometryShape can be any Geometry-derived class. You aren't restricted to PathGeometry or GroupGeometry.

 

For instance, you could have it be just an EllipseGeometry. Although at that point, just use the built-in ellipse/circle shape :)

0

Share this post


Link to post
Share on other sites

I wonder How many will prefer it over Shape Maker?

 

I prefer it to Shape Maker. Partly due to specifics of shapes I've made.

And I created converter script to automate geometry grafting labor. Check my topic for details.

0

Share this post


Link to post
Share on other sites

See - someone reads your tut @BoltBait. Took me a few tries - but by George I think I got it!

I plan to try using Kaxaml to draw my next shape.

And correct me if I'm wrong - you can't import the geo code into ShapeMaker. Figured that out all on my own but it did frustrate me for awhile.

 

Thanks for the tut and the examples. I enjoy learning new things. B)

 

 

1

Share this post


Link to post
Share on other sites
52 minutes ago, AndrewDavid said:

... you can't import the geo code into ShapeMaker.

 

ShapeMaker has a nice manual; let's see what it says about 'Paste Path Stream':

Paste Path is capable of interpreting StreamGeometry strings which are a lightweight version of
PathGeometry strings. Both can appear in XAML files - but only StreamGeometry can be parsed by
ShapeMaker. Users attempting to paste in PathGeometry strings will receive an error message even
though there is nothing 'wrong' with the string.

So, you can import StreamGeometry, but not PathGeometry.

 

BoltBait's example of StreamGeometry:

F1 M 21,142 L 160,22 L 300,142 L 300,318 L 21,318 Z

 

1

Share this post


Link to post
Share on other sites
1 hour ago, AndrewDavid said:

And correct me if I'm wrong - you can't import the geo code into ShapeMaker.

 

True. But, you can design something in ShapeMaker and OUTPUT the geo code using the menu File > Export Path Geometry.

1

Share this post


Link to post
Share on other sites
36 minutes ago, toe_head2001 said:

Paste Path Stream

That's for the advanced users.

 

Not there yet!

Thanks for the reference though.

Haven't played with that aspect yet @toe_head2001.

I'll get there.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0