sK1 development restarted
sK1 project has been a bit silent for the most of this year. This is basically because we started it all over again. Read on to find out more.
A year ago we decided to introduce major changes to both sK1, the vector graphics editor, and UniConvertor, the vector graphics conversion tool. After some analysis the decision was made to start everything from scratch.
Why we did it
Initially the plan was to do refactoring of both sK1 and UniConvertor. This decision didn’t come out of blue, because the source code inherited the architecture from Sketch/Skencil which was fine for late 90s, but didn’t really cut the mustard for 2010s. Given amount of code base to go through we decided to just redo everything from start.
That wasn’t by any means an easy decision to make, but it wasn’t the only way out, especially since supporting the old toolkit was starting to take too much time. Mere 2-3 years ago we still had some hopes for Tcl/Tk 8.5-8.6, but alas it was a defeat. So we also had to find a new toolkit, and the choice was between GTK+ and Qt. Architecture was another issue we had to deal with, since we used to support sK1 and UniConvertor as two separate projects using same code base. There was a great deal of other architectural issues.
The architecture of sK1/Skencil was formally declared as MVC pattern, that is, Model-View-Controller:
Within this pattern View is UI of the application, Controller is that part of code that deals with user input, and Model is the tree-like document objects hierarchy that contains all information about what’s on the canvas.
But that’s only what it was supposed to be. The real thing looked much worse with all three components completely messed up. The model had bits of UI, and the model’s objects were hardwired to Xlib structures, and so on. Skencil/Sketch was also initially designed as one document per instance application, hence loading of new documents used to result in memory leaks.
For the new architecture we decided to go for MVP pattern which stands for Model-View-Presenter:
This way documents model is isolated from UI, and that solves quite a few issues:
- we could create a hybrid application that would use UniConvertor as its core (Model + Presenter), and the vector graphics editor would be just a front-end;
- a better design would help us avoid memory leaks;
- new applications could be written on top of UniConvertor;
- model redesign would drop memory use dramatically.
The model redesign bit needs some elaboration. Typically when you create e.g. a thousand of equal rectangles, you get a thousand of copies of a method that is specific for the rectangle. So we decided to move as much of code to Presenter (which is just one per document) as possible, thus making objects of the model plain datasets. Testing revealed that this leads to a considerable drop of memory use, even better than in Corel DRAW and Adobe Illustrator. However this is specific for Python and doesn’t make a lot of sense for e.g. C++.
New file format
SK1’s file format was derived from the old Sketch/Skencil’s one and lacked some useful features, such as:
- embedding files like fonts, ICC profiles, color palettes etc.;
- simple extraction of embedded images;
- readable document structure.
So we designed a new file format that is modeled after OpenDocument and called it PDXF (PrintDesign XML Format). Just like OpenRaster or OpenDocument files it’s a ZIP archive with content.xml that describes the structure and nested folders for each type of embedded data. The difference is that it doesn’t use things like external CSS: each object is described inside its tag.
Choosing a new toolkit
As previously mentioned, we had to pick either GTK+ or Qt as a new toolkit. So we implemented test applications in both toolkits to compare and make a decision. Here is what we discovered:
- Qt has considerably more features.
- QPainter is much faster than Cairo and supports OpenGL natively;
- However GTK+ is more lightweight and uses twice as little memory.
- Unlike QPainter in Qt, Cairo isn’t part of GTK+, so one could do a server build that doesn’t require Xlib/WinAPI, which is important for UniConvertor.
- GTK+ is 100% free, while Qt is tossed from company to company.
So we decided to go for GTK+, but redesigned UniConvertor in a way that makes it possible to create a Qt-based vector graphics editor.
Since we started a whole new project, we decided to rename the actual editor. The new name is PrintDesign which is rather self-explanatory.
We also redesigned the logo. It still represents CMYK primaries and looks good in all resolutions starting with 10×10px.
The new user interface uses tabs for MDI, and unlike in sK1 every document in PrintDesign has its own canvas and its own message loop. That isolates every document instance rather well.
Testing of this initial implementation revealed that the application:
- starts momentarily;
- works reliably in a multidocument mode;
- cleans up reserved memory well enough when you close a document;
- renders complex documents very fast.
We already used Cairo since 2007, but it was built on top of an existing renderer which used Xlib (and it looks like Inkscape developers have been trying to do the same lately). We are using Cairo differently now. Even though PrintDesign is still in its infancy, we have basic canvas functionality in place, that is, selection and transformations, and we have new selection markers instead of the old XOR-based from sK1.
All the testing was done with just one implemented shape — rectangles. The next thing we are going to do is implement support for more shapes, text and bitmaps.
The old architecture, inherited from Skencil, was quite limiting in a way that all file formats were read as a stream of data. It’s OK for some simplistic file formats such as PLT. But when it comes to CDR or SVG, where definitions can be stored separately from an object, things suddenly start looking really bad. You end up with spaghetti of procedures, where parsing, analysis and creating of model’s objects are intertwined.
To fix it we decided to use a different approach and create format specific models for each supported file format. What it means is that when you start importing a document, UC will create a file format model, then convert data of this model to PrintDesign model’s objects, then (optionally) merge the resulted document into an existing one (if you import a file into an existing illustration). It also helps dealing with nested file formats (e.g. bits of CMX and TTF in CDR files).
We also created a new application called Format Explorer for visualization and analysis of reverse-engineered file formats. Since it uses UniConvertor directly, the newly created conversion code automatically becomes available for both UniConvertor and PrintDesign. Format Explorer is an in-house project that uses Qt for user interface.
It’s way too early for any releases, but it’s free software, so you can track the progress if you want to:
UniConvertor 2.0: http://uniconvertor.googlecode.com/svn/trunk/
PrintDesign 1.0: http://print-design.googlecode.com/svn/trunk/
As you can see, we have also moved from SourceForge to Google Code for better reliability.
Our plans are rather ambitious, but please don’t expect immediately useful software. Even big software companies cannot magic a whole new application from scratch in few months, it takes years to get there. Our primary objective is to release UniConvertor 2.0 with new features: improved support for Corel DRAW files, including importing files from X5 and exporting CDR files. This version will be released in few months. the first fully working prototype of PrintDesign will be presented at Libre Graphics Meeting 2012 in Vienna.