## PgmCanvas

PgmCanvas — A virtual positioning class for drawables.

## Synopsis

    #include <pgm/pgm.h>

                        PgmCanvas;
    PgmCanvas *         pgm_canvas_new                      (void);
    PgmError            pgm_canvas_set_size                 (PgmCanvas *canvas,
                                                             gfloat width,
                                                             gfloat height);
    PgmError            pgm_canvas_get_size                 (PgmCanvas *canvas,
                                                             gfloat *width,
                                                             gfloat *height);
    PgmError            pgm_canvas_add                      (PgmCanvas *canvas,
                                                             PgmDrawableLayer layer,
                                                             PgmDrawable *drawable);
    PgmError            pgm_canvas_remove                   (PgmCanvas *canvas,
                                                             PgmDrawable *drawable);
    PgmError            pgm_canvas_add_many                 (PgmCanvas *canvas,
                                                             PgmDrawableLayer layer,
                                                             PgmDrawable *drawable_1,
                                                             ...);
    PgmError            pgm_canvas_remove_many              (PgmCanvas *canvas,
                                                             PgmDrawable *drawable_1,
                                                             ...);
    PgmError            pgm_canvas_set_order                (PgmCanvas *canvas,
                                                             PgmDrawable *drawable,
                                                             gint order);
    PgmError            pgm_canvas_get_order                (PgmCanvas *canvas,
                                                             PgmDrawable *drawable,
                                                             PgmDrawableLayer *layer,
                                                             gint *order);
    PgmError            pgm_canvas_get_layer_count          (PgmCanvas *canvas,
                                                             PgmDrawableLayer layer,
                                                             gint *count);
    PgmError            pgm_canvas_regenerate               (PgmCanvas *canvas);
    PgmError            pgm_canvas_get_pixel_formats        (PgmCanvas *canvas,
                                                             gulong *pixel_formats);
    PgmError            pgm_canvas_get_pixel_offsets        (PgmCanvas *canvas,
                                                             gfloat *x,
                                                             gfloat *y);

## Object Hierarchy

      GObject
       +----GstObject
             +----PgmCanvas

## Signals

      "drawable-added"                                 : Run First
      "drawable-removed"                               : Run First
      "drawable-reordered"                             : Run First
      "regenerated"                                    : Run First
      "size-changed"                                   : Run First

## Description

### Canvas coordinates

A PgmCanvas object is used as a virtual positioning system for the PgmDrawable. It provides Pigment users (application developers using the library) a very simple and flexible way to build their user interface without having to worry about visual rendering problems such as non square pixels, aspect ratio of images or videos, keeping proportional alignment or spacing between objects when resizing, etc.

The origin of the canvas coordinate system corresponds to the upper-left corner. A canvas can only understand canvas coordinates, and those coordinates have nothing to do with pixels. This is why the methods you can call on a canvas always use coordinates with floating numbers. Let's say you want to draw a user interface with an aspect ratio of 16:9 (which is nice to do on most wide screen TV of the market). In that case you would for example set the canvas size to width 16.0 and height 9.0. Every coordinate and size of the drawables you are going to put on the canvas will use the same coordinate system. So, if you wanted to put an image in the middle of the user interface you would compute its position so that its center is at (8.0, 4.5) on the canvas. You would also define the size of that image using values of the same scale. For example, the width of the image could be 1.0 and its height 1.0 thus making appear as a square.

A canvas is never drawn directly which is why you can use abstract coordinates to place objects on it. Also, since it is using floating numbers there is no limit in precision. At some point we still need to have a visual representation of what is on the canvas, this is what PgmViewport does. A canvas can be projected on 0 to n viewport.

It is entirely the application's responsibility to decide how many drawables are going to be drawn on the canvas and their size. Using the viewport information the application can decide which aspect ratio to use and how many drawables can fit on the canvas while still being easily readable. If for example the end user (user interface user) steps away from the monitor and cannot read the text the application can just make the drawables bigger on the canvas which will automatically get reprojected onto the viewport.

