Contents

 

Inkscape Coding Style

This page documents the conventions used in the source code of Inkscape. Please adhere to these conventions when writing new code. If you see code which does not conform to them, feel free to fix it!

Basics: indentation, spacing and braces

Code is consistently indented using four spaces. Tab characters are not allowed anywhere in the code. The only exception is makefiles and other build system files where tab characters are syntactically required.

The following things are indented:

  • Bodies of control statements: for, if, while, switch, etc.
  • Free statement blocks, i.e. opening and closing braces which do not follow any control statement. These are sometimes used to limit the lifetime of objects.
  • Bodies of classes and functions.
  • Statements continued from the previous line.

The following things are not indented:

  • Contents of namespaces.
  • Access control specifiers.

Code is written using compact braces, which means that the opening brace goes on the same line as the control statement. The closing brace of an if block goes on the same line as the following else keyword. However, there is an exception: if the condition of an if or while or the header of a for loop are broken into more than one line, the opening brace goes on a separate line. Braces are mandatory and must not be omitted even when the body of the block has only a single line. For function definitions, the opening brace should go on a separate line if the function is more than a few lines long or when the argument list spans more than a single line. Opening braces of constructors with member initializers must go on a separate line.

Spaces are present in the following places:

  • Around all binary operators, including assignments
  • Between a keyword and parentheses
  • Between an identifier or keyword and a brace
  • After commas and semicolons that do not end a line
  • Between the template keyword and the template argument list

Spaces are absent in the following places:

  • Before semicolons and commas
  • On the inner side of parentheses
  • Between a function name and its argument list
  • Between unary operators and their operands
  • Inside an empty argument list
  • Between a label and a colon
  • Around the scope operator ::

Member initializer lists and base class lists that contain more than one class should be written using Boost-style indentation: each member or class goes on a separate line and is preceded by the appropriate punctuation and a space. This makes it very easy to spot errors.

namespace Inkscape {
namespace UI {

Sandwich make_sandwich(int x);
int make_a_mess(float y);

} // namespace UI
} // namespace Inkscape

class Bunkum
    : public Nonsense
    , protected PublicSpeech
{
public:
    Bunkum()
        : _x(1024)
        , _y(42)
    {}
private:
    void _forget();
    int _x, _y;
};

template <typename Basket>
void fill_basket(Basket &b)
{
    switch (a) {
        case 1:
            do_one();
            break;

        case 2:
            do_two();
            break;

        default:
            break;
    }

    for (int i = 0; i < 30; ++i) {
        b << Inkscape::UI::make_sandwich();
    }
    return b;
}

Naming conventions

Class and namespace names use UpperCamelCase. Global and public static functions, stack variables, and class members (class variables) use lower_snake_case. Class member functions (methods) use lowerCamelCase. Protected and private class members are prefixed with an underscore. Macros and constants use UPPER_SNAKE_CASE. Template parameters which are types use UpperCamelCase, while those which are integers use UPPER_SNAKE_CASE, like constants. Type prefixes, Hungarian notation, etc. are disallowed. Use meaningful suffixes if you need to disambiguate, e.g. text_raw and text_escaped.

Variable names should be nouns. Function names should be verbs, with the exception of getters, which can be nouns. For instance, a class property called position would have the setter setPosition() and the getter position().

Filename conventions

All files which are part of the Inkscape source should use lowercase-with-hyphens. C++ files should have the .cpp extension, while header files should have the .h extension. Spaces, uppercase letters and underscores are not allowed. Using numbers in filenames is discouraged.

Placement of const

The const qualifier binds to the right, not to the left. This fact is often forgotten, so in order for everyone to keep this in mind, we require the const qualifier to be written after the type.

#define SOME_MACRO(x) x
void call_global();
unsigned const IMPORTANT_CONSTANT = 42;

class Example {
public:
    void callPublic();
    static void call_public_static();
    int public_variable;
protected:
    void _callProtected();
    static void _call_protected_static();
    int _protected_variable;
private:
    void _callPrivate();
    static void _call_private_static();
    int _private_variable;
};

