LibreCAD 3 Lua plugin system

Brief project summary

During the GSoC 2016, I began a simple implementation of Lua plugins. They offer a GUI version with preview of what could be done before with the LibreCAD command line. The plugins can only add primitive entities to a document, others operations are difficult to program, and won’t be intuitive for the user.

This project aims at improving this plugin system. The plugins could create new entities types, and define custom interactions.

For example, the rectangle plugin is only adding 4 lines in the document. After that, individual lines can be modified, and it doesn’t look like a rectangle anymore. Here the script should handle the modification of the entity so it will always remain a rectangle.

The plugins could also make operations on files, which would allow scripts to import or export different formats.

The same Lua code could be run in LibreCAD, or in command line or in a quick script, and have the same result.

This proposal is also including drawing optimizations for LibreCAD, and a unit test system for entities rendering.

Detailed project description

Implementation of new plugins:

First, the Lua script system needs to be improved. For the moment each file is included by the Lua UI.

The current implementation has some limits for security reasons. Some functions were modified or removed. It is currently impossible to read or write a file, and some plugins can make LibreCAD crash.

The solution here is to run each plugin on its own instance. Some function currently defined in Lua would be moved to a C++ API accessible from the scripts. This includes the function to get the selected layer and metadata. New managers will be required in C++ because actually these information are only available in the Lua UI.

The API needs to be integrated in the command line and in the quick script dialog. Currently, they only have an access to the bindings of the kernel entities.

A plugin manager would be required in the lcadluascript library, currently everything is done in the Qt UI library, which makes it inaccessible from the command line.

It would implement methods to start or stop a script, add the bindings, etc... Some needs to be implemented in the UI, for example the method to write a file, which will open a dialog in the GUI, and read console input in the command interface.

The files operations needs to be secure, when a script needs to open or save a file, it will ask the user where is the file, which prevent opening sensitive files.

For the automation scripts, it could operate on the files in a specific folder, like PHP does with open_basedir.

The plugins will all inherit of a Lua class, with a separation between UI functions and rendering functions, so the same plugin could easily be used in the GUI and in the command line.

Implementation of custom entities:

This project will also add custom entities, which could be defined by scripts, with custom interactions. They would be associated to a block for the drawing, and allthe data would be included in the INSERT entity.

I think this is the best representation, because LibreCAD will treat the custom entities like the other CAD programs, which will make the entities always look the same on two different programs, only the interactions won’t be available. If a block is modified outside LibreCAD, it will be visible in LibreCAD too, and they could be regenerated by the user.

This representation is also required because otherwise it would add Lua as a dependency.

The interactions with the custom entities includes:

• New elements in the right click menu

• Apparition of new buttons in the toolbar

• Modification of the entity with their drag points

• New snap points

The kernel require the implementation of Blocks and INSERT entities. The data will be stored in the INSERT entity in the application defined group (code 102). The plugins can define their own code, only one will be reserved for LibreCAD with the plugin name.

Drawing order and optimizations:

A drawing order needs to be added as, actually, it is random. It wasn’t an issue before because we were using only basic entities, but now with the implementation of images, this is also needed.

LibreCAD 3 is redrawing everything each time the cursor is moved, some objects don’t need to be refreshed every time (like the grid). This could be improved by redrawing only what’s needed. For example, moving the cursor should only refresh the temp entities and the cursor.

The last optimization is the transfer between Cairo and Qt. Currently, there are multiple Cairo painters, which are each transferred to a QImage, and a QPainter is drawing each QImage on LCADViewer widget.

The addition of the layers could be done in Cairo and drawn directly in the widget with a custom painter.

Rendering unit tests:

The idea here is to use LibreCAD command line to generate images of rendered entities, and compare them to existing images (what we expect).

We can use a program to compare the differences between the images, but I’m not sure it will be portable. If that’s not possible, we can compare them using subtraction. Removing image2 from image1 should result in a totally black image. The result can be expressed in percentage: 100% – percentage of white pixels which stayed.

Deliverables

• Support of INSERT and BLOCK and custom entities in the kernel and the drawer

• Load and save BLOCK/INSERT/custom entities

• Lua API

• Interactions of the user with the custom entities

• Lua script dialog using the new API

• LibreCAD command line with the new API

• Unit tests

• Documentation of the code and on how to create a script

• Rendering unit tests

• Rendering optimizations

Development schedule

• May 30th – June 4th: I have my finals this week

• June 5th – June 11th : - Add BLOCK and INSERT support in kernel and drawer - Load and save them in DXF files

• June 12th – June 25th : - Move functions from Lua to a C++ class - Create bindings for this class - Create a sandbox for the plugins in C++ - Create a GUI to manage plugins

• June 26th – July 2nd : - Creation of the custom entity in the kernel - Load and save them in DXF files

• July 3rd – July 9th: - Interactions of the user with the custom entities

• July 10th – July 16th: - Add the Lua API to the Lua script dialog and to the command line

• July 17th – July 23rd : - Update of the current scripts to add new features - Make the current scripts compatible as a LibreCAD plugin, as a quick Lua script, and as a command line plugin

• July 24th – July 31st: - Documentation on how to create a script

• August 1st – August 6th : - Create unit tests to compare rendered entities with images of expectation

• August 7th – August 13th : - Optimizations of LibreCAD drawing - Create drawing order

• August 14th – August 21st: - Code verification - Code optimization - Writing of missing unit tests - Writing of missing documentation

Milestones

• BLOCK and INSERT support in LibreCAD • Lua API • Custom entity support in LibreCAD • Update of plugins to add new features • Documentation on script creation • Rendering modifications and unit tests