Synfig developers docs

Synfig developers

May 26, 2021

Contents:

1 Contributing guidelines 3 1.1 Ways to contribute...... 3 1.2 Contributing code changes...... 4 1.3 Thank You...... 6

2 Setting up your preferred IDE7 2.1 Setting up Netbeans IDE for Synfig Development...... 7 2.2 Setting up QtCreator IDE for Synfig development...... 12

3 Code structure 17 3.1 Overview...... 17 3.2 synfig-core...... 18

4 Building Synfig using command line 25 4.1 Dependencies...... 25 4.2 Preparing Environment...... 26 4.3 Building Synfig using Autotools...... 29 4.4 Building Synfig Using CMake...... 31

5 Packaging Synfig for distribution 33 5.1 Packaging using Autotools...... 33 5.2 Packaging using CMake...... 34

6 Tutorials 37 6.1 Adding a Render progress bar...... 37 6.2 Adding a Sound notification...... 42 6.3 Creating a custom widget...... 45 6.4 How to add new Dock Window...... 46

7 Release procedure 49 7.1 Preparation...... 49 7.2 Apply latest translations...... 49 7.3 Update NEWS files...... 49 7.4 Update version number...... 50 7.5 Build packages...... 50 7.6 Write press release...... 50 7.7 Finish repository changes...... 50

i 7.8 Publish packages...... 51 7.9 Update flatpak and snap packages...... 51 7.10 Publish announcement...... 51 7.11 Close related bugs...... 52

8 Roadmap 53 8.1 Rendering...... 53 8.2 Bones system...... 53 8.3 tools...... 53 8.4 Sound...... 54 8.5 Other...... 54

9 Google Summer of Code 55 9.1 Google Summer of Code 2019...... 55 9.2 Google Summer of Code 2020...... 63 9.3 Google Summer of Code 2021...... 72

10 Projects 81 10.1 Control handling exported values during copy-pasting [IN PROGRESS]...... 81 10.2 Google Season of Docs [DECLINED]...... 82 10.3 Export for web via Lottie [IN PROGRESS]...... 83 10.4 Better Shortcuts [DRAFT]...... 104 10.5 Skeleton Tool (GSoC-2020) [IN PROGRESS]...... 105

11 List of hotkeys 107 11.1 Global hotkeys...... 107 11.2 Local hotkeys...... 107

12 Random notes 109 12.1 Building Synfig for production...... 109 12.2 How to login to docker image?...... 109

13 Code of Conduct 111 13.1 Values we Appreciate...... 111 13.2 Our Pledge...... 112 13.3 Our Standards...... 112 13.4 Our Responsibilities...... 112 13.5 Scope...... 112 13.6 Enforcement...... 113 13.7 Attribution...... 113

14 Indices and tables 115

ii Synfig developers docs

Note: IMPORTANT Please have a look at our contributing guidelines here

Contents: 1 Synfig developers docs

2 Contents: CHAPTER 1

Contributing guidelines

Hi there! Interested in contributing to Synfig? We’d love your help. Synfig is an open source project, built one contribution at a time by users like you. Please read these guidelines carefully, it will help you and us to save precious time later. As you prepare to join our community, you should find out what this project is about - if you didn’t do this already. We highly recommend to become familiar with existing Synfig functionality before you start any coding. You can start with beginner’s tutorials. Also, you can request a free access to our video training course, which allow you to grab all basics in the shortest time.

Note: • Download Synfig -> https://www.synfig.org/download-stable/ • Join Synfig Forum -> https://forums.synfig.org/ • We use GitHub to manage our repository. If you’re not familiar with git/GitHub, we strongly recommend following a tutorial, such as this one.

1.1 Ways to contribute

Whether you’re a developer, a designer, or just a Synfig devotee, there are lots of ways to contribute. Here’s a few ideas: • Install Synfig on your computer and kick the tires. Does it work? Does it do what you’d expect? If not, open an issue and let us know. • Comment on some of the project’s open issues. Have you experienced the same problem? Know a work around? Do you have a suggestion for how the feature could be better? • Read through the documentation, and ask the community(on forum or GitHub), any time you see something confusing, or have a suggestion for something that could be improved.

3 Synfig developers docs

• Browse through the Synfig discussion forum, and lend a hand answering questions. There’s a good chance you’ve already experienced what another user is experiencing. • Find an open issue (especially those labeled help wanted/good first issue), mention yourself in the comment with the interest to work on the issue and submit a proposed fix. If it’s your first pull request, we promise we won’t bite, and are glad to answer any questions. • Help evaluate open pull requests, by testing the changes locally and reviewing what’s proposed. • Open an issue if you found something that needs a fix (Please don’t forget to mentioned if you want to work on the issue you opened or have started working for a fix!)

Note: • Synfig issue tracker -> https://github.com/synfig/synfig/issues • Some beginner issue to ensure you can use synfig.. • Want easy projects? Check out our list of “good first issues”.

1.2 Contributing code changes

1.2.1 1. Get code and prepare your working tree

Warning: • Before you start working on any issue kindly ensure that someone else is not already working on it by looking at comments. • If no one is working on that issue drop a comment to let everyone know you will be working on it. • We know your time is precious :)

Fork the project by clicking “Fork” in the top right corner of synfig/synfig. Clone the repository locally git clone https://github.com//synfig

Create a new, descriptively named branch to contain your change git checkout-b my-awesome-feature

1.2.2 2. Making code changes

Learn how to build Synfig here - https://synfig-docs-dev.readthedocs.io/en/latest/common/building.html Make sure to read about code structure - https://synfig-docs-dev.readthedocs.io/en/latest/common/structure.html Don’t forget to configure IDE. We recommend to use NetBeans. Here are video instructions on how to configure it - https://www.youtube.com/watch?v=SNkdiSxBV_s Now, have fun, hack away. • make sure to follow the code style used in the module you are contributing to

4 Chapter 1. Contributing guidelines Synfig developers docs

• before committing and pushing the changes, test the code both manually and automatically with the automated test suite if applicable

1.2.3 3. Commit message style guidelines

When done, commit your changes. • commits should be descriptive in nature • the message should explain the nature of the change

