Have you ever looked at an icon like the one above and wanted it in your diagram? With the release of Gliffy Confluence Plugin 5.1 you can do that now with our Stencil beta feature that lets you drag and drop SVG files directly into the Gliffy HTML5 editor. In this post, we’ll walk you through what a stencil is, why using one is better than using an image, and some of the technical challenges we faced along the way.
Stencil vs Shape
In Gliffy terms, a stencil is an object that tells our editor how to draw the shape. A stencil can be resized to just about any dimension (within browser limits) and not lose any detail like an image does. This ability to add custom stencils brings us an exciting step closer to custom shapes. The difference being that a stencil gives the editor the ability to draw a symbol, but it doesn’t provide any behavior like a shape does. You can’t, for example, change the color or the line-width of a shape in a dropped SVG file, because the SVG file only has a static value for those things. The shape will forever be just that thick and that particular color. With a stencil, our editor doesn’t know those properties should be editable.
Even though we don’t have custom shapes yet, being able to drop just about any SVG file into Gliffy is still a big win. It opens the door to a whole slew of content, both public domain and purchasable, from content sites like the noun project or from companies like Amazon that decide to release their network symbols in an easy to use package.
As an added bonus, custom Visio shapes will now be converted using this same approach. Previously any custom Visio shapes were converted into a static image using Batik. So you’ll see a number of visual improvements and closer accuracy to the original Visio file.
See it in Action
Vector vs Raster
So now that you’ve seen how our stencils work, why should you use them? Sure, you can theoretically import all the content you need via our image upload feature, but you’ll quickly find the difference between the two when you attempt to scale them.
If you recall, an image is basically a bitmap. The file format keeps track of how many pixels it has, what color each pixel is, and where each pixel goes. If you try to scale the image, you’ll notice a definite loss of clarity because each pixel also scales up in size too. In a scaled image, a pixel that used to be a indistinguishable point on the page, now appears as a plainly visible square. Vector graphics on the other hand use paths, which are drawing commands that are agnostic to what size the graphic is. The example image below is pretty telling in the difference in quality.
Example: Vector graphic to the left, and image to the right. The image loses clarity as it is scales.
Behind the Curtain: Transforming your SVG into Canvas Commands
Since we’ve chosen to use the canvas API for a number of technical reasons, whenever you drop an SVG file into the Gliffy Editor we must convert the SVG file into canvas drawing commands. After reading the file locally using the file api, we call a Java service to transform the file. The logic behind this is really a beefed up Java port of Canvg, an SVG parser and renderer by Gabe Lerner. In our port, we’ve of course added a bunch of goodies including: non-scaling-stroke support, dashed-line support, better arc command support, and most importantly the ability to use mustache in an SVG file to change things such as color, size, and anything else you would normally want to manipulate in a given shape.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="" height="" viewBox="0 0 100 100" overflow="visible" preserveAspectRatio="none" />
An example of an SVG template using and placeholders
However, since we would be transforming not only our SVG well-defined shapes, but any SVG shapes, we also had to solve the following issues:
1) Give the user a bounding box that makes visual sense.
2) Ensure that the shape resizes in a sensible way.
Bounding Box Madness
What exactly do I mean by this? To highlight the issue, let’s take a closer look at the following SVG file that draws a penguin.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="612px" height="792px" viewBox="0 0 612 792" enable-background="new 0 0 612 792" xml:space="preserve">
<path d="M330.178,386.124 … "/>
In this example the viewport or viewbox is set, such that the viewable area is visible at 0,0 with a width of 612 pixels and a height of 792 pixels. The penguin, however, is drawn in the middle of the viewport. Internally, we assume that all of our Gliffy made shapes have an editable area based on an SVG’s viewbox, but we can’t make the same assumption in this case. When a user drops this file into the editor, we’d expect the penguin shape to show up with an overlay using the blue rectangle, not the magenta one, as shown above.
To compute the blue box, we would need to keep track of the file’s visible bounding box, a bounding box being the smallest box that contains a given set of points. In a more complicated file, we would also need to track the combined bounding box of any other visible path, and this is exactly what we do for our service. Whenever you drop in an SVG file into the editor, we not only transform the SVG into the proper drawing commands, but as we parse the file, we also keep track and compute the bounding box of all visible paths.
With this bounding box information in hand, we also know how to scale up the stencil, since we know it’s original ratio, and we can scale it without it appearing to have an arbitrary amount of whitespace.
Just the first step
SVG is a very large specification so please keep in mind that while our ultimate goal is to support just about any SVG file, this feature is still very much in beta status, and certain SVG features like CSS style support have not been implemented yet. We’d love to hear feedback from you, especially if you have problems importing certain SVG files.
We also know this isn’t the best workflow to import custom content, which is why this is a beta feature, but stay tuned! We’re also hard at work redesigning our shape library. Soon you’ll have a number of new Gliffy designed shapes to use, and we’re planning on making it just as easy to pull in external content.