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:

Inkscape logo with a rainbow gradient
The Inkscape logo as the clipping mask with a raster image.
Illustrator logo fading away
Illustrator Logo (Raster Image) with Transparency
Brush stroke
Brush texture now rendered using the fallback bezier curves.
A crosshair
A very simple image that had some styling issues before

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.

Screenshot of illustrator showing a brush with it's underlying Path Element
Illustrator: The Brush texture is rendering along the path, which can be manipulated easily as desired.
Screenshot of Inkscape showing the earlier Brush, it now consists of 81 individual path elements for all of it's texture.
Inkscape: The Brush texture is now rendered as individual path elements, editing the underlying path is no longer possible

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.

A crosshair
An image of a crosshair that was being wrongly rendered before

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.

Raster Image of an Apple
Raster Image of an Apple [^copyright]

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.

Inkscape logo used as a clipping mask
Inkscape logo used as a clipping mask

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


  1. GCC, Gitlab, Kotlin, The Rust Foundation, openSUSE, etc. ↩︎

  2. Specifically, Adobe Illustrator and Affinity Designer. ↩︎

  3. Confused? Read: Not free as in beer, but free as in freedom↩︎

  4. The base feature is implemented, however more investigation is needed to figure out some edgecases ↩︎