1.2.4 4. Submitting a pull request

• The smaller the proposed change, the better. If you’d like to propose two unrelated changes, submit two pull requests. • The more information, the better. Make judicious use of the pull request body. Describe what changes were made, why you made them, and what impact they will have for users. • If this is your first pull request, it may help to understand GitHub Flow. Push the branch (you have created it) to your GitHub fork: git push origin my-awesome-feature

Create a pull request (from now on we will shorten it often to just PR) by visiting https://github.com//synfig and following the instructions at the top of the screen: • from your forked repository of the project select your branch and click “New Pull Request” • check the changes tab and review the changes again to ensure everything is correct • write a concise description of the PR, if an issue exists for

Note: While creating the PR please mention the issue number. For example, to close an issue numbered 123, you could use the phrase “Closes #123” or “Closes: #123” in your pull request description or commit message. Once the branch is merged into the default branch, the issue will close.

• after submitting your PR, check back again whether your PR has passed our required tests • if the tests fail for some reason, try to fix them and if you get stuck ask for help. • if the tests pass, maintainers will review the PR and may ask you to improve details or changes, please be patient: creating a good quality open source project takes a bit of sweat and effort; ensure to follow up with this type of operations • once everything is fine with us we’ll merge your PR

1.2.5 5. Avoiding unnecessary changes

• while making changes to the required files, then saving it and comitting it, different contributors often find that there occur same changes that they have not made and those changes gets committed with the desired change that the person wants to make • these unnecessary changes should be evaluated first before the commit should be made

1.2. Contributing code changes 5 Synfig developers docs

• these changes generally occur due to different settings and customizations of your editor that you are working with. These changes are produced on their own as soon as you save a file. Examples are - Introducing new lines, removing and adding spaces, etc • to avoid such changes please check your editor settings first. If this sort of behaviour persists please use any command line editor like VIM, etc

1.3 Thank You

If you follow these guidelines closely your contribution will have a very positive impact on the Synfig project. Thanks a lot for your patience.

6 Chapter 1. Contributing guidelines CHAPTER 2

Setting up your preferred IDE

Integrated Development Environment (or just IDE) is a powerful tool for programmers to maximize their coding productivity. One can debug and test while at the same time utilize all the cool editing features provided by an IDE. Since most modern IDEs are equipped with CMake support out of the box or installed as extensions/plugins, fortu- nately, Synfig has a working CMake build script. That means you can literally configure any of those CMake supported IDEs for Synfig development. Choose your preferred IDE for Synfig development:

2.1 Setting up Netbeans IDE for Synfig Development

2.1.1 Prerequisites

1. Clone synfig repo 2. Execute 1-setup-.sh script to install build tools and dependencies 3. Install Oracle’s Java 8 or Open JDK v8

Note: TL;DR You can also refer to this video tutorial -> https://youtu.be/op-PShrJTCM

2.1.2 Installation

The Apache Netbeans IDE is recommended for Synfig Studio development. The Installer automatically prepares the IDE so that it comes with all required plug-ins, the correct workspace encoding settings, pre-configured code formatters and more. Simply follow these steps: • Download the Netbeans Installer. • Launch the Netbeans IDE and go to tools -> plugins.

7 Synfig developers docs

• Go to Settings tab and enable Netbeans 8.2 plugins portal:

• Go to Available plugins and click on check for newest. • Now select and install C/C++ plugin:

2.1.3 Setup New Synfig Project

IDE Installation is now completed so let’s configure our new synfig project. • Click file -> new project

8 Chapter 2. Setting up your preferred IDE Synfig developers docs

• Select C/C++ and C/C++ Project with Existing Source:

• Select your synfig source file directory • Under Select configuration mode select custom and press next:

• Click next and skip the Pre Build Action(do not check any option).

2.1. Setting up Netbeans IDE for Synfig Development 9 Synfig developers docs

• Under Build Action uncheck the clean and build after finish and click next:

• Now click next on step 5 and step 6 without making any changes. • Click finish:

10 Chapter 2. Setting up your preferred IDE Synfig developers docs

2.1.4 Setting up make configuration

Now we will configure make settings for our synfig project. • Right click on project(Synfig) and select properties:

• Under Build -> make section change Build result so that it points to “_debug/build/bin/synfigstudio”:

• Press apply and ok. Yay! your Netbeans IDE is now configured and you can use all the functionalities including debugging etc.

2.1. Setting up Netbeans IDE for Synfig Development 11 Synfig developers docs

2.2 Setting up QtCreator IDE for Synfig development

2.2.1 Prerequisites

1. Clone synfig repo 2. Execute 1-setup-.sh script to install build tools and dependencies

2.2.2 Installation

For users, you can install qtcreator using your distribution’s package management tool. For Windows and Mac users, you can download and install open source version of qtcreator from Qt’s official website.

2.2.3 Setup new Synfig project

• Select Open project

• Browse and select CMakeLists.txt

12 Chapter 2. Setting up your preferred IDE Synfig developers docs

• Manage your kit For most users, you can select and use the default kit usually named Desktop. But if you want to use another generator (say Ninja) and not the one provided by the default kit (Makefiles), you can create your own kit and name it Synfig or any other name of your choice.

• Manage your build path QtCreator tends to generate build directory above our source directory. If that’s OK with you than you can skip this part and proceed with Configure Project. But if you’re someone who has multiple projects inside your preferred root project directory, QtCre- ator generating build directories in our root directory might become messy later in the future because you’d have to deal with multiple directories as your project lists grows. Once you’re done, select Configure Project.

2.2. Setting up QtCreator IDE for Synfig development 13 Synfig developers docs

2.2.4 Setup make configuration

• Set processor count Depending on your generated build files, the build system might utilize parallelism during build process or it might run only on one CPU. If you want to control the number of CPUs to be utilized by CMake during build process you can set it from Projects > Build > CMake arguments. For instance, if you’ve a quad-core processor, you can use -j 4

• Change run configuration QtCreator, by default, sets synfig_bin to be run as our output but usually we are testing the GUI frontend so change it to synfigstudio from Projects > Run > Run configuration

2.2.5 File browser