template <typename TypeParam, int INTEGER_PARAM>
void call_global_template(boost::array<TypeParam, INTEGER_PARAM> const &array);

Preprocessor

Conditional compilation using the preprocessor is strongly discouraged, since it leads to code rot. Use it only when it is unavoidable, for instance when an optional dependency is used. A special case is using conditional compilation to exclude an entire file based on the platform, which is allowed.

In preference to conditionally compiled, platform-specific code, you should aim to write portable code which works the same regardless of platform. Using the GLib and GTK+ libraries can help a lot in this respect. If you must use different code depending on the platform, try to encapsulate it in helper functions, so that the amount of code that differs between platforms is kept to a minimum.

File layout

Inkscape files have a fixed layout. Each code file should contain things in this order:

  1. Machine-readable license information conforming to the SPDX standard
  2. A Doxygen comment with a brief description of what's in the file.
  3. A separate non-Doxygen comment with author and licensing information.
  4. Open of include guard (only in headers).
  5. Header corresponding to .cpp file (only in .ccp files).
  6. System header includes, e.g. #include <header>. These headers should be ordered alphabetically within library dependencies; in the following order: standard C++ headers (e.g. iostream), quasi-system headers (e.g. boost), glib/gtk headers, quasi-internal headers (e.g. lib2geom).
  7. Internal header includes. These headers should be ordered alphabetically with headers without sub-directories first.
  8. The code itself, in the Inkscape namespace. Here the order is more flexible, but usually global function declarations should come after class declarations. The order of definitions in the .cpp file should match the order of declarations in the .h file.
  9. Close of include guard.
  10. A comment with standard modelines for Vim and Emacs, also usable by other editors. This block is the same for all files.

The code below demonstrates a small example file which conforms to the required layout.

// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
 * Selector component (click and rubberband)
 *//*
 * Authors:
 *   Krzysztof Kosiński <[email protected]>
 *
 * Copyright (C) 2009 Authors
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_UI_TOOL_SELECTOR_H
#define SEEN_UI_TOOL_SELECTOR_H

#include <memory>
#include <gdk/gdk.h>
#include <2geom/rect.h>
#include "ui/tool/manipulator.h"

class SPDesktop;
class CtrlRect;

namespace Inkscape {
namespace UI {

class SelectorPoint;

class Selector : public Manipulator {
public:
    Selector(SPDesktop *d);
    virtual ~Selector();
    virtual bool event(SPEventContext *, GdkEvent *);
    
    sigc::signal<void, Geom::Rect const &, GdkEventButton*> signal_area;
    sigc::signal<void, Geom::Point const &, GdkEventButton*> signal_point;
private:
    SelectorPoint *_dragger;
    Geom::Point _start;
    CtrlRect *_rubber;
    gulong _connection;
    bool _cancel;
    friend class SelectorPoint;
};

} // namespace UI
} // namespace Inkscape

#endif

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace .0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:

Source code formatters

The task of keeping the source files conformant to the coding style can be simplified by using automatic source code formatters.

Artistic Style options

Artistic Style (astyle) is a C++ source code formatter. You can use it to reformat any nonconformant source code. For the Inkscape coding style, put the following in your .astylerc file:

--style=stroustrup
--indent=spaces=4
--indent-preprocessor
--indent-col1-comments
--pad-oper
--unpad-paren
--pad-header
--align-pointer=name
--align-reference=name
--add-brackets
--convert-tabs

The same content is available in the astylerc file in Inkscape's source code repository, which you can pass as the argument to the --options option. You can also use an equivalent command line.

astyle --options=astylerc
astyle -A4 -s4 -k3 -W3 -cjHpUwY

clang-format options

clang-format is a source code formatter shipped as part of the Clang compiler, based on LLVM. Recent revisions of Inkscape come with a suitable _clang-format file, which means clang-format should pick up the correct settings out of the box.