# Primitives addon

## General

### API: al_get_allegro_primitives_version

Returns the (compiled) version of the addon, in the same format as
[al_get_allegro_version].

## High-level drawing routines

### API: al_draw_line

Draws a line segment between two points.

*Parameters:*

* x1, y1, x2, y2 - Start and end points of the line
* color - Color of the line
* thickness - Thickness of the line, pass `<= 0` to draw hairline lines

### API: al_draw_triangle

Draws an outlined triangle.

*Parameters:*

* x1, y1, x2, y2, x3, y3 - Three points of the triangle
* color - Color of the triangle
* thickness - Thickness of the lines, pass `<= 0` to draw hairline lines

### API: al_draw_filled_triangle

Draws a filled triangle.

*Parameters:*

* x1, y1, x2, y2, x3, y3 - Three points of the triangle
* color - Color of the triangle

### API: al_draw_rectangle

Draws an outlined rectangle.

*Parameters:*

* x1, y1, x2, y2 - Upper left and lower right points of a rectangle
* color - Color of the rectangle
* thickness - Thickness of the lines, pass `<= 0` to draw hairline lines

### API: al_draw_filled_rectangle

Draws a filled rectangle.

*Parameters:*

* x1, y1, x2, y2 - Upper left and lower right points of a rectangle
* color - Color of the rectangle

### API: al_draw_rounded_rectangle

Draws an outlined rounded rectangle.

*Parameters:*

* x1, y1, x2, y2 - Upper left and lower right points of a rectangle
* color - Color of the rectangle
* rx, ry - The radii of the round
* thickness - Thickness of the lines, pass `<= 0` to draw hairline lines

### API: al_draw_filled_rounded_rectangle

Draws an filled rounded rectangle.

*Parameters:*

* x1, y1, x2, y2 - Upper left and lower right points of a rectangle
* color - Color of the rectangle
* rx, ry - The radii of the round

### API: al_calculate_arc

Calculates an elliptical arc, and sets the vertices in the destination to the
calculated positions. If `thickness <= 0`, then `num_points` of points are
required in the destination, otherwise twice as many are needed.  The
destination buffer should consist of regularly spaced (by distance of stride
bytes) doublets of floats, corresponding to x and y coordinates of the
vertices.

*Parameters:*

* dest - Pointer to the destination buffer
* stride - Distance (in bytes) between successive pairs of coordinates
* cx, cy - Center of the arc
* rx, ry - Radii of the arc
* start_theta - The initial angle from which the arc is calculated
* delta_theta - Angular span of the arc (pass a negative number to switch
 direction)
* thickness - Thickness of the arc
* num_points - The number of points to calculate

### API: al_draw_ellipse

Draws an outlined ellipse.

*Parameters:*

* cx, cy - Center of the ellipse
* rx, ry - Radii of the ellipse
* color - Color of the ellipse
* thickness - Thickness of the ellipse, pass `<= 0` to draw hairline ellipse

### API: al_draw_filled_ellipse

Draws a filled ellipse.

*Parameters:*

* cx, cy - Center of the ellipse
* rx, ry - Radii of the ellipse
* color - Color of the ellipse

### API: al_draw_circle

Draws an outlined circle.

*Parameters:*

* cx, cy - Center of the circle
* r - Radius of the circle
* color - Color of the circle
* thickness - Thickness of the circle, pass `<= 0` to draw hairline circle

### API: al_draw_filled_circle

Draws a filled circle.

*Parameters:*

* cx, cy - Center of the circle
* r - Radius of the circle
* color - Color of the circle

### API: al_draw_arc

Draws an arc.

*Parameters:*

* cx, cy - Center of the arc
* r - Radius of the arc
* color - Color of the arc
* start_theta - The initial angle from which the arc is calculated
* delta_theta - Angular span of the arc (pass a negative number to switch
    direction)
* thickness - Thickness of the circle, pass `<= 0` to draw hairline circle

### API: al_calculate_spline

