When we first delved into iOS development in 2014, we had an unexpected problem — there were no simple and efficient tools to work with vector graphics. The available native options had significant disadvantages:
Third-party libraries were available (SpriteKit, iOS Charts, and SVGKit, to name a few), but most of them solved a single specific problem, and none provided a universal API for working with vector graphics.
We decided to leverage our experience in Desktop and Web technologies to create an easy-to-use multipurpose library that would work with SVG files efficiently, draw and animate vector images, create graphs and interactive custom widgets.
One of the best approaches to deal with custom graphics is to use a scene graph (a tree-like hierarchical representation of the graphical scene). That’s what we decided to do with Macaw. To have clear goals in mind, we outlined desired features and a set of rules we would adhere to.
The minimum feature set we wanted to support included a scene graph to compose graphics from primitives, an SVG parser and serializer, support for basic animation and touch events. As for the self-imposed rules, we settled on this list:
It took us ten months of development to release the first public version in October 2016. It included all the features we planned — a reactive scene graph, events, animation, and even SVG support.
Two weeks later, we had 1000+ GitHub stars and a growing understanding of what changes and improvements were needed. The biggest realization was that a lot of people simply needed to draw a static SVG without all the bells and whistles. Three months later (next major version), we included a simple view that rendered an SVG file. We also confirmed our suspicions that the SVG parser was the most crucial part of the project, and have worked on developing and improving it ever since.
Another thing we noticed was the demand for complex animations. In the following release, we included support for node animation that modifies the scene (called ‘content animation’ in Macaw). A bit later, we introduced morphing, path animations, performance enhancements for content animations, and other fixes and improvements.
After 5 years of development, Macaw has grown from a scene graph implementation for iOS to a serious vector graphics toolset available for iOS and macOS with support for:
Naturally, a lot of problems came up during the development, and it’s not possible (or interesting) to list them all. Here are two that we are most proud of conquering.
Native vs. Content Animations
Initially, all of the animations were done with native iOS tools. It was fast but restrictive — no animation could include actions that require changing the state of the content graph. Turns out that complex animations often require it, so we had no choice but to add content animations.
Because redrawing the whole graph is costly, our implementation supports a partial redraw. We made it so that everything happens under the hood, and all the animations are exactly the same from the API point of view. A complex animation may require extracting an element from the scene into a separate CALayer and using native tools to transform it. Meanwhile, the updated scene continues to be modified behind it, with everything being fast and seamless for the user.
Testing the SVG Parser
Is there a better way to check the stability and progress of an incrementally developed SVG parser than to run the official SVG test suite? Obviously not, but it proved harder than we expected, the main reason being the rendering differences between platforms, operating systems, and devices. It meant we could not simply take a reference picture and compare it pixel by pixel with our result. We went through three different options for testing:
Undertaking the significant effort to create a viable testing method helped us grow the parser coverage of the SVG standard from 10% to 40%. While it doesn’t look impressive on paper, 40% covers all but the most esoteric vector graphics. It also makes Macaw one of the best SVG parsers currently available for iOS.
With Macaw, iOS users now have a convenient tool for efficiently creating rich graphical interfaces, and it has become the main library for SVG support with over five thousand stars on GitHub.
When Apple introduced Swift UI in XCode 11, it rendered a part of Macaw obsolete. Swift UI is just the declarative UI building tool we needed and could not find five years ago.
However, we don’t think it will be the end of Macaw. Our path forward is in continuous improvement and growth of our SVG parser, since in this area our tool is still one of the best tools available.