odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

CONTRIBUTING.md (9121B)


      1 # Contributing to Blend2D
      2 
      3 The following is a set of guidelines for contributing to Blend2D and other repositories hosted in the [Blend2D Organization](https://github.com/blend2d) on GitHub.
      4 
      5 
      6 ## Table of Contents
      7 
      8 * [Asking Questions](#asking-questions)
      9 * [Reporting Bugs](#reporting-bugs)
     10 * [Website Enhancement](#website-enhancement)
     11 * [Coding Style](#coding-style)
     12 
     13 
     14 ## Asking Questions
     15 
     16 We prefer GitHub issues to be used for reporting bugs and similar problems. So please consider using our [Gitter Channel](https://gitter.im/blend2d/blend2d) to ask questions. It is active and may provide you quick help.
     17 
     18 * **Generic questions** should be asked on [Gitter](https://gitter.im/blend2d/blend2d) if possible
     19 * **Feature Suggestions** may be discussed on [Gitter](https://gitter.im/blend2d/blend2d), we will add features that match our future plans to the roadmap
     20 * For **C/C++ API Questions** use either [Gitter](https://gitter.im/blend2d/blend2d) or open a new issue on GitHub (see pinned issues first, we prefer to write a documentation regarding API functions that are not clear)
     21 * Read our [FAQ](https://blend2d.com/about.html#FAQ) as well, we would gladly improve it if you found something missing or can improve the existing content
     22 
     23 
     24 ## Reporting Bugs
     25 
     26 A good bug report should contain the following information:
     27 
     28 * Brief and detailed bug description
     29 * Steps to reproduce the bug (isolated test-case is preferred but not required)
     30 * Build and system information (use `<blend2d-debug.h>` to obtain it, see below)
     31 
     32 To make the reporting bugs as easy as possible Blend2D provides a header file called `<blend2d-debug.h>`. It contains functions for C and C++ API users that can be used to query useful information from Blend2D runtime and to dump the content of some Blend2D objects.
     33 
     34 Use the snippet below in your own code and include its output in your bug report. It will help us to identify the issue quicker. Debug API is provided for both C and C++ users.
     35 
     36 ```c
     37 #include <blend2d.h>
     38 #include <blend2d-debug.h>
     39 
     40 int main(int argc, char* argv[]) {
     41   // This will query and dump Blend2D build and system information. We
     42   // need this information to make the initial guess of where the problem
     43   // could be. Some JIT and SIMD bugs can depend on this information.
     44   bl_debug_runtime();
     45 
     46   // Now dump everything you have by using the following functions.
     47   bl_debug_array(&arr);          // Dumps the content of BLArray
     48   bl_debug_context(&ctx);        // Dumps the state of BLContext
     49   bl_debug_matrix2d(&mat);       // Dumps the content of BLMatrix2D
     50   bl_debug_image(&img);          // Dumps the content of BLImage (without pixels)
     51   bl_debug_path(&path);          // Dumps the content of BLPath
     52   bl_debug_stroke_options(&opt); // Dumps the content of BLStrokeOptions
     53 }
     54 ```
     55 
     56 When reporting bugs related to incorrect renderings it is important to also include the rendered image together with the bug report as it will help us to understand the problem better.
     57 
     58 
     59 ## Website Enhancement
     60 
     61 If you found a typo or have suggestions about the content on Blend2D website you can either contact us directly via email or discuss it on Gitter. Please don't open GitHub issues that are related to the website.
     62 
     63 
     64 ## Coding Style
     65 
     66 If you plan to contribute to Blend2D make sure you follow the guidelines described in this section.
     67 
     68 
     69 ### Source Files
     70 
     71 * Source files contain a header, which contains a project name `[Blend2D]`, description, and license that refers to `LICENSE.md` file (when you are creating a new file just copy the header from any other file)
     72 * Source files that include other Blend2D headers use relative paths starting with `./` or `../`
     73 * Header guard format is `BLEND2D_FILE_H` for root headers and `BLEND2D_PATH_FILE_H` for headers in a subdirectory
     74 * Source files (.cpp) must first include `api-build_p.h` and then other headers
     75 * Source files that use compiler intrinsics (SSE, AVX, NEON) must have the following suffix:
     76   * X86/X64
     77     * `*_sse2.cpp`         - SSE2
     78     * `*_sse3.cpp`         - SSE3
     79     * `*_ssse3.cpp`        - SSSE3
     80     * `*_sse4_1.cpp`       - SSE4.1
     81     * `*_sse4_2.cpp`       - SSE4.2 + POPCNT + PCLMULQDQ
     82     * `*_avx.cpp`          - AVX
     83     * `*_avx2.cpp`         - AVX2   + POPCNT + BMI + BMI2
     84     * `*_avx2fma.cpp`      - AVX2   + POPCNT + BMI + BMI2 + FMA
     85     * `*_avx512.cpp`       - AVX512 + POPCNT + BMI + BMI2
     86   * ARM/AArch64
     87     * `*_asimd.cpp`        - ASIMD
     88     * `*_asimd_crypto.cpp` - ASIMD + CRYPTO
     89 
     90 
     91 ### API Design
     92 
     93 #### Namespaces
     94 
     95 * Do not use namespaces in public API if possible
     96 
     97 Namespaces are used mostly internally. There are few exceptions like `BLRuntime` and `BLFileSystem` though.
     98 
     99 
    100 #### C vs C++ API
    101 
    102 * Public headers must place C++ specific functionality between `#ifdef __cplusplus` and `#endif`
    103 * Private headers use C++ by default (no C compatibility)
    104 
    105 Since Blend2D exports only C API and can be compiled without linking to standard C++ library it cannot use functions that depend on it. Blend2D at the moment only uses atomics and some other utilities like `std::numeric_limits<>` that don't require linking to C++ standard library and it must stay like that.
    106 
    107 
    108 #### Exception Safety and Error Handling
    109 
    110 * Do not use exceptions or RTTI
    111 
    112 Exceptions and RTTI are never used by Blend2D. In general every public function is marked `noexcept` (or `BL_NOEXCEPT_C` for C API) that should guarantee that the compiler won't emit unwind tables even when C++ exceptions are enabled at build time. Blend2D users can use exceptions in their code, but Blend2D would never throw them.
    113 
    114 * Use error codes for error handling and propagation
    115 * Use `BLResult` as a return value in functions that can fail
    116 
    117 Every function that can fail must return `BLResult`. Use `BL_PROPAGATE(<expression>)` to return on failure, but be careful and check how it's used first.
    118 
    119 
    120 #### Default Constructed State
    121 
    122   * Always offer a defined default constructed state.
    123 
    124 Default constructed state guarantees that no dynamic memory is allocated when creating a default constructed instance. Only initialization like `create()` or `begin()` and using setters would turn default initialized instance into an instance that could use dynamically allocated memory. Use `.reset()` to set the state of any class back to its default constructed state and to release all resources it holds.
    125 
    126 
    127 ### Coding Conventions
    128 
    129 If you are planning to contribute to Blend2D, please read our coding conventions carefully.
    130 
    131 * Indent by 2 spaces and never use TABs
    132 * Class and struct names use *Upper Camel Case* convention and always start with `BL` prefix (`BLClassName`)
    133 * Global functions and variables use *snake_case* convention and always start with `bl_` prefix (`bl_function_name`)
    134 * Structs are used for everything that doesn't have initialization and must be compatible with C API
    135 * Structs can have utility member functions available in C++ mode like `.reset()`, but cannot have constructors, destructors, or assignment operators
    136 * Classes are only used for implementing C++ API that is based on C API
    137 * Pointer `*` or reference `&` is part of the type, for example `BLImage* image` and not ~~`BLImage *image`~~
    138 * Namespaces are not indented, use the following in public headers:
    139 
    140 ```c++
    141 namespace BLSomeNamespace {
    142 [...]
    143 } // {BLSomeNamespace}
    144 ```
    145 
    146 * No line between a statement and opening bracket `{`:
    147 
    148 ```c++
    149 class BLSomeClass {
    150   void some_function() {
    151     for (size_t i = 0; i < 10; i++) {
    152       if (i & 0x1) {
    153         [...]
    154       }
    155     }
    156   }
    157 };
    158 ```
    159 
    160 * No spaces in a conditional expression, function declaration, and call:
    161 
    162 ```c++
    163 // Right:
    164 if (x) {
    165   some_function(x);
    166 }
    167 
    168 /* WRONG:
    169 if( x )
    170   some_function ( x );
    171 */
    172 ```
    173 
    174 * If obvious, omit `== nullptr` and `!= nullptr` from conditional expressions, except asserts:
    175 
    176 ```c++
    177 void* ptr;
    178 
    179 // Right:
    180 BL_ASSERT(ptr != nullptr);
    181 if (ptr) {
    182   [...]
    183 }
    184 
    185 /* WRONG:
    186 BL_ASSERT(ptr);
    187 if (ptr != nullptr) {
    188   [...]
    189 }
    190 */
    191 ```
    192 
    193 * Blend2D transitions to always use blocks in branches (**if**/**else**):
    194 
    195 ```c++
    196 // Right:
    197 if (something) {
    198   do_something()
    199 }
    200 
    201 if (x) {
    202   first();
    203 }
    204 else {
    205   second();
    206 }
    207 
    208 /* WRONG:
    209 if (something)
    210   do_something()
    211 
    212 if (x) {
    213   first();
    214 }
    215 else
    216   second();
    217 */
    218 ```
    219 
    220 * There is a space between a **switch** statement and its expression; **case** statement and its content are indented:
    221 
    222 ```c++
    223 switch (expression) {
    224   case 0:
    225     do_something();
    226     break;
    227 
    228   // Case that requires a block.
    229   case 1: {
    230     int var = something;
    231     do_something_else_with_var(var);
    232     break;
    233   }
    234 
    235   // If the default should never be reached, mark it so:
    236   default:
    237     BL_NOT_REACHED();
    238 }
    239 ```
    240 
    241 * Sometimes **case** and its content can be inlined:
    242 
    243 ```c++
    244 switch (condition) {
    245   case 0: do_something(); break;
    246   case 1: do_something_else(); break;
    247 }
    248 ```
    249 
    250 * Public enum values are *UPPER_CASED* and use `BL_` prefix
    251 * Public enums usually end with `_MAX_VALUE`, which should be separated by an empty line
    252 * Public enums are always `uint32_t`, use `BL_DEFINE_ENUM` to make sure they are properly defined in both C and C++ modes:
    253 
    254 ```c++
    255 BL_DEFINE_ENUM(BLSomeEnum) {
    256   BL_SOME_ENUM_A = 0,
    257   BL_SOME_ENUM_B = 1,
    258 
    259   BL_SOME_ENUM_MAX_VALUE = 1
    260 };
    261 ```