Calculates a spline given 4 control points. If `thickness <= 0`, then
`num_segments` of points are required in the destination, otherwise twice as
many are needed.  The destination buffer should consist of regularly spaced (by
distance of stride bytes) doublets of floats, corresponding to x and y
coordinates of the vertices.

*Parameters:*

* dest - Pointer to the destination buffer
* stride - Distance (in bytes) between successive pairs of coordinates
* points - An array of 4 pairs of coordinates of the 4 control points
* thickness - Thickness of the spline ribbon
* num_segments - The number of points to calculate

### API: al_draw_spline

Draws a spline given 4 control points.

*Parameters:*

* points - An array of 4 pairs of coordinates of the 4 control points
* color - Color of the spline
* thickness - Thickness of the spline, pass `<= 0` to draw hairline spline

### API: al_calculate_ribbon

Calculates a ribbon given an array of points. The ribbon will go through all of
the passed points. If `thickness <= 0`, then `num_segments` of points are
required in the destination buffer, otherwise twice as many are needed. 
The destination and the points buffer should consist of regularly spaced
doublets of floats, corresponding to x and y coordinates of the vertices.

*Parameters:*

* dest - Pointer to the destination buffer
* dest_stride - Distance (in bytes) between successive pairs of coordinates in
    the destination buffer
* points - An array of pairs of coordinates for each point
* points_stride - Distance (in bytes) between successive pairs of coordinates
    in the points buffer
* thickness - Thickness of the spline ribbon
* num_segments - The number of points to calculate

### API: al_draw_ribbon

Draws a ribbon given given an array of points. The ribbon will go through all
of the passed points.

*Parameters:*

* points - An array of pairs of coordinates for each point
* color - Color of the spline
* thickness - Thickness of the spline, pass `<= 0` to draw hairline spline

## Low-level drawing routines

### API: al_draw_prim

Draws a subset of the passed vertex buffer.

A note about non power-of-two textures: For maximum portability, you
should only use textures that have their dimensions be a power of two. This 
warning is relaxed, however, if the texture coordinates never exit the
boundaries of a single bitmap. This means that if you want to tile the texture,
you should have it be power of two sized for maximum portability.

*Parameters:*

* texture - Texture to use, pass 0 to use only shaded primitves
* vtxs - Pointer to an array of vertices
* decl - Pointer to the vertex declaration. If set to 0, the vtxs are assumed
      to be of the ALLEGRO_VERTEX type
* start, end - Start and end of the subset of the vertex buffer to draw
* type - Primitive type to draw

*Returns:*
Number of primitives drawn

*See Also:*
[ALLEGRO_VERTEX], [ALLEGRO_PRIM_TYPE], [ALLEGRO_VERTEX_DECL], 
[al_draw_indexed_prim]

### API: al_draw_indexed_prim

Draws a subset of the passed vertex buffer. This function uses an index array
to specify which vertices to use. See the [al_draw_prim] entry for a note about
texture dimensions.

*Parameters:*

* texture - Texture to use, pass 0 to use only shaded primitves
* vtxs - Pointer to an array of vertices
* decl - Pointer to the vertex declaration. If set to 0, the vtxs are assumed
      to be of the ALLEGRO_VERTEX type
* indices - An array of indices into the vertex buffer
* num_vtx - Number of indices from the indices array you want to draw
* type - Primitive type to draw

*Returns:*
Number of primitives drawn

*See Also:*
[ALLEGRO_VERTEX], [ALLEGRO_PRIM_TYPE], [ALLEGRO_VERTEX_DECL], [al_draw_prim]

### API: al_get_allegro_color

Converts an `ALLEGRO_PRIM_COLOR` into a `ALLEGRO_COLOR`.

*Parameters:*

* col - ALLEGRO_PRIM_COLOR to convert

*Returns:*
Converted ALLEGRO_COLOR

*See Also:*
[ALLEGRO_PRIM_COLOR], [al_get_prim_color]

### API: al_get_prim_color

Converts an `ALLEGRO_COLOR` into a `ALLEGRO_PRIM_COLOR`.

*Parameters:*

* col - ALLEGRO_COLOR to convert

*Returns:*
Converted ALLEGRO_PRIM_COLOR