When adding a drawable to a canvas you have to choose a PgmDrawableLayer in which that drawable will be stored. The three layers are used to handle a first control on the drawing order. The first layer drawn is the `PGM_DRAWABLE_FAR` one, all the drawables inside this layer will appear behind the two others. The second layer drawn is the `PGM_DRAWABLE_MIDDLE` one, the drawables inside this layer will be drawn over the `PGM_DRAWABLE_FAR` layer and behind the `PGM_DRAWABLE_NEAR` layer. The third layer drawn is the `PGM_DRAWABLE_NEAR` one, all the drawables inside this layer will be drawn over the two others. This is useful to make sure that dialog is shown on top of all the other objects for example or to make sure that no object is going to go behind the background. Drawables inside a layer are automatically ordered by Pigment depending on their z coordinate set through `pgm_drawable_set_position()`. Pigment also provides a way to reorder drawables inside a layer that have the same z coordinate thanks to the `pgm_canvas_set_order()` function.

When a drawable is created it has a floating reference, when you add it to the canvas, the canvas takes a reference to that drawable and sink the object reference. That means that the canvas now owns the drawable reference and you do not need to unref the drawable when cleaning up your objects. Just unrefing the canvas is going to cleanup all the drawables that were added to it. Here is an example:

Example 3. Create a canvas, add drawables, unref the canvas

    PgmCanvas *canvas = pgm_canvas_new ();
    PgmDrawable *drb1 = pgm_text_new ("hello world");
    PgmDrawable *drb2 = pgm_image_new_from_fd (fd, 1024);
    PgmDrawable *drb3 = pgm_image_new_from_image (drb2);

    pgm_canvas_add_many (canvas, PGM_DRAWABLE_MIDDLE, drb1, drb2, drb3, NULL);
    gst_object_unref (canvas); // Unref canvas, drb1, drb2 and drb3

The drawable-added signal is fired whenever a new drawable is added to the canvas. Likewise the drawable-removed signal is fired whenever an drawable is removed from the canvas. The drawable-reordered signal is fired whenever a drawable is reordered inside the canvas.

Last reviewed on 2007-08-03 (0.3.0)

## Details

### PgmCanvas

    typedef struct {
      /* Layer lists */
      GList *far_layer;
      GList *middle_layer;
      GList *near_layer;

      /* Canvas size */
      gfloat width, height;

      /* Pixel offsets */
      gfloat pixel_offset_x, pixel_offset_y;

      /* Mask of supported formats */
      gulong pixel_formats;
    } PgmCanvas;

The PgmCanvas structure.

GList *`far_layer`; | the list of PgmDrawable in the PGM_DRAWABLE_FAR layer.
GList *`middle_layer`; | the list of PgmDrawable in the PGM_DRAWABLE_MIDDLE layer.
GList *`near_layer`; | the list of PgmDrawable in the PGM_DRAWABLE_NEAR layer.
gfloat `width`; | the canvas width.
gfloat `height`; | the canvas height.
gfloat `pixel_offset_x`; | the pixel offset on x.
gfloat `pixel_offset_y`; | the pixel offset on y.
gulong `pixel_formats`; | the pixel formats mask.

### pgm_canvas_new ()

    PgmCanvas *         pgm_canvas_new                      (void);

Creates a new PgmCanvas instance.

MT safe.

Returns : | a new PgmCanvas instance.

### pgm_canvas_set_size ()

    PgmError            pgm_canvas_set_size                 (PgmCanvas *canvas,
                                                             gfloat width,
                                                             gfloat height);

Sets the `width` and `height` size of `canvas`. These values are not supposed to be pixels. You are strongly encouraged to use abstract coordinates such as 16.0x9.0 for a 16:9 interface or 4.0x3.0 for a 4:3 one, etc.

MT safe.

`canvas` : | a PgmCanvas object.
`width` : | the canvas width.
`height` : | the canvas height.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_get_size ()

    PgmError            pgm_canvas_get_size                 (PgmCanvas *canvas,
                                                             gfloat *width,
                                                             gfloat *height);

