Navigation C API Pages Python bindings Applications

Drawing Context

The GP_Context structure describes an in memory pixmap. The structure contains all metadata needed for drawing, loaders and filters.

Data Structure

typedef struct GP_Context {
        uint8_t *pixels;         /* pointer to image pixels */
        uint8_t  bpp;            /* pixel length in bits */
        uint32_t bytes_per_row;
        uint32_t w;              /* width in pixels */
        uint32_t h;              /* height in pixels */
        /*
         * Row bit offset. The offset is ignored for byte aligned pixels.
         * Basically it's used for non aligned pixels with combination
         * with subcontextes.
         */
        uint8_t offset;

        enum GP_PixelType pixel_type; /* pixel format */

        /*
         * Pointer to optional Gamma correction tables.
         */
        struct GP_Gamma *gamma;

        uint8_t axes_swap:1;         /* swap axes */
        uint8_t x_swap:1;            /* mirror x */
        uint8_t y_swap:1;            /* mirror y */
        uint8_t bit_endian:1;        /* GP_BIT_ENDIAN */
        uint8_t free_pixels:1;       /* if set GP_ContextFree() calls free on context->pixels */
} GP_Context;

The pixels field points to the image data.

The pixels are stored as a one-dimensional array consisting of byte-aligned lines (i.e. each image line starts at whole byte and ends at whole byte).

The pixels array starts exactly at upper left corner of the image and is stored in horizontal lines (each line contains w pixels and there is h lines). Each line is bytes_per_row bytes long (which equals to w * bpp / 8 rouned up to the whole bytes). The first pixel may actually start at offset bit in the first byte in each line (but only for some subcontexts for pixel types that are not byte aligned).

The pixel_type enumeration defines in which format and how are pixel data stored in the pixels buffer, i.e. organization and function of the pixel channels.

The optional pointer to gamma tables describes per-channel gamma correction. Unfortunatelly very few parts of the library use it at the moment (this will be fixed in subsequent releases).

The bitfield at the the end of the structure describes image orientation (see bellow) and a flag that tell if pixels data should be freed, which is usefull for example for subcontexts.

Rotation

The orientation flags affects the gfx and text drawing functions and blits. If some of the flags is changed the origin and direction of the drawing is changed accordingly. Note that the image pixels are not affected by this at all only the coordinates passed to drawing functions are transformed.

If you don’t need this functionality just don’t touch the flags the as overhead of these transformations is not measurable.

If you really need drawing primitives that do not use the orientation flags, you could use variants with _Raw suffix (although this is not recommended).

There are various helper macros for transforming coordinates and sizes in core/GP_Transform.h. And context helper functions to "rotate" the flags clock wise and counter clock wise as well as functions to get the context size when taking into the account the width and height.

#include <core/GP_Transform.h>
/* or */
#include <GP.h>

/* Transforms point user coordinates to bitmap coordinates */
GP_TRANSFORM_POINT(context, x, y)

/* Transforms rectangular area coordinates and size */
GP_TRANSFORM_RECT(context, x, y, w, h)

/* Inverse transformation, bitmap coordinates to user coordinates */
GP_RETRANSFORM_POINT(context, x, y)
#include <core/GP_Context.h>
/* or */
#include <GP.h>

/*
 * Rotate context flags clock wise.
 */
void GP_ContextRotateCW(GP_Context *context);

/*
 * Rotate context flags counter clock wise.
 */
void GP_ContextRotateCCW(GP_Context *context);

/*
 * Retruns 1 if rotation flags are equal.
 */
int GP_ContextRotationEqual(const GP_Context *c1, const GP_Context *c2);

/*
 * Sets context rotation flags.
 */
void GP_ContextSetRotation(GP_Context *dst, int axes_swap,
                           int x_swap, int y_swap);

/*
 * Copies rotation flags.
 */
void GP_ContextCopyRotation(const GP_Context *src, GP_Context *dst);

/*
 * Returns context width and height taking the rotation flags into the account.
 */
GP_Size GP_ContextW(const GP_Context *context);
GP_Size GP_ContextH(const GP_Context *context);

Basic context functions

#include <core/GP_Context.h>
/* or */
#include <GP.h>