• File system To browse your project files, change File System sub-menu from Computer to synfig-studio. That way you’ll be able to see all the source files, resources, translation files, etc as it is in your file system.

14 Chapter 2. Setting up your preferred IDE Synfig developers docs

2.2. Setting up QtCreator IDE for Synfig development 15 Synfig developers docs

2.2.6 Source code indentation

• Use tab character Synfig source files mainly C++ and CMake use tab character for indentation. QtCreator might use spaces by default depending on platforms or versions. Change C++ code style settings to Tabs Only. You could also duplicate built-in settings and make changes to preserve default settings.

You’re all done :) Happy hacking!

16 Chapter 2. Setting up your preferred IDE CHAPTER 3

Code structure

3.1 Overview

Synfig is divided into three components: ETL, synfig-core and synfig-studio. • ETL is a template library that implements reference counting, portable threading and other low-level stuff. Every part of the Synfig project uses ETL in some way. It is like the C++ STL. • synfig-core is Synfig’s backend. It renders scenes and knows how to read and write Synfig XML files. This directory contains the Synfig library and the Synfig command-line tool. • synfig-studio is the graphical editor. It uses the GTK+ widget library. If you want to hack on the interface, this is what you should look at. The structure of synfig-core is: • synfig-core/src/synfig/ - Code of “libsynfig” library. This is actually the main part of synfig-core. It contains code of render engine and routines for reading/writing Synfig’s files. The libsynfig library is used by all other Synfig’s components. • synfig-core/src/modules/ - Functionality of libsynfig can be extended with modules and this directory is a place for them. A module can do following things:

– Add support for importing specific file format(s). Examples:

* synfig-core/src/modules/mod_png/mptr_png.cpp * synfig-core/src/modules/mod_bmp/mptr_bmp.cpp – Add support for exporting (rendering) to specific file format(s). Examples:

* synfig-core/src/modules/mod_png/trgt_png.cpp * synfig-core/src/modules/mod_gif/trgt_gif.cpp – Implement a layer type(s). Examples:

* synfig-core/src/modules/mod_geometry/circle.cpp - Circle Layer * synfig-core/src/modules/lyr_freetype/lyr_freetype.cpp - Text Layer

17 Synfig developers docs

* synfig-core/src/modules/mod_noise/distort.cpp - Noise Distort Layer – Implement a valuenode (see below on valuenodes). Example:

* synfig-core/src/modules/mod_noise/valuenode_random.cpp • synfig-core/src/tool/ - Code of synfig command-line tool (binary is simply called synfig). It uses libsynfig to read Synfig files and render them in any supported format. Main components of synfig-studio: • synfig-studio/src/synfigapp/ - Code of libsynfigapp library. This is a layer between GUI and libsynfig (from synfig-core). It contains code for actions - operations that transform loaded Synfig’s file in some way. When user makes some change to Synfig file in GUI, then an action is called that does the actual modification. • synfig-studio/src/gui/ - Code of GUI written in . This defines how application looks and behave. So, we have following structure: gui---> libsynfigapp------> libsynfig

synfig-cli------> libsynfig

3.2 synfig-core

3.2.1 Layers

The basic building block in Synfig is Layer.

Note: synfig-core/src/synfig/layer.cpp

Layer either displays some graphical information on the screen (circle, line, text, etc.) or does some transformation of graphic information under it - i.e. acts as filter (blur, translation, noise distortion, etc.).

Note: Built-in layers: • synfig-core/src/synfig/layers/ Layers as modules: • synfig-core/src/modules/lyr_std • synfig-core/src/modules/lyr_freetype • synfig-core/src/modules/mod_example • synfig-core/src/modules/mod_geometry • synfig-core/src/modules/mod_gradient • synfig-core/src/modules/mod_noise • synfig-core/src/modules/mod_particle

18 Chapter 3. Code structure Synfig developers docs

Layers are placed in particular order.

- Layer3 - Layer2 - Layer1

Layers are rendered from bottom to top.

3.2.2 Context and Blend Methods

All graphics information under particular layer is called its Context. In example above Layer 2 together with Layer 1 are context of Layer 3. If Layer 3 is a graphic layer, then it displays some graphic information, which is composed with its context (Layer 1 and Layer 2). The way how Layer 3 composed with its context is defined by layer’s Blend Method.

Note: synfig-core/src/synfig/color/ TODO: Add link to list of available blend methods

If Layer 3 is a filter layer, then it transforms graphic information created by Layer 1 and Layer 2.

3.2.3 Canvas

A structure which stores a list of layers is called Canvas.

Note: synfig-core/src/synfig/canvas.cpp

A canvas can also store other canvases. This is how layers organized into hierarchy. In GUI canvases represented by Groups, but in code they are called Paste Canvases. Past Canvas is a special type of layers, which holds Canvas of other layers.

Note: synfig-core/src/synfig/layers/layer_pastecanvas.cpp

Every Synfig file has a Root Canvas, which contains all layers. Also it can have several Exported canvases - a separate canvases that are outside of Root Canvas. Paste Canvas can be inline (i.e. include all its content in itself) or linked (i.e. reference content from exported canvases or other Synfig files).

Note: Loading Synfig file: synfig-core/src/synfig/loadcanvas.cpp Saving Synfig file: synfig-core/src/synfig/savecanvas.cpp

3.2. synfig-core 19 Synfig developers docs

3.2.4 ValueNodes

Every layer has a set of Parameters, which define how layer is rendered (and what it is rendering). In simplest case layer parameter can be defined by a value of particular type - ValueBase (Integer, Real, Bool, Color, etc).

Note: synfig-core/src/synfig/base_types.cpp

In complex case parameter can be defined by ValueNode. ValueNode is a formula that produces a value from some calculations. Each ValueNode has parameters that define input data for formula. Parameters of ValueNode can also be represented by ValueBases (static value) or ValueNodes (calculated value), so it is possible to construct nested formulas.

Note: synfig-core/src/synfig/valuenodes/ synfig-core/src/modules/mod_noise/valuenode_random.cpp