Retrieves width and height size of `canvas` in `width` and `height`.

MT safe.

`canvas` : | a PgmCanvas object.
`width` : | a pointer to a gfloat where the canvas width is going to be stored.
`height` : | a pointer to a gfloat where the canvas height is going to be stored.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_add ()

    PgmError            pgm_canvas_add                      (PgmCanvas *canvas,
                                                             PgmDrawableLayer layer,
                                                             PgmDrawable *drawable);

Adds `drawable` to `canvas` in `layer`. Both `canvas` and `drawable` reference counts will be increased by one as they are linking to each other. `drawable` reference will be sink as well so if the object reference was floating it now belongs to `canvas` and you don't have to unref `drawable` when cleaning up your objects.

MT safe.

`canvas` : | a PgmCanvas object.
`layer` : | a PgmDrawableLayer to add drawable into.
`drawable` : | the PgmDrawable object to add.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_remove ()

    PgmError            pgm_canvas_remove                   (PgmCanvas *canvas,
                                                             PgmDrawable *drawable);

Removes `drawable` from `canvas`. Both `canvas` and `drawable` reference counts will be decreased by one as they were referencing each other. In most cases that means that `drawable` is going to be destroyed because `canvas` owned the only reference to it. If you want to reuse `drawable` in another canvas or in another layer you need to take a reference to it before removing it from `canvas`.

MT safe.

`canvas` : | a PgmCanvas object.
`drawable` : | the PgmDrawable object to remove.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_add_many ()

    PgmError            pgm_canvas_add_many                 (PgmCanvas *canvas,
                                                             PgmDrawableLayer layer,
                                                             PgmDrawable *drawable_1,
                                                             ...);

Adds a NULL-terminated list of drawables to `canvas`. This function is equivalent to calling `pgm_canvas_add()` for each member of the list.

MT safe.

`canvas` : | a PgmCanvas object.
`layer` : | a PgmDrawableLayer to add the drawables into.
`drawable_1` : | the PgmDrawable object to add.
`...` : | additional PgmDrawable objects to add.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_remove_many ()

    PgmError            pgm_canvas_remove_many              (PgmCanvas *canvas,
                                                             PgmDrawable *drawable_1,
                                                             ...);

Removes a NULL-terminated list of drawables from `canvas`. This function is equivalent to calling `pgm_canvas_remove()` for each member of the list.

MT safe.

`canvas` : | a PgmCanvas object.
`drawable_1` : | the PgmDrawable object to remove.
`...` : | additional PgmDrawable objects to remove.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_set_order ()

    PgmError            pgm_canvas_set_order                (PgmCanvas *canvas,
                                                             PgmDrawable *drawable,
                                                             gint order);

Defines the ordering of `drawable` in its layer at position `order`. Since drawables are ordered function of their z coordinate, set through `pgm_drawable_set_position()`, this function is only useful if you want to reorder drawables at the same z coordinate. If you try to reorder a drawable inside a layer at an order where the current drawable doesn't have the same z coordinate, the function will do nothing and return an error.

MT safe.

`canvas` : | a PgmCanvas object.
`drawable` : | the PgmDrawable to reorder.
`order` : | the new position of `drawable`.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_get_order ()

    PgmError            pgm_canvas_get_order                (PgmCanvas *canvas,
                                                             PgmDrawable *drawable,
                                                             PgmDrawableLayer *layer,
                                                             gint *order);

Retrieves the layering of `drawable`.

MT safe.

`canvas` : | a PgmCanvas object.
`drawable` : | the PgmDrawable to retrieve the layering.
`layer` : | a pointer to a PgmDrawableLayer in which `drawable` layer is going to be stored.
`order` : | a pointer to a gint in which the position of `drawable` in the `layer` is going to be stored.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_get_layer_count ()

    PgmError            pgm_canvas_get_layer_count          (PgmCanvas *canvas,
                                                             PgmDrawableLayer layer,
                                                             gint *count);

