For a few months this year, I was working with an internet marketing company in the middle of a hard pivot into print marketing. Personal disagreements with this as a business strategy aside, it did put me into contact with a number of unique problems to solve. And if you know anything about me, it’s that I do love a unique problem.
In this instance, we were retrofitting their existing website with a new design and most importantly a new builder app so that customers could customize their printed goods (custom holiday cards, ect). Since I was the only web developer working on this project full time, we elected to use an existing App that gave us a fair amount of latitude in re-branding and in the kinds of designs we could construct in it. We decided to use a service called Pitch-Print. It was a very strong service, and while it had its problems, I enjoyed working with their app overall.
The Problem
Pitch Print was entirely based on web technologies, and was designed to be compatible with the largest number of browsers possible. This means that features that were included were constrained by not only developer time, but by what the collection of browsers they targeted could support. This meant the developers ended up developing a lot of odd solutions and shims to add support for edge cases. One of those edge cases, masks, happened to be a large component of the Holiday cards we were tasked with getting into the Pitch Print app.
If you’re unfamiliar with what a mask is, it is a shape that can be used in computer art to constrain another piece of art. In our designs, we were using it to essentially crop uploaded user photos to fit the designs.
In this particular instance, the solution their team came up with was a very specific subset of SVG markup that could then be turned into a mask. This markup could not contain any meta data, and could not contain any elements outside of the path element. Adobe Illustrator and Inkscape do not export in this format, and were noted as incompatible in their documentation. To complicate this further, on testing we discovered that paths that were compatible could not be correctly rotated, so we had to use paths that were at the exact angle already. And of course, we were on a strict deadline so we only had a few days to get a solution in place.
The Method
Like many of my ideas, I had this one while I was sleeping. I have a long running joke with everyone I talk to about what I do for a living. People say to me, “Well, you’re obviously good at math”, and I respond, “No, I’m good at telling the computer to do the math for me.” It’s still nagging at me even now, that there’s probably an equation I can run to do this work, but we didn’t have time for me to do the research, so I went with what happened in my dream.
Basically I lucked out, because every mask we needed to generate was a rectangle.
I took whatever placeholder asset our designer used to define the mask and I painted it onto an HTML5 canvas element. I then extracted the pixel data of the canvas into a large nested array. I set up a while loop to test the pixels one by one until it encountered a pixel with a non-zero alpha value. By reversing the x direction, the y direction, and then the x direction again we did this four different times finding four different points. The four points of our rectangle. With these four points, it was easy to turn that data in to an SVG path that Pitch Print would accept. The whole thing took me about 2 hours to prototype and an additional 4 to wrap in an electron app so that I could have access to the file system to write the results to files and do multiple masks in a batch.
The Result
The masks weren’t perfect. Because I was using raster images to calculate approximate positions of vectored coordinates the angles weren’t exact, but in what amounted to a little less than one work day I had a “good enough” solution that allowed us to get the designs up and available for sale well within our deadline, and because we were working with SVG files, ones that were obviously wrong could always be tweaked by hand, and others only myself and the designer could see the mistakes in.
So, this is a solution that I proud of because it worked and we got deployed quickly, not because it was the “right” solution. If I had more time with the problem, I probably would have written a utility to parse and modify the SVGs that Adobe Illustrator could generate, as this was where our designer was working and would have all but eliminated the approximation problem with the coordinates. That’s still something that I think I would enjoy writing, but I’m not sure I’ll ever have explicit reason to.
That said, because the prototype was written entirely in JavaScript, I went ahead and hosted it on the site so you can look through the functional code yourself.
You can find that here: https://stephkennedy.dev/experiments/mask_proto/index.html
All the code is in the document, so feel free to inspect the page and look through it. It’s not complex by any means.