It is possible to link ValueNodes and ValueBases among different parameters (and among different layers). I.e. for two circle layers A and B we can link their Radius parameters (both static values, ValueBase). In this case, changing radius of one circle will change radius of another (see https://wiki.synfig.org/Doc:Getting_Started#Linking). In more complex case we can have Radius parameter of circle A defined by Scale ValueNode. The Scale ValueNode have two parameters - “Link” and “Scalar”. If “scalar” parameter is set to static value 2.0 and “Link” parameter is linked to “Radius” value of circle B, then circle A will always have a radius twice bigger than circle B. TODO: Make an illustration of layers sharing same ValueNodes/ValueBases Among all different ValueNodes there is a special ValueNode, which deserves a special attention - it is called “Ani- mated”.

Note: synfig-core/src/synfig/valuenodes/valuenode_animated.cpp synfig-core/src/synfig/valuenodes/valuenode_animated.h synfig-core/src/synfig/valuenodes/valuenode_animatedinterface.cpp synfig-core/src/synfig/valuenodes/valuenode_animatedinterface.h

This ValueNode stores multiple values of parameter for different moments of time and calculates interpolated values between them.

3.2.5 Rendering process

When Synfig needs to render a frame it starts by evaluating parameters of layers. If a parameter is ValueNode (calcu- lated value), then it evaluates its parameters. This process works recursively, going all the way down to the leaf nodes, calculating their value, then calculating the value of their parent, and so on until reaching the root of the node tree. Since ValueNodes can be animated (meaning that they can change value at different points of time), so the entire tree needs to be evaluated on each frame. Once a layer has the values for it’s parameters, it renders the intended shape or effect onto a raster. A raster is an array of pixels, each pixel with its color/opacity. It doesn’t carry any information about the vector shapes that it’s representing, only their pixel data.

20 Chapter 3. Code structure Synfig developers docs

Then comes blending. The raster result of the previous layers is combined with the current one according to the set blending method. Some layers (transforms, distortions, etc) just modify the raster result of the previous layers and pass that on to the next layer, instead of blending. Note that a layer sees all the layers underneath as a single combined raster. That layer cannot distinguish the pixel data that comes from the next layer that’s underneath, from pixel data from any other layer that’s underneath.

On diagram: “V” stands for ValueNodes, “L” for layers, “BL” for blank layer (completely transparent layer default background), “BM” for blend method.

3.2.6 Render engine

Now, let’s talk about render engines. In fact there are two of them now. The new one (called “Cobra”) is the our latest development and it is the future of Synfig. And there is an old one (without a name). As of version 1.2.0 it is deactivated. But some layers are still use its code, in case if they are not ported to Cobra yet (Synfig fallbacks to old render engine). This generally works much slower comparing to case when layer’s code is ported to Cobra. If you examine code of any layer, you will see a function called accelerated_render() - this is a code of old render engine. Old rendering engine examines stack of layers in two passes. First, it is going from top to bottom and applies required transformations (when possible). Also, it defines required context for rendering each layer. On second pass it goes from bottom to top. It is doing actual rendering for each layer and mixing it according to Blend Method with previous layers (context). I.e., if we have Stretch Layer on top of Shape Layer, then on first pass Synfig goes down and applies stretch to all vertices of Shape Layer, thus eliminating Stretch from operations. Then on rendering stage it renders Shape Layer only (as stretch is already applied on first pass).

3.2. synfig-core 21 Synfig developers docs

On the other hand, if we have Blur Layer between Stretch Layer and Shape Layer, then it is not possible to apply Stretch (because Blur is a raster-based effect). So it doesn’t eliminates Stretch on first pass. On second pass it renders all 3 layers - Shape, then blurs it and finally stretches result. Now, let’s talk about Cobra engine, which is more advanced.

Note: The code of Cobra render engine is located in /synfig-core/src/synfig/rendering

Its main concepts are: Task, Queue, Optimizer, Sub-Engine and Renderer. Task is the main primitive of Cobra render engine that does something. This is like Layer in Synfig’s concept, but even more simple/low-level. I.e. there is a task for blending, task for drawing filled region, task for affine transformation, etc. For example, Outline and Region Layers are executed by the same task - the one that drawing filled region (Task Contour).

Note: synfig-core/src/synfig/rendering/common/task/ synfig-core/src/synfig/rendering/software/task/ synfig-core/src/synfig/rendering/opengl/task/

So, why we need both Tasks and Layers? How do both concepts relate to each other? Layers are good for user (they help to construct and organize animation document) and Tasks are good for render engine (they are not good for editing, but allow to render animation document as fast as possible). Tasks describe user’s animation document in a low-level form, in a language that is suitable for render engine. In a very simple view Cobra render engine also works in two passes. In first pass it takes a tree of Layers, and constructs a Queue of Tasks. In second pass it executes tasks in Queue (does rendering).

Note: synfig-core/src/synfig/rendering/renderqueue.cpp

Queue is a linear list, but Tasks can have dependencies. I.e. task A can depend on task B and C. That means when render engine processes Queue, it skips task A unless tasks B and C are ready. The task A is executed in next pass, after B and C are done. This allows to organize parallel (multi-threaded) rendering. When Cobra does its first pass (transforms Layers to Queue of Tasks) it applies Optimizers. Optimizers are analyzing list of tasks and re-organizing it to speedup rendering process.

Note: synfig-core/src/synfig/rendering/common/optimizer/

For example, there is an optimizer that looks for a sequences of Region/Outline Layers which could be merged into one task and thus rendered in single pass (without intermediate blending functions). Now let’s get to Sub-Engines. It is clear there is a possibility to implement one particular task in different ways. For example, we can draw a vector region using straight-forward CPU calculations (software method), or activate OpenGL and use its functions to draw the same shape using videocard (hardware-accelerated). In the same fashion, we can do Gaussian blur operation with straight-forward CPU calculations, or utilize hardware- accelerated methods. So, all tasks are grouped by implementation method, forming a Sub-Engines.

22 Chapter 3. Code structure Synfig developers docs

Currently we have 2 sub-engines - “software” (the main one, all tasks done with calculations on CPU) and “OpenGL” (all tasks are hardware-accelerated using OpenGL, it is currently broken). • Software Sub-Engine - `synfig-core/src/synfig/rendering/software/` • Tasks of Software Sub-Engine - `synfig-core/src/synfig/rendering/software/task/` • OpenGL Sub-Engine - `synfig-core/src/synfig/rendering/opengl/` • Tasks of OpenGL Sub-Engine - `synfig-core/src/synfig/rendering/opengl/task/ Generally, it is possible one Sub-Engine can use tasks from other Sub-Engine. I.e., when OpenGL Sub-Engine is active and there is some task missing, then it can be replaced by task from Software Sub-Engine. Each Sub-Engine can have several configurations with different set of Optimizers. We call those configurations Ren- derers - and this is what user actually see when choosing renderer via “Edit” -> “Preferences. . . ” -> “Render”.

For example, “Draft” and “LowRes” rendering modes are just Renderers of Software Sub-Engine.

Note: • Default Software Renderer - synfig-core/src/synfig/rendering/software/renderersw. cpp • Safe-mode Software Renderer (not uses Optimizers) - synfig-core/src/synfig/rendering/ software/renderersafe.cpp • Draft Software Renderer - synfig-core/src/synfig/rendering/software/ rendererdraftsw.cpp • LowRes Software Renderer - synfig-core/src/synfig/rendering/software/ rendererlowressw.cpp

3.2. synfig-core 23 Synfig developers docs

Now, let’s get back to Layers. We already know how Layers define their rendering for old render engine. But how this done for Cobra render engine? If layer is ported to Cobra engine, then you will see build_rendering_task_vfunc() or build_composite_task_vfunc() or build_composite_fork_task_vfunc() functions. So, in Cobra engine layers just use tasks as building blocks to construct structures which produce required output.

24 Chapter 3. Code structure CHAPTER 4

Building Synfig using command line

4.1 Dependencies

List of dependencies required for building Synfig: • autoconf (build-time) • automake (build-time) • adwaita-icon-theme • boost (system module) • fftw3 • gettext • glibmm-2.4 • gtkmm-3.0 • imagemagick (optional) • intltool (build-time) • JACK (optional, Linux-only) • Magick++ (optional) • libxml++-2.6 • libsigc++-2.0 • mlt++ • pango • pkg-config (build-time) • SDL2_mixer • zlib

25 Synfig developers docs

4.2 Preparing Environment

Building Synfig requires many dependent libraries installed for your system. For full list of libraries please refer to this page. Below you will find instructions how to install them on various operating systems.

4.2.1 Linux

First of all make sure you have “git” installed. Use it to fetch Synfig’s sources:

$ git clone https://github.com/synfig/synfig.git ~/synfig.git

Then navigate to sources directory:

$ cd ~/synfig.git

Now you need to install all required dependencies. This is easy to do by running a special script shipped with Synfig’s sources:

$ ./1-setup-linux-native.sh

Wait till the script finish installing dependencies and you’re ready to build.

4.2.2 OSX

We will be running all commands in terminal, so start by launching Terminal app. First you need to install Xcode Command Line Tools with the following command:

$ xcode-select --install

Follow instructions on the screen to complete installation. Next, get Synfig’s sources:

$ git clone https://github.com/synfig/synfig.git ~/synfig.git

When download finishes, navigate to sources directory:

$ cd ~/synfig.git

Now we can install all required libraries via HomeBrew. There is a special script included with sources:

Warning: It is NOT recommended to use this method on OSX version < 10.11 with already working Homebrew - with almost 100% probablility your Homebrew installation will be damaged. You’ve been warned. For more details about this issue see here - https://github.com/synfig/synfig/blob/ 678cc3a7b1208fcca18c8b54a29a20576c499927/1-setup-osx-brew.sh#L34-L37

$ ./1-setup-osx-brew.sh

26 Chapter 4. Building Synfig using command line Synfig developers docs

Depending on version of your system the process of installing dependencies might take some time. When it completes you are ready to build Synfig!

Note: If you are having problems with slow download speed of brew packages, check to see if your ISP is blocking some IP addresses. For example, in Russia Roskomnadzor blocks some IP addresses (https://isitblockedinrussia.com/ ?host=54.192.98.189) used by the Homebrew CDN (they use Cloudfront servers). This leads to long connection timeouts. To fix this, you can restrict the curl connect-timeout parameter. This is how I fixed it:

$ echo "--connect-timeout 1" >> ~/.curlrc $ export HOMEBREW_CURLRC=1

P.S. Quick hack if you certificates outdated, and brew can’t download packages:

$ echo "--insecure" >> ~/.curlrc $ export HOMEBREW_CURLRC=1

4.2.3 Windows

Note: For compiling Synfig on Windows we use MinGW installation in MSYS2 environment. Alternative for that approach could be to build using MSVC and Microsoft vcpkg (https://github.com/microsoft/ vcpkg), but we haven’t digged into that yet. Any help on this matter is appreciated here - https://github.com/synfig/ synfig/issues/860.

Download and install MSYS2, following instructions here - http://www.msys2.org/. Make sure to select the correct MSYS as per your needs.

4.2. Preparing Environment 27 Synfig developers docs

Always use the proper shell: • MinGW32 for compiling 32-bit Synfig. • MinGW64 for compiling 64-bit Synfig. • Never use the MSYS shell for compiling Synfig. After picking the needed MSYS Shell.

$ pacman -S git

Next, get Synfig’s sources:

$ git clone https://github.com/synfig/synfig.git ~/synfig.git

When download finishes, navigate to sources directory:

$ cd ~/synfig.git

Now you need to install all required dependencies. Run a special script shipped with Synfig’s sources:

$ ./1-setup-windows-msys2.sh

Wait till the script finish installing dependencies. Now install CMake and Ninja with: • For MINGW32:

$ pacman -S mingw-w64-i686-cmake mingw-w64-i686-ninja

28 Chapter 4. Building Synfig using command line Synfig developers docs

• For MINGW64:

$ pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja

When it completes you are ready to build Synfig!

4.3 Building Synfig using Autotools

4.3.1 Things to know before you start

Synfig is divided into three components: ETL, synfig-core and synfig-studio. • ETL - the extended template library. • synfig-core - contains the render engine and core/command-line tool (cli) • synfig-studio - gui for the application. All those three components are included with the main source repository of Synfig - https://github.com/synfig/synfig. git. ETL is required for synfig-core and synfig-core is required for building synfig-studio. So, first builds ETL, then synfig-core, and then synfig-studio.

4.3.2 First build

We have a special script, which carries all build routines for you. In fact, there are two of them - “2-build-debug.sh” and “2-build-production.sh”. As you might guess, the first one is for building development version with debug symbols (useful for development itself) and the second one is without debug symbols (useful for production). Another difference is that first script places result of the build in “_debug/build” subdirectory, and with second script the result will reside in “_production/build”. In all other aspects both scripts work exactly the same and accept the same arguments. I will assume that your intention is to develop Synfig, so let’s continue with first script - “2-build-debug.sh”. You can build everything by simply executing the script:

$ ./2-build-debug.sh

The script will build and install ETL, then synfig-core and finally - synfig-studio. When building is done, you can launch Synfig by executing

$ ~/synfig.git/_debug/build/bin/synfigstudio

4.3.3 Re-building your changes

Of course it is not very efficient to run a full rebuild process on every change. So, the script provides a set of arguments that allow you to execute particular stages of the build: The syntax is:

4.3. Building Synfig using Autotools 29 Synfig developers docs

$ ./2-build-debug.sh [package] [phase] where • [package] can have following values: – all - builds all three packages (default). – etl - builds ETL only. – core - builds synfig-core only. – studio - builds synfig-studio only. • [phase] allows you to choose particular phase to execute for given package: – clean - does “make clean” operation. – configure - running “./configure” script with all necessary options. – make - running “make” command and “make install”. – build - executes “configure” and “make” phases (default). – full - executes all phases: “clean”, “configure” and “make” (exactly in that order). You might ask: why execute those commands/phases from a script , while it is possible to call “./configure” and “make” commands by hand in particular directories? Well, for “make” this would work and is desirable for many cases. But for “./configure” you have to specify many parameters, such as prefix, and locations of some dependent libraries. So it is more convenient to call “./configure” using this helper script. Examples: 1. Configure and (re)build synfig-core (executes “./configure”, “make” and “make install”):

./2-build-debug.sh core equivalent to:

./2-build-debug.sh core build

2. Do a full clean build of synfig-core (executes “make clean”, “./configure”, “make” and “make install”):

./2-build-debug.sh core full

3. Quick rebuild of synfig-core (without executing “./configure”):

./2-build-debug.sh core make

Since “make” doesn’t require any parameters, the same result can be achieved by executing: cd~/synfig.git/_debug/synfig-core/ make install

4. Quick rebuild of of everything - ETL, synfig-core and synfig-studio (without executing “./configure”):

./2-build-debug.sh all make

Here are some recommendations when to call particular phases: Considering the structure of Synfig (see first chapter of this article), we have following dependency chain: synfig-studio -> synfig-core -> ETL

30 Chapter 4. Building Synfig using command line Synfig developers docs

So, you should follow this logic: • when change is made to ETL, then rebuild everything - ETL, synfig-core and synfig-studio; • when change is made to synfig-core, then you need to rebuild synfig-core and synfig-studio only; • when change is made to synfig-studio, then you have to to rebuild synfig-studio only; You might notice that if you rebuild simply by running “make install” that takes considerably less time than when you do a ful-cycle rebuild with “./configure” and then “make install”. So, when it is safe to skip “./configure”? The answer is: if you edited .h and .cpp files only, then it is safe to skip. In all other cases it is safer to re-start ./configure on rebuilding. Let’s suppose you made changes in synfig-studio (only .h and .cpp files) and want to rebuild it. The following command is enough:

./2-build-debug.sh studio make

And finally a quick note about “build.conf.sample” file in the root of source repository. With this file you can tweak the number of threads used by the build scripts. Just copy “~/synfig.git/build.conf.sample” to “~/synfig.git/build.conf” and adjust its contents according to your needs.

4.4 Building Synfig Using CMake

The usual process of building with CMake is pretty much the same as the standard one, but despite that, this part will cover that so you can follow along and get the same results. Below you will find instructions how to build Synfig on various operating systems.

4.4.1 Linux

You need to make a directory where Synfig will be built.

$ mkdir cmake-build && cd cmake-build

Once you’re in your build folder, this is the part where you can configure and set different CMake flags according to your need. For the purpose of this documentation, the default build will be followed.

$ cmake ..

When it completes, you need to build Synfig using make command.

$ make

Once this is complete, you will find the build present in /output folder of your build directory. You can run Synfig by using

$ ./output/bin/synfigstudio

You can also specify a target if you want to build that specific target.

$ make build_images

4.4. Building Synfig Using CMake 31 Synfig developers docs

If you wish to install Synfig to /usr/local/, make sure you have root privileges (or write permissions to those three directories), and simply type

$ make install

4.4.2 OSX

Building on OSX follows the same steps as that of Linux. You need to make a build folder first.

$ mkdir cmake-build && cd cmake-build

Once that’s done, you can run the CMake command along with passing any flags as required.

$ cmake ..

When it completes, you need to build Synfig using make command.

$ make

Once this is complete, you will find the build present in /output folder of your build directory. You can run Synfig by using

$ ./output/bin/synfigstudio

4.4.3 Windows

Synfig is shipped with this special script to build it on Windows (MSYS2). All you need to do is run that script.

$ ./2-build-msys-cmake.sh

Once this is completed successfully, you can run Synfig by.

$ ./cmake-build-msys/output/bin/synfigstudio.exe

32 Chapter 4. Building Synfig using command line CHAPTER 5

Packaging Synfig for distribution

5.1 Packaging using Autotools

5.1.1 OSX

You can build OSX package by executing following 3 scripts from Synfig’s source root:

$ ./1-setup-osx-brew.sh $ ./2-build-production.sh $ ./3-package-osx-dmg.sh

Please refer to https://synfig-docs-dev.readthedocs.io/en/latest/common/building.html for details.

5.1.2 Windows and Linux

We have a set of scripts that allow to build Windows installers and Linux Appimages in isolated Docker environment. Both types of packages are built on Linux platform (Windows binaries are built using cross-compilation).

TL;DR;

1. Fetch builder repository:

$ git clone https://github.com/morevnaproject/morevna-builds $ cd morevna-builds

2. Run builder:

$ ./build-synfigstudio.sh

This will fetch Docker image, and build packages for Windows and Linux, 64bit and 32bit. This process involves building all required libraries, so it will take a very long time.

33 Synfig developers docs

After build finishes grab packages from “publish” directory.

Resolving problems

It might happen that compilation fails at some stage. This could be for various reasons. One very common reason could be that updates to builder scripts conflicting with what you already have built before (when using previous versions of this builder). Unfortunately, such cases are hard to track and the easiest workaround is to completely remove “docker-builder-data/build/packet” directory and re-run build script. This will build everything from scratch. If the problem persists, please submit error message to https://github.com/morevnaproject/morevna-builds/issues You can also try to fix problem by yourself by jumping into Docker’s build environment of particular package (the one that failing). Depending on the platform and architecture you do that with specific command: 1. For Linux 64-bit:

$ ./docker/debian-7-64bit/run.sh PACKAGENAME shell

2. For Linux 32-bit:

$ ./docker/debian-7-32bit/run.sh PACKAGENAME shell

3. For Windows 64-bit:

$ ./docker/debian-7-64bit/win64.sh PACKAGENAME shell

4. For Windows 32-bit:

$ ./docker/debian-7-64bit/win32.sh PACKAGENAME shell

Make sure to replace PACKAGENAME with actual package name (script name from docker-builder- data/build/script/packet, without “.sh” at the end).

Directory structure

• “docker-builder-data/build/packet” - directory where build files stored. • “docker-builder-data/build/script/packet” - script files, which tell how to build each particular package. • “docker/debian-7-32bit” - 32-bit Docker environment configuration and scripts. • “docker/debian-7-64bit” - 64-bit Docker environment configuration and scripts.

5.2 Packaging using CMake

As an optional step you might wish to build a package/installer for distribution. Synfig can be packaged for different operating systems using CPack which comes with CMake. First important thing to know is that you need a production build for that (for obvious reason it is very unlikely you want to distribute a build with debug symbols). So, make sure to get production build first by passing the flag at cmake step:

34 Chapter 5. Packaging Synfig for distribution Synfig developers docs

$ cmake .. -D CMAKE_BUILD_TYPE=Release

Most of the configuration are already set so no extra flags need to be set for Synfig. Below you will find instructions how to package Synfig for various operating systems.

5.2.1 Linux

A .deb package for Synfig can be made by using the following code.

$ cpack -G DEB

5.2.2 Windows

A .exe installer for synfig can be made by using the following code.

$ cpack -G NSIS

5.2. Packaging using CMake 35 Synfig developers docs

36 Chapter 5. Packaging Synfig for distribution CHAPTER 6

Tutorials

6.1 Adding a Render progress bar

Now let’s implement a Render Progress Bar! It has been requested several time: • Indication needed that rendering is in progress. #383 • Feature request: Give feedback when rendering is happening and complete #626 • also in Default render parameter are bad #464 Summary • 1 Things to take into account • 1.1 Where to place the Progress Bar? • 1.2 How does really a render work? • 1.3 Where to do calls and implementation? • 2 Implementation • 2.1 synfig-studio/src/gui/docks/dock_info.h • 2.2 synfig-studio/src/gui/docks/dock_info.cpp • 2.3 synfig-studio/src/gui/docks/app.h • 2.4 synfig-studio/src/gui/docks/app.cpp • 2.5 synfig-studio/src/gui/docks/render.cpp • 2.6 synfig-studio/src/gui/docks/asyncrender.cpp

37 Synfig developers docs

6.1.1 Things to take into account

Where to place the Progress Bar?

I chose to implement it in the Dock_Info panel. After all, this is a kind of information!

How does really a render work?

App (.h .cpp) is the root of everything and used to store globals. But we start in fact from CanvasView (.h .cpp) which contains the call to display the RenderSettings Dialog (.h .cpp). Then we press on render button which leads to execute an AsyncRenderer (.h .cpp) (or 2, sequentially, if we have a second pass for Alpha extraction). AsyncRenderer can have 4 types of targets: • AsyncTarget_Cairo • AsyncTarget_Cairo_Tile • AsyncTarget_Scanline • AsyncTarget_Tile Only AsyncTarget_Cairo and AsyncTarget_Scanline have a frame_ready() function that we will use to implement our call to update to the Render ProgressBar. Note that we can have 2 passes, this has to be considered when displaying the percents of accomplished render. The render itself is done writing the data to the target, then the selected codec is fed through a pipe (for example ffmpeg).

Where to do calls and implementation?

In different files, as it is a “multi-level” task. The details are described in each file touched in the next section.

6.1.2 Implementation synfig-studio/src/gui/docks/dock_info.h

Declare the components and members • In #include section:

#include In private section:

Gtk::ProgressBar render_progress;

//! Number of passes request - 1 or 2 (if alpha) int n_passes_requested; (continues on next page)

38 Chapter 6. Tutorials Synfig developers docs

(continued from previous page) //! Number of passes pending - 2,1,0 int n_passes_pending;

• In public section:

//! Current render progress - 0.0 to 1.0 // depends on n_passes_requested and current_pass void set_render_progress( float value); void set_n_passes_requested(int value); void set_n_passes_pending( int value); synfig-studio/src/gui/docks/dock_info.cpp

Here we will implement the UI and members • In #include section:

#include "app.h" #include

It will permit to access our App::dock_info_ as a static from anywhere in the application • In Dock_Info(), at the end: just before table->show_all();

//Render Progress Bar table->attach(*manage(new Gtk::Label(_("Render Progress:"))),0,1,5,6, ˓→Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL); table->attach(render_progress,0,5,6,7,

˓→Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL); render_progress.set_show_text(true); render_progress.set_text(strprintf("%.1f%%", 0.0)); render_progress.set_fraction(0.0); //Another spacer table->attach(*manage(new Gtk::Label),0,5,7,8); and after add(*table);

//Render progress set_n_passes_requested(1); //Default set_n_passes_pending (0); //Default set_render_progress (0.0); //Default, 0.0%

• Then at the end of the file, we add these 3 functions: void studio::Dock_Info::set_n_passes_requested(int value) { n_passes_requested= value; } void studio::Dock_Info::set_n_passes_pending(int value) { n_passes_pending= value; } void studio::Dock_Info::set_render_progress(float value) { (continues on next page)

6.1. Adding a Render progress bar 39 Synfig developers docs

(continued from previous page) float coeff=(1.000/( float)n_passes_requested); //% of fraction for 1

˓→pass if more than 1 pass float already_done= coeff * (float)(n_passes_requested- n_passes_pending-1); float r= ( coeff * value )+ already_done;

render_progress.set_text( strprintf("%.1f%%", r *100 )); render_progress.set_fraction(r); }

The 2 first ones are obvious, the last one does the calculation for the display of the current percents of the WHOLE TASK. If we have only 1 pass, value will be reflected directly. In case of 2 (or more, who knows what will be implemented later!), each pass will still continue to send its progress as if it was the only one in the world; we will do the adjustments here. • 100% of pass 1 while be displayed as 50%. • 100% of pass 2 while be displayed as 100%. • If we had 3 passes, it would be 33.3%, 66.6% and 100.0% synfig-studio/src/gui/docks/app.h

Lets add our static dock_info_.A studio::dock_info is already defined in the .cpp but we need to access it as App::dock_info_! • Inside the static declarations: static Dock_Info* dock_info_; //For Render ProgressBar synfig-studio/src/gui/docks/app.cpp

Let’s declare the static • Inside the declare of statics

Dock_Info* App::dock_info_=0;

• At the end of the constructor App()

App::dock_info_= dock_info;

It looks like some kind of alias! synfig-studio/src/gui/docks/render.cpp

Here the things start to become serious • In the #include section:

#include "docks/dockmanager.h" #include "docks/dock_info.h"

• In RenderSettings::on_render_pressed

40 Chapter 6. Tutorials Synfig developers docs

Just before submit_next_render_pass();

App::dock_info_->set_n_passes_requested(render_passes.size()); App::dock_info_->set_n_passes_pending(render_passes.size()); App::dock_info_->set_render_progress(0.0); App::dock_manager->find_dockable("info").present(); //Bring Dock_Info to front

We initialized our ProgressBar with its default parameters to display 0.0% Note that the Dock_Info will be brought to front to show the progression. . . It’s its goal! • In RenderSettings::submit_next_render_pass() Just after render_passes.pop_back();

App::dock_info_->set_n_passes_pending(render_passes.size()); //! Decrease until 0 App::dock_info_->set_render_progress(0.0); //For this pass

We reinitialized the parameters for this specific pass! Doing tests I noticed that with extract alpha option on, we have 2 passes and therefore the render done sound was played 2 times! Let’s correct this bad behaviour In RenderSettings::on_finished(), around submit_next_render_pass(); bool really_finished= (render_passes.size()==0); //Must be checked BEFORE submit_

˓→next_render_pass(); submit_next_render_pass();

//Sound effect - RenderDone (-1 : play on first free channel, 0 : no repeat) if (App::use_render_done_sound) Mix_PlayChannel(-1, App::gRenderDone,0); if (really_finished) { //Because of multi-pass render if (App::use_render_done_sound) Mix_PlayChannel(-1, App::gRenderDone,0); App::dock_info_->set_render_progress(1.0); }

This way, it will play only once the full render has occured! synfig-studio/src/gui/docks/asyncrender.cpp

Now the deepest part • In #include section:

#include In the beginning of *AsyncRenderer::start()*

App::dock_info_->set_render_progress(0.0);

• In void frame_ready() of both AsyncTarget_Cairo and AsyncTarget_Scanline After ready_next=true; int n_total_frames_to_render= warm_target->desc.get_frame_end() //120 - warm_target->desc.get_frame_start() //0 +1; //->121 int current_rendered_frames_count= warm_target->curr_frame_ - warm_target->desc.get_frame_start(); float r=( float) current_rendered_frames_count (continues on next page)

6.1. Adding a Render progress bar 41 Synfig developers docs

(continued from previous page) /( float) n_total_frames_to_render; App::dock_info_->set_render_progress(r);

Here the current progress is calculated according the starting, ending and current frame, in a range of 0.0 to 1.0 The pass (or target) thinks it is the only one in the world but it is compensated in the display :)

Hoping this will help you to come and join the effort in development of Synfig :)

6.2 Adding a Sound notification

After the implementation of #648 - GUI: Play a sound when rendering is done, it could be useful to keep a track of the way to implement a new sound notification in SynfigStudio This tutorial will be divided in 2 parts: • Adding the sound notification • Adding an option to Preferences dialog

6.2.1 Adding the sound notification

synfig-studio/sounds/

• Add your sample in this directory in your source tree. • Add a notice about the license of your sample in readme.txt (the asset should have a permissive license) • Add your sound sample to the list in Makefile.am synfig-studio/src/gui/app.h

Declare the sound (Mix_Chunk*) as a static member.

//The sound effects that will be used static Mix_Chunk* gRenderDone;

You could add a bool declared as a static member for an option to play the sound (to be defined in Preferences dialog).

static bool use_render_done_sound;

synfig-studio/src/gui/app.cpp

• Initialize the sound (Mix_Chunk*) to NULL. You could find the gRenderDone and add it after.

Mix_Chunk* App::gRenderDone= NULL;

42 Chapter 6. Tutorials Synfig developers docs

As well you may initialize the bool for allow to play the sound; this will be connected later in the Preferences dialog bool App::use_render_done_sound= true;

• Locate this part (at the end of the constructor App::App ) path_to_sounds+= ETL_DIRECTORY_SEPARATOR; and load your sound as follow (the volume is set at 50% if success)

//Load sound effects App::gRenderDone= Mix_LoadWAV( (path_to_sounds+"renderdone.wav").c_str() ); if ( App::gRenderDone== NULL){ synfig::error( _("SDL_mixer could not load gRenderDone : %s\n"), Mix_GetError() ); } else { Mix_VolumeChunk(App::gRenderDone, MIX_MAX_VOLUME/2); }

• Finally, free the sound in the destructor App::~App (and NULL the pointer)

//