*See Also:*
[ALLEGRO_PRIM_COLOR], [al_get_allegro_color]

### API: al_create_vertex_decl

Creates a vertex declaration, which describes a custom vertex format.

*Parameters:*

* elements - An array of ALLEGRO_VERTEX_ELEMENT structures.
* stride - Size of the custom vertex structure

*Returns:*
Newly created vertex declaration.

*See Also:*
[ALLEGRO_VERTEX_ELEMENT], [ALLEGRO_VERTEX_DECL], [al_destroy_vertex_decl]

### API: al_destroy_vertex_decl

Destroys a vertex declaration.

*Parameters:*

* decl - Vertex declaration to destroy

*See Also:*
[ALLEGRO_VERTEX_ELEMENT], [ALLEGRO_VERTEX_DECL], [al_create_vertex_decl]

### API: al_draw_soft_triangle

Draws a triangle using the software rasterizer and user supplied pixel
functions. For help in understanding what these functions do, see the
implementation of the various shading routines in addons/primitives/tri_soft.c.
The triangle is drawn in two segments, from top to bottom. The segments are
deliniated by the vertically middle vertex of the triangle. One of each segment
may be absent if two vertices are horizontally collinear.

*Parameters:*

* v1, v2, v3 - The three vertices of the triangle
* state - A pointer to a user supplied struct, this struct will be passed to
  all the pixel functions
* init - This function is called once, before any drawing is done. The three
  points passed to it may be altered by clipping.
* first - The function is called twice, once per triangle segment. It is
  passed 4 parameters, the first two are the coordinates of the initial pixel
  drawn in the segment. 
  The second two are the left minor and the left major steps, respectively.
  They represent the sizes of two steps taken by the rasterizer as it walks
  on the left side of the triangle. From then on, the each step will either
  be classified as a minor or a major step, corresponding to the above
  values.
* step - Called once per scanline. The last parameter is set to 1 if the step
  is a minor step, and 0 if it is a major step.
* draw - Called once per scanline. The function is expected to draw the
  scanline starting with a point specified by the first two parameters
  (corresponding to x and y values) going to the right until it reaches the
  value of the third parameter (the x value of the end point). All coordinates
  are inclusive.

### API: al_draw_soft_line

Draws a line using the software rasterizer and user supplied pixel functions.
For help in understanding what these functions do, see the implementation of
the various shading routines in addons/primitives/line_soft.c.
The line is drawn top to bottom.

*Parameters:*

* v1, v2 - The two vertices of the line
* state - A pointer to a user supplied struct, this struct will be passed to
  all the pixel functions
* first - The function is called before drawing the first pixel of the line. It
  is passed the coordinates of this pixel, as well as the two vertices above.
  The passed vertices may have been altered by clipping.
* step - Called once per pixel. The second parameter is set to 1 if the step is
  a minor step, and 0 if this step is a major step. Minor steps are taken only
  either in x or y directions.
  Major steps are taken in both directions diagonally. In all cases, the the
  absolute value of the change in coordinate is at most 1 in either direction.
* draw - Called once per pixel. The function is expected to draw the pixel at
  the two coordinates passed to it.

## Transformations

### API: al_copy_transform

Makes a copy of a transformation.

*Parameters:*

* src - Source transformation
* dest - Destination transformation

### API: al_use_transform

Sets the transformation to be used for the primitive drawing operations. Every
drawing operation after this call will be transformed using this
transformation. Call this function with the identity before using non-primitive
drawing functions (e.g. drawing bitmaps), otherwise the behaviour of those
functions will not be defined.

*Parameters:*

* trans - Transformation to use

### API: al_get_current_transform

Returns the current transformation, as set by [al_use_transform].

*Returns:*
A pointer to the current transformation.

### API: al_invert_transform

Inverts the passed transformation. If the transformation is nearly singular 
(close to not having an inverse) then the returned transformation may be
invalid. Use [al_check_inverse] to assertain if the transformation has an
inverse if you are in doubt.

*Parameters:*

* trans - Transformation to invert

*See Also:*
[al_check_inverse]

