...
 
Commits (6)
nodejs_run:
graphene_test:
stage: test
script:
- npm install
- npm test
\ No newline at end of file
- ./configure
- ninja -C _build test
# Contributing to Graphene
If you found a bug (which I'm sure there will be plenty), or if you want
to add your own pet feature, then follow these steps:
1. Fork the [ebassi/graphene](https://github.com/ebassi/graphene) repo
2. Fix bugs or add new features and push them to your clone
3. Open [a new issue](https://github.com/ebassi/graphene/issues/new)
4. Open [a pull request](https://github.com/ebassi/graphene/pulls)
5. Wait for me to give feedback on the pull request
6. Celebrate when your code gets merged
That's pretty much it.
Please, respect the coding style when writing patches for Graphene. The
coding style can be immediately gleaned from the existing code, but here is
a short version:
* Indentation is made of spaces, and only spaces — **no tabs**
* Each indentation level is 2 spaces
* Curly braces for blocks go on a separate indentation level
* Except for functions
* Do not use curly braces for single-statement blocks
* When declaring or defining a function, arguments go on separate
lines
* When calling a function never break a line between the function
name and the opening parenthesis, and between the opening parenthesis
and the first argument
* Leave a space between functions and parenthesis
A more comprehensive coding style document is available in the `docs`
directory.
Copyright 2014 Emmanuele Bassi. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Graphene
### A thin layer of types for graphic libraries
[![Build Status](https://travis-ci.org/ebassi/graphene.svg?branch=master)](https://travis-ci.org/ebassi/graphene)
[![Build status](https://ci.appveyor.com/api/projects/status/pw7o5grgko1l06hd/branch/master?svg=true)](https://ci.appveyor.com/project/ebassi/graphene/branch/master)
When creating graphic libraries you most likely end up dealing with points
and rectangles. If you're particularly unlucky, you may end up dealing
with affine matrices and 2D transformations. If you're writing a graphic
library with 3D transformations, though, you are going to hit the jackpot:
4x4 matrices, projections, transformations, vectors, and quaternions.
Most of this stuff exists, in various forms, in other libraries, but it
has the major drawback of coming along with the rest of those libraries,
which may or may not be what you want. Those libraries are also available
in various languages, as long as those languages are C++; again, it may or
may not be something you want.
For this reason, I decided to write the thinnest, smallest possible layer
needed to write a canvas library; given its relative size, and the
propensity for graphics libraries to have a pun in their name, I decided
to call it Graphene.
This library provides types and their relative API; it does not deal with
windowing system surfaces, drawing, scene graphs, or input. You're
supposed to do that yourself, in your own canvas implementation, which is
the whole point of writing the library in the first place.
### Dependencies
Graphene has little dependencies.
Graphene contains optimizations for speeding up vector operations; those
optimizations are optional, and used only if both Graphene was compiled
with support for them *and* if the system you're running on has them.
Currently, Graphene supports the following platform-specific fast paths:
* Streaming SIMD Extensions (SSE) 2
* ARM NEON
* GCC vector extensions
In the remote case in which none of these optimizations are available,
Graphene will fall back to a naive scalar implementation.
Graphene can, optionally, provide types for integrating with GObject
properties and signals, as well as introspection information for its
use with other languages through introspection-based bindings.
### Installation
In order to build and install Graphene you will need development tools and
the headers of the dependencies. You will also need:
* [meson](http://mesonbuild.com)
* [ninja](https://ninja-build.org/)
Alternatively, you can also use Autotools.
First of all, clone the Git repository:
$ git clone git://github.com/ebassi/graphene
$ cd graphene
Then run:
$ mkdir _build && cd _build
$ meson .. # on Windows, it's "meson.py"
$ ninja test
# ninja install
It is possible, when building Graphene, to disable specific optimizations by
using configuration options:
* `-Denable-sse2=false` - will disable the SSE2 fast paths
* `-Denable-arm-neon=false` - will disable the ARM NEON fast paths
* `-Denable-gcc-vector=false` - will disable the GCC vector intrinsics
If you don't plan on generating introspection data, use `-Denable-introspection=false`
when configuring Graphene; similarly, if you don't plan on using GObject with
Graphene, use `-Denable-gobject-types=false`. Disabling GObject types will also
automatically disable generating introspection data.
You can also disable building the test suite and the benchmark suite, using
the `-Denable-tests=false` and `-Denable-benchmarks=false` configuration switches
respectively.
#### Building on Windows
In order to build on Windows, it's recommended to use the
[MSYS2](http://sourceforge.net/projects/msys2/) environment.
First, [install MSYS2](https://msys2.github.io/) and update it fully
as documented.
Then use `pacman` to set up the build environment by installing the
necessary prerequisites for your target. For all build systems, you
will need a standard development environment and the appropriate native
toolchain. You also need a Python interpreter for introspection builds,
which are the default.
$ pacman -S base-devel
$ pacman -S python3 # for introspection
$ pacman -S mingw-w64-x86_64-toolchain # only MINGW64 target
$ pacman -S mingw-w64-i686-toolchain # only MINGW32 target
If you're using GNU Autotools, you don't need to do anything more.
Autotools is part of the `base-devel` group.
If you want to try Meson, install the appropriate native package:
$ pacman -S mingw-w64-x86_64-meson # only MINGW64 target
$ pacman -S mingw-w64-i686-meson # only MINGW32 target
There are a number of optional dependencies too:
$ pacman -S gtk-doc # optional
$ pacman -S mingw-w64-x86_64-glib2 # optional, MINGW64 target only
$ pacman -S mingw-w64-i686-glib2 # optional, MINGW32 target only
$ pacman -S glib2 glib2-devel # optional, MSYS target only
Then clone the Graphene repository and build as usual by following the
instructions in the section above. If you're using Meson, please note
that the tool may be installed as "meson.py" on MSYS2.
### Contributing
If you found a bug (which I'm sure there will be plenty), or if you want
to add your own pet feature, then follow these steps:
1. Fork the [ebassi/graphene](https://github.com/ebassi/graphene) repo
2. Fix bugs or add new features and push them to your clone
3. Open [a new issue](https://github.com/ebassi/graphene/issues/new)
4. Open [a pull request](https://github.com/ebassi/graphene/pulls)
5. Wait for me to give feedback on the pull request
6. Celebrate when your code gets merged
That's pretty much it.
Please, respect the coding style when writing patches for Graphene. The
coding style can be immediately gleaned from the existing code, but here is
a short version:
* Indentation is made of spaces, and only spaces — **no tabs**
* Each indentation level is 2 spaces
* Curly braces for blocks go on a separate indentation level
* Except for functions
* Do not use curly braces for single-statement blocks
* When declaring or defining a function, arguments go on separate
lines
* When calling a function never break a line between the function
name and the opening parenthesis, and between the opening parenthesis
and the first argument
* Leave a space between functions and parenthesis
A more comprehensive coding style document is available in the `docs`
directory.
## Documentation
### Release notes
The release notes are available on the Graphene
[wiki](https://github.com/ebassi/graphene/wiki/Release-Notes).
### Available types
Graphene provides common types needed to handle 3D transformations:
* [2D points](http://ebassi.github.io/graphene/docs/graphene-Point.html)
* [3D points](http://ebassi.github.io/graphene/docs/graphene-Point3D.html)
* [triangles](http://ebassi.github.io/graphene/docs/graphene-Triangle.html)
* [rectangles](http://ebassi.github.io/graphene/docs/graphene-Rectangle.html)
* [quads](http://ebassi.github.io/graphene/docs/graphene-Quad.html)
* [quaternions](http://ebassi.github.io/graphene/docs/graphene-Quaternion.html)
* [euler angles](http://ebassi.github.io/graphene/docs/graphene-Euler.html)
* [vectors](http://ebassi.github.io/graphene/docs/graphene-Vectors.html) (2, 3, or 4-sized)
* [matrices](http://ebassi.github.io/graphene/docs/graphene-Matrix.html)
* [planes](http://ebassi.github.io/graphene/docs/graphene-Plane.html)
* [axis aligned bounding boxes](http://ebassi.github.io/graphene/docs/graphene-Box.html)
* [spheres](http://ebassi.github.io/graphene/docs/graphene-Sphere.html)
* [frustums](http://ebassi.github.io/graphene/docs/graphene-Frustum.html)
Graphene also provides its low-level SIMD [vector](http://ebassi.github.io/graphene/docs/graphene-SIMD-vector.html)
and [matrix](http://ebassi.github.io/graphene/docs/graphene-SIMD-matrix.html)
types, which are used to implement the API above.
All types can be placed on the stack, but provide allocation/free functions
for working on the heap as well. The contents of all structure types, unless
noted otherwise, should be considered private, and should never be accessed
directly.
The full API reference for Graphene is [available online](http://ebassi.github.io/graphene/docs/).
### License
Graphene is released under the terms of the MIT/X11 license.
See the `LICENSE` file for more details.
[binaries]
c = '/usr/bin/i686-w64-mingw32-gcc'
cpp = '/usr/bin/i686-w64-mingw32-cpp'
ar = '/usr/bin/i686-w64-mingw32-ar'
strip = '/usr/bin/i686-w64-mingw32-strip'
pkgconfig = '/usr/bin/i686-w64-mingw32-pkg-config'
exe_wrapper = 'wine'
[properties]
root = '/usr/i686-w64-mingw32/sys-root/mingw'
c_args = [ '-O2', '-g', '-pipe', '-Wall', '-Wp', '-D_FORTIFY_SOURCE=2', '-fexceptions', '--param=ssp-buffer-size=4', '-I/usr/i686-w64-mingw32/sys-root/mingw/include' ]
c_link_args = [ '-L/usr/i686-w64-mingw32/sys-root/mingw/lib' ]
[host_machine]
system = 'windows'
cpu_family = 'i686'
cpu = 'i686'
endian = 'little'
[binaries]
c = '/usr/bin/x86_64-w64-mingw32-gcc'
cpp = '/usr/bin/x86_64-w64-mingw32-cpp'
ar = '/usr/bin/x86_64-w64-mingw32-ar'
strip = '/usr/bin/x86_64-w64-mingw32-strip'
pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config'
exe_wrapper = 'wine'
[properties]
root = '/usr/x86_64-w64-mingw32/sys-root/mingw'
c_args = [ '-pipe', '-Wp,-D_FORTIFY_SOURCE=2', '-fexceptions', '--param=ssp-buffer-size=4', '-I/usr/x86_64-w64-mingw32/sys-root/mingw/include' ]
c_link_args = [ '-L/usr/x86_64-w64-mingw32/sys-root/mingw/lib' ]
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
#!/bin/sh
set -x
test -n "$srcdir" || srcdir=$1
test -n "$srcdir" || srcdir=.
cd "$srcdir"
PROJECT=graphene
VERSION=$(git describe --abbrev=0)
NAME="${PROJECT}-${VERSION}"
rm -f "${NAME}.tar"
echo "Creating git tree archive…"
git archive --prefix="${NAME}/" --format=tar HEAD > ${NAME}.tar
rm -f "${NAME}.tar.xz"
echo "Compressing archive…"
xz -f "${NAME}.tar"
set +x
newlines = lf
input_tab_size = 8
output_tab_size = 8
string_escape_char = 100
string_escape_char2 = 0
# indenting
indent_columns = 2
indent_with_tabs = 9
indent_align_string = true
indent_brace = 2
indent_braces = false
indent_braces_no_func = true
indent_func_call_param = false
indent_func_def_param = false
indent_func_proto_param = false
indent_switch_case = 0
indent_case_brace = 2
indent_paren_close = 1
indent_label = 0
indent_paren_open_brace = false
# spacing
sp_arith = add
sp_assign = add
sp_enum_assign = add
sp_bool = add
sp_compare = add
sp_inside_paren = remove
sp_inside_fparens = remove
sp_func_def_paren = force
sp_func_proto_paren = force
sp_paren_paren = remove
sp_balance_nested_parens = false
sp_paren_brace = remove
sp_before_square = remove
sp_before_squares = remove
sp_inside_square = remove
sp_after_comma = add
sp_before_comma = remove
sp_after_cast = add
sp_sizeof_paren = add
sp_not = remove
sp_inv = remove
sp_addr = remove
sp_member = remove
sp_deref = remove
sp_sign = remove
sp_incdec = remove
sp_attribute_paren = remove
sp_macro = force
sp_func_call_paren = force
set func_call_user = _ N_ C_
sp_brace_typedef = add
sp_cond_colon = add
sp_cond_question = add
sp_defined_paren = remove
# alignment
align_keep_tabs = false
align_with_tabs = false
align_on_tabstop = false
align_number_left = true
align_func_params = true
align_var_def_span = 0
align_var_def_amp_style = 1
align_var_def_colon = true
align_enum_equ_span = 0
align_var_struct_span = 2
align_var_def_star_style = 2
align_var_def_amp_style = 2
align_typedef_span = 2
align_typedef_func = 0
align_typedef_star_style = 2
align_typedef_amp_style = 2
# newlines
nl_assign_leave_one_liners = true
nl_enum_leave_one_liners = false
nl_func_leave_one_liners = false
nl_if_leave_one_liners = false
nl_end_of_file = add
nl_assign_brace = remove
nl_func_var_def_blk = 1
nl_fcall_brace = add
nl_enum_brace = remove
nl_struct_brace = force
nl_union_brace = force
nl_if_brace = force
nl_brace_else = force
nl_elseif_brace = force
nl_else_brace = add
nl_for_brace = force
nl_while_brace = force
nl_do_brace = force
nl_brace_while = force
nl_switch_brace = force
nl_before_case = true
nl_after_case = false
nl_func_type_name = force
nl_func_proto_type_name = remove
nl_func_paren = remove
nl_func_decl_start = remove
nl_func_decl_args = force
nl_func_decl_end = remove
nl_fdef_brace = force
nl_after_return = false
nl_define_macro = false
nl_create_if_one_liner = false
nl_create_for_one_liner = false
nl_create_while_one_liner = false
nl_after_semicolon = true
nl_multi_line_cond = true
# mod
mod_full_brace_for = remove
mod_full_brace_if = remove
mod_full_brace_while = remove
mod_full_brace_do = remove
mod_full_brace_nl = 3
mod_paren_on_return = remove
# line splitting
#code_width = 78
ls_for_split_full = true
ls_func_split_full = true
# positioning
pos_bool = trail
pos_conditional = lead
#!/bin/bash
# configure script adapter for Meson
# Based on build-api: https://github.com/cgwalters/build-api
# Copyright 2010, 2011, 2013 Colin Walters <walters@verbum.org>
# Copyright 2016, 2017 Emmanuele Bassi
# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php)
# Build API variables:
# Little helper function for reading args from the commandline.
# it automatically handles -a b and -a=b variants, and returns 1 if
# we need to shift $3.
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read "$1" <<< "${BASH_REMATCH[1]}"
else
read "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
sanitycheck() {
# $1 = arg name
# $1 = arg command
# $2 = arg alternates
local cmd=$( which $2 2>/dev/null )
if [ -x "$cmd" ]; then
read "$1" <<< "$cmd"
return 0
fi
test -z $3 || {
for alt in $3; do
cmd=$( which $alt 2>/dev/null )
if [ -x "$cmd" ]; then
read "$1" <<< "$cmd"
return 0
fi
done
}
echo -e "\e[1;31mERROR\e[0m: Command '$2' not found"
exit 1
}
sanitycheck MESON 'meson'
sanitycheck MESONTEST 'mesontest'
sanitycheck NINJA 'ninja' 'ninja-build'
enable_docs='-Denable-gtk-doc=false'
enable_man='-Denable-man=false'
enable_introspection=''
while (($# > 0)); do
case "${1%%=*}" in
--prefix) read_arg prefix "$@" || shift;;
--bindir) read_arg bindir "$@" || shift;;
--sbindir) read_arg sbindir "$@" || shift;;
--libexecdir) read_arg libexecdir "$@" || shift;;
--datarootdir) read_arg datarootdir "$@" || shift;;
--datadir) read_arg datadir "$@" || shift;;
--sysconfdir) read_arg sysconfdir "$@" || shift;;
--libdir) read_arg libdir "$@" || shift;;
--mandir) read_arg mandir "$@" || shift;;
--includedir) read_arg includedir "$@" || shift;;
--enable-gtk-doc) enable_docs='-Denable-gtk-doc=true';;
--disable-gtk-doc) enable_docs='-Denable-gtk-doc=false';;
--enable-man) enable_man='-Denable-man=true';;
--disable-man) enable_man='-Denable-man=false';;
--enable-introspection) enable_introspection='';;
--disable-introspection) enable_introspection='-Ddisable_introspection=true';;
*) echo -e "\e[1;33mINFO\e[0m: Ignoring unknown option '$1'";;
esac
shift
done
# Defaults
test -z ${prefix} && prefix="/usr/local"
test -z ${bindir} && bindir=${prefix}/bin
test -z ${sbindir} && sbindir=${prefix}/sbin
test -z ${libexecdir} && libexecdir=${prefix}/bin
test -z ${datarootdir} && datarootdir=${prefix}/share
test -z ${datadir} && datadir=${datarootdir}
test -z ${sysconfdir} && sysconfdir=${prefix}/etc
test -z ${libdir} && libdir=${prefix}/lib
test -z ${mandir} && mandir=${prefix}/share/man
test -z ${includedir} && includedir=${prefix}/include
# The source directory is the location of this file
srcdir=$(dirname $0)
# The build directory is the current location
builddir=`pwd`
# If we're calling this file from the source directory then
# we automatically create a build directory and ensure that
# both Meson and Ninja invocations are relative to that
# location
if [[ -f "${builddir}/meson.build" ]]; then
mkdir -p _build
builddir="${builddir}/_build"
NINJA_OPT="-C ${builddir}"
fi
# Wrapper Makefile for Ninja
cat > Makefile <<END
# Generated by configure; do not edit
all:
CC="\$(CC)" CXX="\$(CXX)" ${NINJA} ${NINJA_OPT}
install:
DESTDIR="\$(DESTDIR)" ${NINJA} ${NINJA_OPT} install
check:
${MESONTEST} ${NINJA_OPT}
END
echo "Summary:"
echo " meson:....... ${MESON}"
echo " ninja:....... ${NINJA}"
echo " prefix:...... ${prefix}"
echo " bindir:...... ${bindir}"
echo " sbindir:..... ${sbindir}"
echo " libexecdir:.. ${libexecdir}"
echo " datarootdir:. ${datarootdir}"
echo " datadir:..... ${datadir}"
echo " sysconfdir:.. ${sysconfdir}"
echo " libdir:...... ${libdir}"
echo " mandir:...... ${mandir}"
echo " includedir:.. ${includedir}"
echo " additional:.."
echo " - ${enable_docs} ${enable_man} ${enable_introspection}"
exec ${MESON} \
--prefix=${prefix} \
--libdir=${libdir} \
--libexecdir=${libexecdir} \
--datadir=${datadir} \
--sysconfdir=${sysconfdir} \
--bindir=${bindir} \
--includedir=${includedir} \
--mandir=${mandir} \
--default-library shared \
${enable_docs} \
${enable_man} \
${enable_introspection} \
${builddir} \
${srcdir}
# vim: ai ts=8 noet sts=2 ft=sh
/.libs
/html
/xml
/*.stamp
/graphene-decl-list.txt
/graphene-decl-list.txt.bak
/graphene-decl.txt
/graphene-decl.txt.bak
/graphene-undeclared.txt
/graphene-undocumented.txt
/graphene-unused.txt
/graphene.args
/graphene.hierarchy
/graphene.interfaces
/graphene.prerequisites
/graphene.signals
/graphene.types
/gtkdoc-check.log
/gtkdoc-check.test
/gtkdoc-check.trs
/test-suite.log
# Graphene Coding Style
This document is intended to be a short description of the preferred
coding style to be used for the Graphene source code.
Coding style is a matter of consistency, readability and maintainance;
coding style is also completely arbitrary and a matter of taste. This
document will use examples at the very least to provide authoritative
and consistent answers to common questions regarding the coding style,
and will also try to identify the allowed exceptions.
The examples will show the preferred coding style; the negative examples
will be clearly identified. Please, don't submit code to Graphene that
looks like any of these.
Part of the rationales for these coding style rules are available either
in the Linux kernel `CodingStyle` document or in Cairo's `CODING_STYLE`
one.
When in doubt, check the surrounding code and try to imitate it.
### Line width
The maximum line width for source files is 100 characters, whenever possible.
Longer lines are usually an indication that you either need a function
or a pre-processor macro.
### Indentation
Each new level is indented 2 or more spaces than the previous level:
if (condition)
single_statement ();
This can only be achieved using space characters. It may not be achieved
using tab characters alone, or using a combination of spaces and tabs.
Do not change the editor's configuration to change the meaning of a
tab character (see below); code using tabs to indent will not be accepted
into Graphene.
Even if two spaces for each indentation level allows deeper nesting than
8 spaces, Graphene favours self-documenting function names that can take
quite some space. For this reason alone you should avoid deeply nested
code.
### Tab characters
The tab character must always be expanded to spaces. If a literal
tab must be used inside the source, the tab must always be interpreted
according to its traditional meaning:
```
Advance to the next column which is a multiple of 8.
[ these two lines should be aligned ]
```
### Braces
Curly braces should not be used for single statement blocks:
if (condition)
single_statement ();
else
another_single_statement (arg1);
In case of multiple statements, curly braces should be put on another
indentation level:
if (condition)
{
statement_1 ();
statement_2 ();
statement_3 ();
}
The "no block for single statements" rule has only three exceptions:
1. if the single statement covers multiple lines, e.g. for functions with
many arguments, and it is followed by else or else if:
```
/* valid */
if (condition)
{
a_single_statement_with_many_arguments (some_lengthy_argument,
another_lengthy_argument,
and_another_one,
plus_one);
}
else
another_single_statement (arg1, arg2);
```
2. if the condition is composed of many lines:
```
/* valid */
if (condition1 ||
(condition2 && condition3) ||
condition4 ||
(condition5 && (condition6 || condition7)))
{
a_single_statement ();
}
```
3. Nested if's, in which case the block should be placed on the
outermost if:
```
/* valid */
if (condition)
{
if (another_condition)
single_statement ();
else
another_single_statement ();
}
/* invalid */
if (condition)
if (another_condition)
single_statement ();
else if (yet_another_condition)
another_single_statement ();
```
In general, new blocks should be placed on a new indentation level,
like:
int retval = 0;
statement_1 ();
statement_2 ();
{
int var1 = 42;
gboolean res = FALSE;
res = statement_3 (var1);
retval = res ? -1 : 1;
}
While curly braces for function definitions should rest on a new line
they should not add an indentation level:
/* valid */
static void
my_function (int argument)
{
do_my_things ();
}
/* invalid */
static void
my_function (int argument) {
do_my_things ();
}
/* invalid */
static void
my_function (int argument)
{
do_my_things ();
}
Curly braces must not be placed on the same line as a condition:
/* invalid */
if (condition) {
statement_1 ();
statement_2 ();
}
### Conditions
Do not check boolean values for equality:
/* invalid */
if (condition == TRUE)
do_foo ();
/* valid */
if (another_condition)
do_bar ();
Even if C handles NULL equality like a boolean, be explicit:
/* valid */
if (some_pointer == NULL)
do_blah ();
/* invalid */
if (some_other_pointer)
do_blurp ();
In case of conditions split over multiple lines, the logical operators should
always go at the end of the line:
/* invalid */
if (condition1
|| condition2
|| condition3)
{
do_foo ();
}
/* valid */
if (condition1 &&
condition2 &&
(condition3 || (condition4 && condition5)))
{
do_blah ();
}
### Types
All public types in Graphene should conform to the `<namespace>_<type>_t`
pattern, e.g.:
/* valid */
typedef struct _graphene_quaternion_t graphene_quaternion_t;
/* valid */
typedef enum {
...
} graphene_euler_order_t;
/* invalid */
typedef struct _foo_bar_t foo_bar_t;
/* invalid */
typedef enum {
...
} GrapheneBlah;
CamelCase is not allowed in the public API, and it's strongly discouraged
for the internals as well.
All public types should have public structure definitions, but if fields are
to be considered private then you should add them at the end of the
structure definition, and use the `GRAPHENE_PRIVATE_FIELD` macro to declare
them, e.g.:
/* valid */
struct _graphene_euler_t
{
GRAPHENE_PRIVATE_FIELD (graphene_vec3_t, angles);
GRAPHENE_PRIVATE_FIELD (graphene_euler_order_t, order);
};
/* invalid */
struct _graphene_foo_t
{
graphene_vec4_t __some_private_field;
graphene_vec4_t public_field;
};
All public types should have the following functions:
* a `graphene_<type>_alloc()` allocator; the contents of the structure
returned by this function are undefined
* a `graphene_<type>_free()` deallocator; this function should be NULL-safe
* a `graphene_<type>_init()` initializer
All initializer functions should take a pointer of the type they initialize
as their first argument, and return the initialized structure, e.g.:
/* valid */
graphene_rect_t * graphene_rect_init (graphene_rect_t *rect,
float x,
float y,
float width,
float height);
All types should be usable on the stack, after being initialized; the
behaviour of a type before initialization is undefined.
### Functions
Functions should be declared by placing the returned value on a separate
line from the function name:
void
my_function (void)
{
}
The arguments list must be broken into a new line for each argument,
with the argument names right aligned, taking into account pointers:
void
my_function (some_type_t type,
another_type_t *a_pointer,
final_type_t another_type)
{
}
The alignment also holds when invoking a function without breaking the
80 characters limit:
align_function_arguments (first_argument,
second_argument,
third_argument);
To respect the 80 characters limit do not break the function name from
the arguments:
/* invalid */
a_very_long_function_name_with_long_parameters
(argument_the_first, argument_the_second);
/* invalid */
a_very_long_function_name_with_long_parameters (
argument_the_first, argument_the_second);
/* valid */
first_a = argument_the_first;
second_a = argument_the_second;
a_very_long_function_name_with_long_parameters (first_a, second_a);
All public functions must be annotated with the `GRAPHENE_AVAILABLE_IN_x_y`
macro for the `x.y` stable release in which they appear. Functions private
to a specific source file should always be marked as `static`; functions
private to the whole project should be declared in a private header.
### Whitespace
Always put a space before a parenthesis but never after:
/* valid */
if (condition)
do_my_things ();
/* valid */
switch (condition)
{
}
/* invalid */
if(condition)
do_my_things();
/* invalid */
if ( condition )
do_my_things ( );
A `switch()` should open a block on a new indentation level, and each case
should start on the same indentation level as the curly braces, with the
case block on a new indentation level:
/* valid */
switch (condition)
{
case FOO:
do_foo ();
break;
case BAR:
do_bar ();
break;
}
/* invalid */
switch (condition) {
case FOO: do_foo (); break;
case BAR: do_bar (); break;
}
/* invalid */
switch (condition)
{
case FOO: do_foo ();
break;
case BAR: do_bar ();
break;
}
/* invalid */
switch (condition)
{
case FOO:
do_foo ();
break;
case BAR:
do_bar ();
break;
}
It is preferable, though not mandatory, to separate the various cases with
a newline:
switch (condition)
{
case FOO:
do_foo ();
break;
case BAR:
do_bar ();
break;
default:
do_default ();
}
The `break` statement for the `default:` case is not mandatory, but it is
appreciated.
If a case block needs to declare new variables, the same rules as the
inner blocks (see above) apply; the break statement should be placed
outside of the inner block:
switch (condition)
{
case FOO:
{
int foo;
foo = do_foo ();
}
break;
...
}
Do not eliminate whitespace and newlines just because something would
fit in the line character limit:
/* invalid */
if (condition) foo (); else bar ();
Please, eliminate all trailing or leading whitespace before submitting a
patch for review.
### Headers
Headers are special, for Graphene, in that they don't have to obey the
80 characters limit. The only major rule for headers is that the functions
definition should be vertically aligned in three columns:
return value function_name (type argument,
type argument,
type argument);
The maximum width of each column is given by the longest element in the
column:
bool graphene_type_set_property (graphene_type_t *type,
const char *value,
char **out_value);
const char *graphene_type_get_property (graphene_type_t *type);
It is also possible to align the columns to the next tab:
void graphene_type_set_property (graphene_type_t *type,
float value);
float graphene_type_get_property (graphene_type_t *type);
int graphene_type_update_foobar (graphene_type_t *type);
Public headers should have inclusion guards and C++ guards:
#ifndef __GRAPHENE_HEADER_H__
#define __GRAPHENE_HEADER_H__
#if !defined(__GRAPHENE_H_INSIDE__) && !defined(GRAPHENE_COMPILATION)
#error "Only <graphene.h> can be included directly."
#endif
#include "graphene-types.h"
GRAPHENE_BEGIN_DECLS
...
GRAPHENE_END_DECLS
#endif /* __GRAPHENE_HEADER_H__ */
Private headers do not need the single header inclusion guard, but they need
every other guard. Private headers should also be clearly named with a
`-private` suffix. Private headers should include the public header for the
type they relate to, first:
#ifndef __GRAPHENE_FOO_PRIVATE_H__
#define __GRAPHENE_FOO_PRIVATE_H__
#include "graphene-foo.h"
GRAPHENE_BEGIN_DECLS
...
GRAPHENE_END_DECLS
#endif
### Includes
Graphene source files should never include the global `graphene.h` header, but
instead include the individual headers that are needed. Every file must
include `graphene-private.h` first, then its own header, then other Graphene
header in an alphabetical order, then system and third-party headers.
/* valid */
#include "graphene-private.h"
#include "graphene-foo.h"
#include "graphene-box.h"
#include "graphene-point3d.h"
#include "graphene-vec3.h"
...
#include <math.h>
### Macros
Try to avoid private macros unless strictly necessary. Remember to #undef
them at the end of a block or a series of functions needing them.
Inline functions are usually preferable to private macros.
Public macros should not be used unless they evaluate to a constant.
### Documentation
All public APIs must have gtk-doc comments. For functions, these should
be placed in the source file, directly above the function.
/* valid */
/**
* graphene_type_get_property:
* @type: a #graphene_type_t
*
* Gets the property of a #graphene_type_t.
*
* Returns: the value of the property
*/
float
graphene_type_get_property (graphene_type_t *type)
{
...
}
Doc comments for macros, function types, structures, etc should be
placed next to the definitions, typically in headers.
Section introductions should be placed in the source file they describe,
after the license header:
/* valid */
/**
* SECTION:graphene-type
* @Title: Type
* @Short_description: A representation of a type
*
* [...]
*/
To properly document a new function, macro, function type or struct,
it needs to be listed in the graphene-sections.txt file.
To properly document a new type, it needs to be given its own section
in `graphene-sections.txt`, and it needs to be included in `graphene-docs.xml`.
### Old code
It is ok to update the style of a code block or function when you
are touching it anyway, but sweeping whitespace changes obscure the
revision control history and should be avoided at all costs.
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>Graphene Reference Manual</title>
<releaseinfo>
<para>This document is the API reference for the Graphene library.</para>
<para>
The latest version of Graphene, as well as the latest version of
this API reference, is <ulink role="online-location" url="http://ebassi.github.com/graphene">available online</ulink>.
</para>
</releaseinfo>
</bookinfo>
<chapter>
<title>Graphene</title>
<refsect2 id="overview">
<para>
Graphene is a library of data types commonly used to implement 2D-in-3D or full 3D canvases.
</para>
<para>
Graphene only contains math data types, like vectors and matrices; it does not deal with windowing
system calls, event handling, drawing, or a full scene graph.
</para>
</refsect2>
<xi:include href="xml/graphene-point.xml"/>
<xi:include href="xml/graphene-point3d.xml"/>
<xi:include href="xml/graphene-size.xml"/>
<xi:include href="xml/graphene-rect.xml"/>
<xi:include href="xml/graphene-quad.xml"/>
<xi:include href="xml/graphene-triangle.xml"/>
<xi:include href="xml/graphene-box.xml"/>
<xi:include href="xml/graphene-sphere.xml"/>
<xi:include href="xml/graphene-frustum.xml"/>
<xi:include href="xml/graphene-simd4f.xml"/>
<xi:include href="xml/graphene-simd4x4f.xml"/>
<xi:include href="xml/graphene-vectors.xml"/>
<xi:include href="xml/graphene-matrix.xml"/>
<xi:include href="xml/graphene-euler.xml"/>
<xi:include href="xml/graphene-quaternion.xml"/>
<xi:include href="xml/graphene-plane.xml"/>
<xi:include href="xml/graphene-ray.xml"/>
<xi:include href="xml/graphene-version.xml"/>
<xi:include href="xml/graphene-gobject.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<index role="1.0">
<title>Index of new symbols in 1.0</title>
<xi:include href="xml/api-index-1.0.xml"><xi:fallback /></xi:include>
</index>
<index role="1.2">
<title>Index of new symbols in 1.2</title>
<xi:include href="xml/api-index-1.2.xml"><xi:fallback /></xi:include>
</index>
<index role="1.4">
<title>Index of new symbols in 1.4</title>
<xi:include href="xml/api-index-1.4.xml"><xi:fallback /></xi:include>
</index>
<index role="1.6">
<title>Index of new symbols in 1.6</title>
<xi:include href="xml/api-index-1.6.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>
<STRUCT>
<NAME>graphene_simd4f_t</NAME>
</STRUCT>
<STRUCT>
<NAME>graphene_simd4x4f_t</NAME>
</STRUCT>
<FUNCTION>
<NAME>graphene_simd4x4f_init</NAME>
<RETURNS>graphene_simd4x4f_t </RETURNS>
graphene_simd4f_t x, graphene_simd4f_t y, graphene_simd4f_t z, graphene_simd4f_t w
</FUNCTION>
<MACRO>
<NAME>GRAPHENE_MAJOR_VERSION</NAME>
#define GRAPHENE_MAJOR_VERSION
</MACRO>
<MACRO>
<NAME>GRAPHENE_MINOR_VERSION</NAME>
#define GRAPHENE_MINOR_VERSION
</MACRO>
<MACRO>
<NAME>GRAPHENE_MICRO_VERSION</NAME>
#define GRAPHENE_MICRO_VERSION
</MACRO>
<INCLUDE>graphene.h</INCLUDE>
<SECTION>
<FILE>graphene-box</FILE>
graphene_box_t
graphene_box_alloc
graphene_box_free
graphene_box_init
graphene_box_init_from_box
graphene_box_init_from_points
graphene_box_init_from_vec3
graphene_box_init_from_vectors
graphene_box_equal
graphene_box_expand
graphene_box_expand_scalar
graphene_box_expand_vec3
graphene_box_get_min
graphene_box_get_max
graphene_box_get_center
graphene_box_get_depth
graphene_box_get_height
graphene_box_get_width
graphene_box_get_size
graphene_box_get_bounding_sphere
graphene_box_get_vertices
graphene_box_union
graphene_box_intersection
graphene_box_contains_box
graphene_box_contains_point
<SUBSECTION>
graphene_box_zero
graphene_box_one
graphene_box_minus_one
graphene_box_one_minus_one
graphene_box_empty
graphene_box_infinite
</SECTION>
<SECTION>
<FILE>graphene-euler</FILE>
graphene_euler_t
graphene_euler_order_t
graphene_euler_alloc
graphene_euler_free
graphene_euler_init
graphene_euler_init_with_order
graphene_euler_init_from_matrix
graphene_euler_init_from_quaternion
graphene_euler_init_from_vec3
graphene_euler_init_from_euler
graphene_euler_equal
graphene_euler_get_x
graphene_euler_get_y
graphene_euler_get_z
graphene_euler_get_order
graphene_euler_to_vec3
graphene_euler_to_matrix
graphene_euler_reorder
</SECTION>
<SECTION>
<FILE>graphene-frustum</FILE>
graphene_frustum_t
graphene_frustum_alloc
graphene_frustum_free
graphene_frustum_init
graphene_frustum_init_from_frustum
graphene_frustum_init_from_matrix
graphene_frustum_get_planes
graphene_frustum_contains_point
graphene_frustum_intersects_sphere
graphene_frustum_intersects_box
graphene_frustum_equal
</SECTION>
<SECTION>
<FILE>graphene-gobject</FILE>
<INCLUDE>graphene-gobject.h</INCLUDE>
<SUBSECTION Standard>
GRAPHENE_TYPE_BOX
GRAPHENE_TYPE_EULER
GRAPHENE_TYPE_FRUSTUM
GRAPHENE_TYPE_MATRIX
GRAPHENE_TYPE_PLANE
GRAPHENE_TYPE_POINT
GRAPHENE_TYPE_POINT3D
GRAPHENE_TYPE_QUAD
GRAPHENE_TYPE_QUATERNION
GRAPHENE_TYPE_RAY
GRAPHENE_TYPE_RECT
GRAPHENE_TYPE_SIZE
GRAPHENE_TYPE_SPHERE
GRAPHENE_TYPE_TRIANGLE
GRAPHENE_TYPE_VEC2
GRAPHENE_TYPE_VEC3
GRAPHENE_TYPE_VEC4
graphene_box_get_type
graphene_euler_get_type
graphene_frustum_get_type
graphene_matrix_get_type
graphene_plane_get_type
graphene_point3d_get_type
graphene_point_get_type
graphene_quad_get_type
graphene_quaternion_get_type
graphene_ray_get_type
graphene_rect_get_type
graphene_size_get_type
graphene_sphere_get_type
graphene_triangle_get_type
graphene_vec2_get_type
graphene_vec3_get_type
graphene_vec4_get_type
</SECTION>
<SECTION>
<FILE>graphene-matrix</FILE>
graphene_matrix_t
graphene_matrix_alloc
graphene_matrix_free
graphene_matrix_init_identity
graphene_matrix_init_from_float
graphene_matrix_init_from_vec4
graphene_matrix_init_from_matrix
graphene_matrix_init_from_2d
graphene_matrix_init_perspective
graphene_matrix_init_ortho
graphene_matrix_init_look_at
graphene_matrix_init_frustum
graphene_matrix_init_scale
graphene_matrix_init_translate
graphene_matrix_init_rotate
graphene_matrix_init_skew
graphene_matrix_is_identity
graphene_matrix_is_2d
graphene_matrix_is_backface_visible
graphene_matrix_is_singular
graphene_matrix_to_float
graphene_matrix_to_2d
graphene_matrix_get_row
graphene_matrix_get_value
graphene_matrix_multiply
graphene_matrix_determinant
graphene_matrix_transform_vec4
graphene_matrix_transform_vec3
graphene_matrix_transform_point
graphene_matrix_transform_point3d
graphene_matrix_transform_rect
graphene_matrix_transform_bounds
graphene_matrix_transform_box
graphene_matrix_transform_sphere
graphene_matrix_transform_ray
graphene_matrix_project_point
graphene_matrix_project_rect_bounds
graphene_matrix_project_rect
graphene_matrix_untransform_point
graphene_matrix_untransform_bounds
graphene_matrix_unproject_point3d
graphene_matrix_translate
graphene_matrix_rotate
graphene_matrix_rotate_x
graphene_matrix_rotate_y
graphene_matrix_rotate_z
graphene_matrix_rotate_quaternion
graphene_matrix_rotate_euler
graphene_matrix_scale
graphene_matrix_skew_xy
graphene_matrix_skew_xz
graphene_matrix_skew_yz
graphene_matrix_transpose
graphene_matrix_inverse
graphene_matrix_perspective
graphene_matrix_normalize
graphene_matrix_get_x_scale
graphene_matrix_get_y_scale
graphene_matrix_get_z_scale
graphene_matrix_interpolate
graphene_matrix_print
</SECTION>
<SECTION>
<FILE>graphene-plane</FILE>
graphene_plane_t
graphene_plane_alloc
graphene_plane_free
graphene_plane_init
graphene_plane_init_from_vec4
graphene_plane_init_from_plane
graphene_plane_init_from_point
graphene_plane_init_from_points
graphene_plane_normalize
graphene_plane_negate
graphene_plane_equal
graphene_plane_distance
graphene_plane_get_normal
graphene_plane_get_constant
</SECTION>
<SECTION>
<FILE>graphene-point</FILE>
GRAPHENE_POINT_INIT
GRAPHENE_POINT_INIT_ZERO
graphene_point_t
graphene_point_alloc
graphene_point_free
graphene_point_init
graphene_point_init_from_point
graphene_point_init_from_vec2
graphene_point_equal
graphene_point_distance
graphene_point_near
graphene_point_interpolate
graphene_point_to_vec2
graphene_point_zero
</SECTION>
<SECTION>
<FILE>graphene-size</FILE>
GRAPHENE_SIZE_INIT
GRAPHENE_SIZE_INIT_ZERO
graphene_size_t
graphene_size_alloc
graphene_size_free
graphene_size_init
graphene_size_init_from_size
graphene_size_equal
graphene_size_scale
graphene_size_interpolate
graphene_size_zero
</SECTION>
<SECTION>
<FILE>graphene-point3d</FILE>
GRAPHENE_POINT3D_INIT
GRAPHENE_POINT3D_INIT_ZERO
graphene_point3d_t
graphene_point3d_alloc
graphene_point3d_free
graphene_point3d_init
graphene_point3d_init_from_point
graphene_point3d_init_from_vec3
graphene_point3d_to_vec3
graphene_point3d_equal
graphene_point3d_near
graphene_point3d_scale
graphene_point3d_cross
graphene_point3d_dot
graphene_point3d_length
graphene_point3d_normalize
graphene_point3d_normalize_viewport
graphene_point3d_distance
graphene_point3d_interpolate
graphene_point3d_zero
</SECTION>
<SECTION>
<FILE>graphene-quad</FILE>
graphene_quad_t
graphene_quad_alloc
graphene_quad_free
graphene_quad_init
graphene_quad_init_from_rect
graphene_quad_init_from_points
graphene_quad_contains
graphene_quad_bounds
graphene_quad_get_point
</SECTION>
<SECTION>
<FILE>graphene-quaternion</FILE>
graphene_quaternion_t
graphene_quaternion_alloc
graphene_quaternion_free
graphene_quaternion_init
graphene_quaternion_init_identity
graphene_quaternion_init_from_quaternion
graphene_quaternion_init_from_vec4
graphene_quaternion_init_from_matrix
graphene_quaternion_init_from_angles
graphene_quaternion_init_from_radians
graphene_quaternion_init_from_angle_vec3
graphene_quaternion_init_from_euler
graphene_quaternion_to_vec4
graphene_quaternion_to_matrix
graphene_quaternion_to_angles
graphene_quaternion_to_radians
graphene_quaternion_to_angle_vec3
graphene_quaternion_equal
graphene_quaternion_dot
graphene_quaternion_invert
graphene_quaternion_normalize
graphene_quaternion_slerp
</SECTION>
<SECTION>
<FILE>graphene-ray</FILE>
graphene_ray_t
graphene_ray_alloc
graphene_ray_free
graphene_ray_init
graphene_ray_init_from_ray
graphene_ray_init_from_vec3
graphene_ray_get_origin
graphene_ray_get_direction
graphene_ray_get_position_at
graphene_ray_get_distance_to_point
graphene_ray_get_distance_to_plane
graphene_ray_get_closest_point_to_point
graphene_ray_equal
</SECTION>
<SECTION>
<FILE>graphene-rect</FILE>
GRAPHENE_RECT_INIT
graphene_rect_t
graphene_rect_alloc
graphene_rect_free
graphene_rect_init
graphene_rect_init_from_rect
graphene_rect_equal
graphene_rect_normalize
graphene_rect_normalize_r
graphene_rect_get_center
graphene_rect_get_top_left
graphene_rect_get_top_right
graphene_rect_get_bottom_right
graphene_rect_get_bottom_left
graphene_rect_get_x
graphene_rect_get_y
graphene_rect_get_width
graphene_rect_get_height
graphene_rect_get_vertices
graphene_rect_union
graphene_rect_intersection
graphene_rect_contains_point
graphene_rect_contains_rect
graphene_rect_offset
graphene_rect_offset_r
graphene_rect_inset
graphene_rect_inset_r
graphene_rect_round_to_pixel
graphene_rect_round
graphene_rect_expand
graphene_rect_interpolate
graphene_rect_zero
</SECTION>
<SECTION>
<FILE>graphene-simd4f</FILE>
graphene_simd4f_t
graphene_simd4f_init
graphene_simd4f_init_zero
graphene_simd4f_init_4f
graphene_simd4f_init_3f
graphene_simd4f_init_2f
graphene_simd4f_dup_4f