Google Summer of Code with Inkscape
Table of Contents
Over this summer, I worked with Jonathan Neuhauser and Manpreet Singh from Inkscape as a GSoC contributor! We worked on an extension that allows Inkscape to read Adobe Illustrator files.
This blog post is a summary of my progress over the summer, covering my work on improving Adobe Illustrator’s file format support in Inkscape and what I learned along the way.
What is Inkscape? and Why did I choose it?
Inkscape is an open-source vector graphics editor. For many people, Inkscape is the first software they use to create vector graphics, and for many, is synonymous with the term. It was the first (and only) vector graphics editor I had used.
As for why I chose Inkscape:
- It was something I was already familiar with, and I was already infuriated by its interface (sometimes) :P
- It’s open source, so I can fix it!
Ha, not that simple. What I noticed was that most of the organizations in GSoC consist of very mature, extensively used projects1; while the capabilities Inkscape provides are heavily dominated by proprietary players like Adobe and Affinity.2 Neither of which is either free as in beer or free as in freedom.3
If Inkscape were to stand on comparable grounds with Adobe Illustrator, the first step would be to add support for .ai files to help users smoothly switch to Inkscape, or at least not be forced to buy Adobe Illustrator to open an Illustrator file. This would increase accessibility for those who do not have the resources to afford Adobe Illustrator.
I was given the opportunity by GSoC to work on Inkscape, but you don’t need to be a GSoC contributor to contribute to Inkscape! It has an awesome community, and anyone is welcome to be a part of it!
Merge Requests
Here is a summary of all the merge requests I have made to the project:
| Title | MR | Status |
|---|---|---|
| Fallback to bezier curves for unimplemented features | !107 | Merged |
| Group Opacity Application (XW command) | !109 | Merged |
| Implement Raster image support | !111 | Review Pending |
| Implement Clipping Mask Support | !115 | Needs more investigation4 |
| Implement second radius type | !127 | Needs Tests |
While working on the above, I also made the following minor maintenance changes:
| Title | MR | Status |
|---|---|---|
| Update global export functions to use new parser API | !108 | Merged |
| Update dependencies and migrate to Inkex Color interface | !110 | Merged |
| Add AI26_BeginPlacedObjectPreview section to file parser | !112 | Review Pending |
| Catch error when live shape conversion fails | !116 | Review Pending |
| Remove old parser implementation | !117 | Merged |
I had also proposed the following optional, time-permitting features:
- Variable Width Strokes
- Filters
- Document Metadata + Object Properties
Unfortunately, during the 12 weeks, I decided to focus my time on other areas that I felt were more impactful, so these features didn’t make it in.
Finally, Text along Path ended up being worked on by Manpreet as part of his MR adding comprehensive support for all text-related functionality.
Changes in Action
Here are some images highlighting functionality made possible by the features we developed during GSoC:
The Experience
Adobe Illustrator files, with the extension .ai, are simply PostScript files. As of right now, the extension-ai repository has a full parser that can parse the file. What needs improvements, and requires significant work, is to convert this data into an Inkscape SVG in a way that is as easy to edit as in Illustrator.
Fallback to bezier curves for unimplemented features !107
One of the first tasks I was assigned was to render any unknown objects using their fallback Bezier curves. Each object in the file has its resultant Bezier curves defined, which can be used to render the object without relying on its original path. This obviously isn’t ideal, as we want to have the ability to edit the object in Inkscape the same way we would in Illustrator, and not just render it.
To be able to modify the base path and have the texture generate along it, we’d need support from Inkscape to do so. Luckily, Inkscape has the Live Path Effect, which allows us to use “Pattern Along Path” to generate the texture along the base path, just like our brush works!
Obviously, the result may not look 1:1 like it would in Illustrator, but that is a compromise we have to make. At the end of the day, we’re not trying to replicate the exact look of the object (as much as we’d like to), but we’re trying to make it as easy to edit as possible. After all, they’re PostScript files; they’re designed to be rendered consistently.
XW Command !109
This was a fun little MR, where I added support for the XW command to the parser. The command itself is used to apply ArtStyles (opacity, stroke-offsets and other brush-related shenanigans to objects.
I actually ran into this issue while working on the previous MR, where the opacity was being wrongly applied to multiple layers.
Raster Image Support !111
This one was a rollercoaster, when I was making the proposal, I had no idea how hard or easy this would be. Turns out much of the work for its support was already there in the old parser! So all that I had to do was add the support for it in the new parser.
However, that didn’t turn out to be just as easy as I thought! Turns out we completely forgot about tranparency, and then I spent quite a lot of time figuring out embedded images, and guess what! Even when everything seemed to be working well! I found out files where the images were just.. placed very strangely!
Turns out, I needed to transform the position into a different coordinate system, that we were using to account for large canvases that I was wholly unaware of! The MR is still open for this exact reason, and I need to patch that up real quick!
Either way, this is one of those problems, that are hard to estimate the time required and difficulty of, even as you are working on it.
Clipping Mask Support !115
Clipping Mask support ended up being quite easy! Turns out it is very well documented in the Adobe Illustrator documentation, and I was able to implement it with relative ease.
One thing that I could’ve gone about implementing was Multi-Layer Masks, that was something that was supported in the past versions of the file format, however Illustrator itself has stopped supporting it, and without a way to generate test files for it, I decided to leave it out.
Clipping masks are pretty useful, and I’m glad I was able to implement it.
Life Lessons and Conclusion
Time Management during the summer was quite a challenge, I had an internship in the first half, and my usual studies in the last third of it. Juggling everything while finishing my academic obligations was quite a challenge, and I’m glad I was able to do it, even if it wasn’t as well as I hoped I would be able to.
Sure, 175 hours may not sound like much, but it’s more than enough to keep you occupied. Spread evenly across the summer, that works out to roughly 2 hours a day, but it’s difficult to use that time efficiently because of the overhead that comes with switching in and out of work.
I ended up doing much of my work on the weekends, as I could sit down and focus on things without any interruptions. I really wish I could’ve done more, but I’m glad I was able to contribute to the project, and I can always work on it in the future 😉.
Footnotes
-
GCC, Gitlab, Kotlin, The Rust Foundation, openSUSE, etc. ↩︎
-
Specifically, Adobe Illustrator and Affinity Designer. ↩︎
-
Confused? Read: Not free as in beer, but free as in freedom. ↩︎
-
The base feature is implemented, however more investigation is needed to figure out some edgecases ↩︎