Plottie: Driving a Silhouette Portrait plotter/cutter
The Silhouette Portrait is a desktop paper cutter and pen plotter which can be used to cut intricate shapes out of paper and card. They are fantastic devices, robust, remarkably accurate and include precision optical registration to allow cutting out of printed designs.
This project started back in 2013 when I originally reverse engineered the USB protocol used by the Silhouette Portrait and built myself a rough-and-ready cutting and plotting tool. In the intervening years I've used the plotter (and my rudimentary software) more than I ever imagined for all manner of projects.
Unfortunately I never put the time in to finishing the software and more recently (around 2018), I finally got fed up with fixing things and vowed to start again and do a proper job and, so, Plottie was born.
Reverse engineering the plotter
I bought my Silhouette Portrait in 2013 to make our wedding invitations. Unfortunately, however, the Silhouette Studio software which came with the device only worked with Windows and macOS, but not on Linux. At the time, the open source and cross platform Robocut software was in its infancy, supporting only a fraction of the functionality I wanted and lacking in robustness. However, it demonstrated that the USB protocol used by Silhouette devices was relatively simple.
To reverse engineer the USB protocol I spun up a Windows virtual machine and then used Wireshark to capture the USB protocol messages on their way to and from the plotter. After lots of trial and error I managed to work out how all of the basic functions were controlled -- and what all of the commands sent by the Silhouette Studio software did. (A snapshot of some of this exploration from 2013 can be found here.)
Based on this work I built a library,
py_silhouette, which provides
an easy-to-use Python API for controlling the plotter at a low level.
py_silhouette source code includes extensive comments and documentation
on the underlying protocol, explaining every command in detail (see
goes into the meaning of the various parameters and construction of
registration marks in detail.
Converting SVGs into line segments
With the device under control, the next task was to provide it with something to cut out. SVG is a widely used vector graphics format and the native format of my graphics editor of choice: Inkscape. As a full-featured vector graphics format, SVG is complex to parse and defines shapes in terms of curves, text and other shapes with sophisticated styling options. As a consequence, converting from SVG to a list of straight line segments -- all the plotter understands -- proved challenging.
Inkscape itself provides numerous export formats, including (in earlier versions) HP-GL -- a file format used by certain plotters. Unfortunately, this functionality was fairly limited and a large number of basic SVG features simply did not work.
After briefly considering writing my own SVG interpreter, I discovered a neat
trick used by Robocut to read SVG files. The Qt GUI
library provides its own SVG
renderer which is able
to render onto any of a number of
ends. Thanks to the outstanding level of care by the Qt developers it is
possible to create a custom
QPaintDevice implementing just a 'draw straight
line' primitive which is then used by all other drawing operations.
Using this Qt SVG trick gets you 90% of the way to a working SVG-to-straight-line-segments conversion. Unfortunately there are a few subtle things which still need some manual intervention (which the inspirational Robocut implementation did not include).
Unfortunately the Qt API does not implement dashed strokes for you and instead sets a flag indicating the expected dash pattern. Implementing dashed strokes correctly proved slightly fiddly but was extremely useful for producing perforated edges and fold lines).
In addition, Qt's SVG Renderer operates on screen coordinates and so accurately converting coordinates to millimetres requires manual parsing of the SVG. This is further complicated by the fact that until recently Inkscape had been using the wrong DPI in all generated SVGs requiring a special-case to correctly handle scale these files.
Back in 2013, Qt's Python bindings weren't quite up to allowing you to provide
a Python implementation of
QPaintDevice and so, like Robocut, I ended up
writing my first implementation in C++. However more recently Qt for Python
(a.k.a. PySide2) has brought vast
improvements to Python Qt compatibility and a Python implementation is now
svgoutline Python library
contains a self-contained implementation of all of the above with an
easy-to-use API. It achieves the best SVG-to-straight-line conversion support
I'm aware of, though still isn't perfect. Its only major limitations are due
either to Qt SVG only supporting the SVG Tiny
1.2 subset of SVG or bugs in its
implementation. The library also
has a fairly extensive test suite which verifies exact conversion of a wide
variety of SVG features.
plottie user interface
The Plottie command-line tool ties all of this work together in a ready to use SVG-to-tiny-bits-of-cut-out-paper-all-over-the-place tool. Plottie has replaced my earlier unpublished (and near-unpublishable(!)) plotting software bringing with it numerous helpful features. These include:
Robust automatic detection of registration marks within an SVG file. This includes things like handling trivial floating point precision errors and not being put-off by other registration-mark-like items in the drawing.
Automatic plot-vs-cut mode selection based on Inkscape Layer names. If a layer called something like 'Cut' or 'Plot' is found, Plottie will guess the correct mode to use.
Flexible object selection. What to cut can be chosen by layer name, colour, SVG object ID or class. Further Plottie will automatically hide and show layers (and objects) in the file. This means that cutting outline layers can remain hidden in the SVG file (keeping the file in a ready-to-print state to avoid mistakes!) and Plottie will still be able to find and use them while ignoring the rest of the design.
Sensible cut re-ordering. Though Plottie doesn't go to the lengths of some tools to manipulate the cut order to support mat-free cutting, it does try to cut inner-most shapes first and otherwise cut in a sensible order.
As such, 99% of the time plotting or cutting can be performed using no more than:
$ plottie path/to/drawing.svg
All of the software I developed during this project can be found on GitHub or
installed from PyPI using