### API: al_check_inverse

Checks if the transformation has an inverse using supplied tolerance. Tolerance
should be a small value between 0 and 1, with 0.001 being sufficient for most
applications. Note that this check is superfluous most of the time if you only
used the primitives addon to construct the transformation. The only thing that
would cause the transformation to not have an inverse is if you applied a 0 (or
very small) scale to the transformation. As long as the scale is comfortably
above 0, the transformation is invertible. This, of course, does not apply if
you manually fiddle with the values of the transformation.

*Parameters:*

* trans - Transformation to check
* tol - Tolerance

*Returns:*
1 if the transformation is invertible, 0 otherwise

*See Also:*
[al_invert_transform]

### API: al_identity_transform

Sets the transformation to be the identity transformation.

*Parameters:*

* trans - Transformation to alter

### API: al_build_transform

Builds a transformation given some parameters. This call is equivalent to
calling the transformations in this order: make identity, scale, rotate,
translate. This method is faster, however.

*Parameters:*

* trans - Transformation to alter
* x, y - Translation
* sx, sy - Scale
* theta - Rotation angle

### API: al_translate_transform

Apply a translation to a transformation.

*Parameters:*

* trans - Transformation to alter
* x, y - Translation

### API: al_rotate_transform

Apply a rotation to a transformation.

*Parameters:*

* trans - Transformation to alter
* theta - Rotation angle

### API: al_scale_transform

Apply a scale to a transformation.

*Parameters:*

* trans - Transformation to alter
* sx, sy - Scale

### API: al_transform_vertex

Transform a vertex.

*Parameters:*

* trans - Transformation to use
* vtx - Vertex to transform

### API: al_transform_transform

Transform a transformation.

*Parameters:*

* trans - Transformation to use
* trans2 - Transformation to transform

## Structures and types

### API: ALLEGRO_PRIM_COLOR

A special structure that defines a color in a way that understandable to both
OpenGL and Direct3D backends.
You should never access internal fields, instead using the two conversion
functions to convert between it and [ALLEGRO_COLOR] structure.

*See Also:*
[al_get_allegro_color], [al_get_prim_color]

### API: ALLEGRO_VERTEX

Defines the generic vertex type, with a 2D position, color and texture
coordinates for a single texture.

*Fields:*

* x, y - Position of the vertex
* color - `ALLEGRO_PRIM_COLOR` structure
* u, v - Texture coordinates measured in pixels

*See Also:*
[ALLEGRO_PRIM_COLOR], [ALLEGRO_PRIM_ATTR]

### API: ALLEGRO_TRANSFORM

Defines the generic transformation type, a 4x4 matrix. 2D transforms use only
a small subsection of this matrix, namely the top left 2x2 matrix, and the
right most 2x1 matrix, for a total of 6 values.

*Fields:*

* m - A 4x4 float matrix

### API: ALLEGRO_VERTEX_DECL

A vertex declaration. This opaque structure is responsible for describing
the format and layout of a user defined custom vertex. It is created and 
destroyed by specialized functions.

*See Also:*
[al_create_vertex_decl], [al_destroy_vertex_decl], [ALLEGRO_VERTEX_ELEMENT]

### API: ALLEGRO_VERTEX_ELEMENT

A small structure describing a certain element of a vertex. E.g. the
position of the vertex, or its color. These structures are used by the 
al_create_vertex_decl function to create the vertex declaration. For that they
generally occur in an array. The last element of such an array should have the 
attribute field be 0, to signify that it is the end of the array.
Here's an example of code that would create a declaration describing the 
ALLEGRO_VERTEX structure:

    ALLEGRO_VERTEX_ELEMENT elems[] = {
       {ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(ALLEGRO_VERTEX, x)},
       {ALLEGRO_PRIM_TEX_COORD_PIXEL, ALLEGRO_PRIM_FLOAT_2, offsetof(ALLEGRO_VERTEX, u)},
       {ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(CUSTOM_VERTEX, color)},
       {0, 0, 0}
    };
    ALLEGRO_VERTEX_DECL* decl = al_create_vertex_decl(elems, sizeof(ALLEGRO_VERTEX));