GP_Context *GP_ContextInit(GP_Context *context, GP_Size w, GP_Size h,
                           GP_PixelType type, void *pixels);

Initialize given context accordingly to parameters, the rest of context parameters are set to the default values (i.e. rotation flags are all set to zero, free_pixels flag is not set). Number of bits per pixel and bytes per row are computed from the given pixel type and size.

The pixels pointer can be NULL and can be changed later manually (the call will not try to allocate the pixel memory automatically).

The function returns a pointer to the initialized context (i.e. the same pointer you passed as second argument).

#include <core/GP_Context.h>
/* or */
#include <GP.h>

GP_Context *GP_ContextAlloc(GP_Size w, GP_Size h, GP_PixelType type);

The GP_ContextAlloc() allocates and initializes a context.

The orientation flags are all set to zero, the free_pixels flag is set and the rest of the metadata are calculated accordingly to width, height and pixel_type.The pixels pointer will point to a newly allocated bitmap with appropriate size; the initial contents of the bitmap are undefined.

#include <core/GP_Context.h>
/* or */
#include <GP.h>

enum GP_ContextCopyFlags {
        /*
         * Copy bitmap pixels too. If not set pixels are uninitialized.
         */
        GP_COPY_WITH_PIXELS   = 0x01,
        /*
         * Copy image rotation flags. If not set flags are set to (0, 0, 0).
         */
        GP_COPY_WITH_ROTATION = 0x02,
};

GP_Context *GP_ContextCopy(const GP_Context *src, int flags);

The GP_ContextCopy() allocates and initializes a copy of the context passed as arguments.

The call returns pointer to newly allocated context or in case of malloc() failure NULL.

If GP_COPY_WITH_PIXELS is set, the bitmap contents (src→pixels) are also copied; otherwise the copy will have the same dimensions but undefined contents.

If GP_COPY_WITH_ROTATION is set rotation flags are copied; otherwise rotation flags are set to zero.

The free_pixels flag for the resulting context is set.

#include <core/GP_Context.h>
/* or */
#include <GP.h>

void GP_ContextFree(GP_Context *context);

Frees the context memory.

If free_pixels flag is set, the pixels buffer is freed too.

If gamma pointer is not NULL the GP_GammaRelease() is called.

Subcontext

A subcontext is a context that refers to a rectangular area within another context. Subcontexts can be used as any other contexts (including subcontext creation).

Warning If you create overlaping subcontexts the result is undefined.

Calling GP_ContextFree() on a allocated subcontext is safe; the bitmap is not freed as it belongs to another context; it will be freed when the parent context is freed (i.e. the free_pixels flag is not set when creating subcontext).

Caution The subcontext doesn’t hold a reference to the original context, so once the parent context is freed the subcontext pixels pointer is not valid anymore.
#include <core/GP_Context.h>
/* or */
#include <GP.h>

GP_Context *GP_SubContext(const GP_Context *context, GP_Context *subcontext,
                          GP_Coord x, GP_Coord y, GP_Size w, GP_Size h);

GP_Context *GP_SubContextAlloc(const GP_Context *context,
                               GP_Coord x, GP_Coord y, GP_Size w, GP_Size h);

Creates subcontext of a context. The rectangular area must fit into the parent context.

The GP_SubContext() function initializes the passed pointer as a subcontext of a context and returns pointer to the initialized subcontext (i.e. the same pointer you passed as the subcontext parameter).

The GP_SubContextAlloc() function allocates GP_Context structure and initializes it as a subcontext. This function may return NULL in case of malloc() failure and the newly created context should be later freed with GP_ContextFree().

Conversions

#include <core/GP_Context.h>
/* or */
#include <GP.h>

GP_Context *GP_ContextConvertAlloc(const GP_Context *src,
                                   GP_PixelType dst_pixel_type);

GP_Context *GP_ContextConvert(const GP_Context *src, GP_Context *dst);

Converts a context to different pixel type.

This is naive implementation that only multiplies/divides the pixel values.

To get a better result use dithering filters instead.

Misc

#include <core/GP_Context.h>
/* or */
#include <GP.h>

void GP_ContextPrintInfo(const GP_Context *self);

This function prints the content of a GP_Context structure, in a readable format, into the stdout.