Retrieves the number of drawables in `layer`.

MT safe.

`canvas` : | a PgmCanvas object.
`layer` : | the PgmDrawableLayer to retrieve the size.
`count` : | a pointer to a gint in which the number of drawables in `layer` is going to be stored.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_regenerate ()

    PgmError            pgm_canvas_regenerate               (PgmCanvas *canvas);

Affects all the drawables of the canvas which need to be displayed at a fixed size. It regenerates those rasterized pixmaps which have been affected by the canvas projection.

MT safe.

`canvas` : | a PgmCanvas object.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_get_pixel_formats ()

    PgmError            pgm_canvas_get_pixel_formats        (PgmCanvas *canvas,
                                                             gulong *pixel_formats);

Gets the list of the supported pixel formats by `canvas`. This is the intersection of the pixel formats supported by the viewports to which `canvas` is bound.

MT safe.

`canvas` : | a PgmCanvas object.
`pixel_formats` : | a pointer to a gulong where the mask of supported PgmImagePixelFormat is going to be stored.
Returns : | a PgmError indicating success/failure.

### pgm_canvas_get_pixel_offsets ()

    PgmError            pgm_canvas_get_pixel_offsets        (PgmCanvas *canvas,
                                                             gfloat *x,
                                                             gfloat *y);

Gets the x and y ratios corresponding to the offsets in canvas coordinates between two pixels at z=0.

`canvas` : | a PgmCanvas object.
`x` : | a pointer to a gfloat where the x pixel offset is going to be stored.
`y` : | a pointer to a gfloat where the y pixel offset is going to be stored.
Returns : | a PgmError indicating success/failure.

## Signal Details

### The `"drawable-added"` signal

    void                user_function                      (PgmCanvas       *canvas,
                                                            PgmDrawable     *drawable,
                                                            PgmDrawableLayer layer,
                                                            gint             order,
                                                            gpointer         user_data)      : Run First

Will be emitted after `drawable` was added to `canvas`.

`canvas` : | the PgmCanvas
`drawable` : | the PgmDrawable that was added to `canvas`
`layer` : | the PgmDrawableLayer in which `drawable` was added
`order` : | the order in `layer` in which `drawable` was added
`user_data` : | user data set when the signal handler was connected.

### The `"drawable-removed"` signal

    void                user_function                      (PgmCanvas       *canvas,
                                                            PgmDrawable     *drawable,
                                                            PgmDrawableLayer layer,
                                                            gpointer         user_data)      : Run First

Will be emitted after `drawable` was removed from `canvas`.

`canvas` : | the PgmCanvas
`drawable` : | the PgmDrawable that was removed from `canvas`
`layer` : | the PgmDrawableLayer from which `drawable` was removed
`user_data` : | user data set when the signal handler was connected.

### The `"drawable-reordered"` signal

    void                user_function                      (PgmCanvas       *canvas,
                                                            PgmDrawable     *drawable,
                                                            PgmDrawableLayer layer,
                                                            gint             order,
                                                            gpointer         user_data)      : Run First

Will be emitted after `drawable` was reordered in `canvas`.

`canvas` : | the PgmCanvas
`drawable` : | the PgmDrawable that was reordered in `canvas`
`layer` : | the PgmDrawableLayer in which `drawable` was reordered
`order` : | the new order of `drawable`
`user_data` : | user data set when the signal handler was connected.

### The `"regenerated"` signal

    void                user_function                      (PgmCanvas *canvas,
                                                            gpointer   user_data)      : Run First

Will be emitted after `canvas` received a regeneration request.

`canvas` : | the PgmCanvas
`user_data` : | user data set when the signal handler was connected.

### The `"size-changed"` signal

    void                user_function                      (PgmCanvas *canvas,
                                                            gpointer   user_data)      : Run First

Will be emitted after `canvas` size was changed.

`canvas` : | the PgmCanvas
`user_data` : | user data set when the signal handler was connected.

## See Also

#PgmViewport, PgmDrawable.