*Fields:*

* attribute - A member of the ALLEGRO_PRIM_ATTR enumeration, specifying what
   this attribute signifies
* storage - A member of the ALLEGRO_PRIM_STORAGE enumeration, specifying how
   this attribute is stored
* offset - Offset in bytes from the beginning of the custom vertex structure. C
   function offsetof is very useful here.

*See Also:*
[al_create_vertex_decl], [ALLEGRO_VERTEX_DECL], [ALLEGRO_PRIM_STORAGE]

### API: ALLEGRO_PRIM_TYPE

Enumerates the types of primitives this addon can draw.

* ALLEGRO_PRIM_POINT_LIST - A list of points, each vertex defines a point

* ALLEGRO_PRIM_LINE_LIST - A list of lines, sequential pairs of vertices define
  disjointed lines

* ALLEGRO_PRIM_LINE_STRIP - A strip of lines, sequential vertices define a
  strip of lines

* ALLEGRO_PRIM_LINE_LOOP - Like a line strip, except at the end the first and
  the last vertices are also connected by a line

* ALLEGRO_PRIM_TRIANGLE_LIST - A list of triangles, sequential triplets of
  vertices define disjointed triangles

* ALLEGRO_PRIM_TRIANGLE_STRIP - A strip of triangles, sequential vertices
  define a strip of triangles

* ALLEGRO_PRIM_TRIANGLE_FAN - A fan of triangles, all triangles share the first
  vertex

### API: ALLEGRO_PRIM_ATTR

Enumerates the types of vertex attributes that a custom vertex may have.

* ALLEGRO_PRIM_POSITION - Position information, can be stored in any supported 
   fashion

* ALLEGRO_PRIM_COLOR_ATTR - Color information, stored in an ALLEGRO_PRIM_COLOR.
   The storage field of ALLEGRO_VERTEX_ELEMENT is ignored

* ALLEGRO_PRIM_TEX_COORD - Texture coordinate information, can be stored only in
   ALLEGRO_PRIM_FLOAT_2 and ALLEGRO_PRIM_SHORT_2. These coordinates are
   normalized by the width and height of the texture, meaning that the
   bottom-right corner has texture coordinates of (1, 1).

* ALLEGRO_PRIM_TEX_COORD_PIXEL - Texture coordinate information, can be stored
   only in ALLEGRO_PRIM_FLOAT_2 and ALLEGRO_PRIM_SHORT_2. These coordinates are
   measured in pixels.

A note about pixel coordinates. In OpenGL the texture coordinate (0, 0) refers
to the top left corner of the pixel. This confuses some drivers, because due to
rounding errors the actual pixel sampled might be the pixel to the top and/or 
left of the (0, 0) pixel. To make this error less likely it is advisable to
offset the texture coordinates you pass to the al_draw_prim by (0.5, 0.5) if you
need precise pixel control. E.g. to refer to pixel (5, 10) you'd set the u and v
to 5.5 and 10.5 respectively.

*See Also:*
[ALLEGRO_VERTEX_DECL], [ALLEGRO_PRIM_STORAGE]

### API: ALLEGRO_PRIM_STORAGE

Enumerates the types of storage an attribute of a custom vertex may be stored
in.

* ALLEGRO_PRIM_FLOAT_2 - A doublet of floats
* ALLEGRO_PRIM_FLOAT_3 - A triplet of floats
* ALLEGRO_PRIM_SHORT_2 - A doublet of shorts

*See Also:*
[ALLEGRO_PRIM_ATTR]

### API: ALLEGRO_VERTEX_CACHE_SIZE

Defines the size of the transformation vertex cache for the software renderer.
If you pass less than this many vertices to the primitive rendering functions
you will get a speed boost. This also defines the size of the cache vertex
buffer, used for the high-level primitives. This corresponds to the maximum
number of line segments that will be used to form them.

### API: ALLEGRO_PRIM_QUALITY

Defines the quality of the quadratic primitives. At 10, this roughly
corresponds to error < 0.5 pixel.

