"... and no one shall work for money, and no one shall work for fame; But each for the joy of the working, and each, in his separate star, shall draw the thing as he sees it, for the god of things as they are"

-Kipling

 

Font to GCode Conversion

The Problem

Like me you may well one day have occasion to write some software that outputs GCode and this software may also need to encode a GCode representation of textual characters. If that situation should come to pass you may well hit the Internet to find out how to convert a TrueType font into GCode lines acceptable to your CNC machine.

There did not seem to be a lot of usable information on the font to GCode problem when I was looking (early 2022) and what little was present was somewhat conflicting. It seems there are a variety of methods depending on which languages and technologies the author chose to use - and none of them seemed be at all straightforward.

The essence of the problem is actually pretty simple though. How do you take an arbitrary TrueType font character composed of splines and Bezier curves and turn it into a sequence of straight line segments which approximate the curves to some specified level of accuracy?

A Digression

Before we get into how it can be done, lets take a short digression to see what it means to convert fonts to GCode at various levels of accuracy. Have a look at the images below. Each has had its curves converted into a series of line segments with varying degrees of granularity.

      

 

The image on the left has such a fine segment resolution that its character is indistinguishable from one drawn as curves. In the middle, the image has been converted at such a low granularity that it looks like text from a 1980's video game. On the right, the character is still composed of a connected sequence of line segments but it looks a lot smoother. Each line segment in the character will have two endpoints and moving the bit between each endpoint will require a line of GCode. The Font to GCode conversion process is always going to be an approximation and you will have to trade off the number of GCode lines you wish to generate against the perceived roughness of the character. If this whole line segment conversion thing seems complicated and problematic, don't be distressed, read on, it will turn out to be much less of an issue than you might imagine since, in the method described below, the granularity is just specified as a single floating point number which you can change at will.

The Solution

If you use .NET the solution to the Font to GCode Conversion problem is simple - relatively trivial even.

The big reveal is that the Flatten method on GraphicsPath object does all the work of converting any .NET path into a connected sequence of straight line segments. It contains some serious magic and practically hands the result to you on a plate. Since it is easy to set up a path based on a string of text in a TrueType font, the font to line segment conversion just happens automatically. Simply set up your paths, call the Flatten method with a float parameter indicative of the flatness granularity you wish and you will subsequently have access to two arrays in the GraphicsPath object. One array will be a sequence PointF[] values called PathPoints which describes the coordinates of each endpoint of the line segments. The other array is a sequence of byte[] values called PointTypes the value of which is a bit flag that describes what that point means.

Once you have the two arrays, you can just sit in a for loop and run through them together. In other words, read the coordinate from PathPoints, figure out what it means by looking at its corresponding value in PointTypes and then do what you want with that information. For example, if the PointType value says the coordinate is a path START then output a GCode line to go to that coordinate and then another to drop the bit into the work. If the flag is a LINE segment end then you output XY GCode to traverse to that coordinate with the bit still in the work since at this point you are actually cutting part of the text along the way. If you see a bit flag on the PointTypes value that says it is also a PATHEND you emit GCode to subsequently pull the tool out of the work when you get to the point directed by the LINE flag. There are other flags of course, but if you have run the Flatten command they will never be present in the PointTypes array.

Seems simple - so why write this page? Well, the thing is (at least by early 2022) nobody seems to have specifically documented the use of the GraphicsPath.Flatten() call for use with Font to GCode conversion. Thus searches on "Font to GCode" never seem to pick it up and as a solution it was so hopelessly obscure it may as well have not existed. Hopefully, you will have an easier time getting to where you need to be now that the search engines can find this page.

Other Things to Consider

Transforming your font string into a sequence of connected line segments is all well and good, but as you might imagine there are a few other things to consider. The first of which is that, in the standard .NET graphics path coordinate system, location the value X=0, Y=0 is set at the top left corner and the positive Y axis moves downwards on the screen. You are unlikely consider this orientation to be acceptable in your output GCode. In reality you will probably wish to use a system in which 0,0 is at the lower left corner and positive Y moves upwards. Alternately, a coordinate system in which the 0,0 coordinate is at the screen center is often preferable. Another issue is that the path coordinate values are given in pixels. You will need to convert the DPI (dots per inch) values of the Windows screen coordinate system into a suitable inch or millimeter value for your GCode output.

Fortunately, the solution to both the coordinate transformation and DPI conversion problems can easily be provided by supplying what is known as a Transformation Matrix to the .NET Graphics system. For a real-world example implementation have a look at the NamePlateGenerator software. It contains, amongst other things, a fully operational TrueType Font to GCode conversion engine using the Flatten method described on this page and also a routine to set up a Transformation Matrix to handle the coordinate flip and translation as well as the DPI conversion. As specific advice to help you figure this stuff out, you might find it useful to download the NamePlateGenerator source code and drop a breakpoint in the panelLabelDisplay_Paint routine. The Visual Studio debugger will walk you right through the entire process. Along the way you will run through the InvertForOutput routine which provides the coordinate conversions - once you see how it is set up you will probably be amazed at how simple it is.

Acknowledgments

The fundamental concepts of how to use .NET to convert TTF Fonts to GCode were derived from Jim Steinbrecher's "Font to G-Code" software. The Visual Basic source for this work can be found at https://www.vbforums.com/showthread.php?666224-Font-to-G-Code-CNC-VB2005E. Thanks Jim - without your work I never would have thought of using the Flatten method!

License

The contents of this web page are provided "as is" without any warranty of any kind and without any claim to accuracy. Please be aware that the information provided may be out-of-date, incomplete, erroneous or simply unsuitable for your purposes. Any use you make of the information is entirely at your discretion and any consequences of that use are entirely your responsibility. All source code is provided under the terms of the MIT License.