High level drawing api

jtappin edited this page Dec 31, 2012 · 6 revisions

GtkFortran High Level Graphics API

The graphics specific modules provide a high level interface to the GtkDrawingArea widget which is compatible with the plplot library and at least in simple cases relieves the user of the hassle of managing redraws. There is also a high level interface to the gdk-pixbuf library that allows the easy mapping of 2 and 3 dimensional Fortran arrays to GdkPixbuf objects.

gtk_draw_hl

This module provides a high-level drawing interface which automatically handles redrawing on exposure, and bundles the most likely events to be needed.

Note:

This module has undergone a major rewrite which has considerably streamlined the code. To the ordinary user, the most noticable difference is that the backing image is now a cairo image surface rather than a GDK pixbuf. When using PLplot, the "memcairo" device is not readily usable any more, however cumulative plotting (e.g. PLplot's strip charts) now works correctly.

Routine List

  • hl_gtk_drawing_area_new; Create the drawing area.
  • hl_gtk_drawing_area_get_surface; Get the backing cairo surface
  • hl_gtk_drawing_area_expose_cb; Default callback for expose events.
  • hl_gtk_drawing_area_destroy_cb; Default callback for destroy signal
  • hl_gtk_drawing_area_resize_cb; Default callback for size-allocate signal
  • hl_gtk_drawing_area_cairo_new; Create a cairo context attached to the backing surface.
  • hl_gtk_drawing_area_resize: Resize the drawing area and the backing surface
  • hl_gtk_drawing_area_cairo_destroy; Destroy the context.

hl_gtk_drawing_area_new

  function hl_gtk_drawing_area_new(scroll, size, ssize, expose_event, &
       & data_expose, button_press_event, data_button_press, &
       & button_release_event, data_button_release, scroll_event, &
       & data_scroll, motion_event, data_motion, realize, data_realize, &
       & configure_event, data_configure, key_press_event, data_key_press, &
       & key_release_event, data_key_release, enter_event, data_enter, &
       & leave_event, data_leave, destroy, data_destroy, event_mask, &
       & event_exclude, auto_add_mask, &
       & tooltip, has_alpha, size_allocate, data_size_allocate) result(plota)

    type(c_ptr) :: plota
    type(c_ptr), intent(out), optional :: scroll
    integer(kind=c_int), intent(in), optional, dimension(2) :: size, ssize
    type(c_funptr), optional :: expose_event, button_press_event, &
         & button_release_event, scroll_event, key_press_event, &
         & key_release_event, motion_event, realize, configure_event,&
         & enter_event, leave_event, destroy, size_allocate
    type(c_ptr), intent(in), optional :: data_expose, data_button_press, &
         & data_button_release, data_scroll, data_motion, data_realize, &
         & data_configure, data_key_press, data_key_release, data_enter, &
         & data_leave, data_destroy, data_size_allocate
    integer(kind=c_int), intent(in), optional :: event_mask, event_exclude
    integer(kind=c_int), intent(in), optional :: auto_add_mask
    character(kind=c_char), dimension(*), optional, intent(in) :: tooltip
    integer(kind=c_int), intent(in), optional :: has_alpha

A high-level drawing area

Argument Type Required? Description
SCROLL c_ptr optional If present, then the drawing area will be placed in a scrollable window, whose pointer will be returned here. If it is present, then it rather than the drawable should be used for packing.
SIZE c_int() optional The requested size for the area. If no size is given then a default size of 256x256 is used.
SSIZE c_int() : optional The requested size for a scrolling window
EXPOSE_EVENT c_funptr optional Callback for expose-event signal N.B. In GTK3 the signal is called "draw". If this is not given then a default handler is provided which copies the image surface to the drawing area.
DATA_EXPOSE c_ptr optional Data for expose_event callback
BUTTON_PRESS_EVENT c_funptr optional Callback for button-press-event signal
DATA_BUTTON_PRESS c_ptr optional Data for button_press_event callback
BUTTON_RELEASE_EVENT c_funptr optional Callback for button-release-event signal
DATA_BUTTON_RELEASE c_ptr optional Data for button_release_event callback
SCROLL_EVENT c_funptr optional Callback for scroll-event signal
DATA_SCROLL c_ptr optional Data for scroll_event callback
REALIZE c_funptr optional Callback for realize signal
DATA_REALIZE c_ptr optional Data for realize callback
CONFIGURE_EVENT c_funptr optional Callback for configure-event signal
DATA_CONFIGURE c_ptr optional Data for configure_event callback
KEY_PRESS_EVENT c_funptr optional Callback for key-press-event signal
DATA_KEY_PRESS c_ptr optional Data for key_press_event callback
KEY_RELEASE_EVENT c_funptr optional Callback for key-release-event signal
DATA_KEY_RELEASE c_ptr optional Data for key_release_event callback
MOTION_EVENT c_funptr optional Callback for the motion-notify-event signal
DATA_MOTION c_ptr optional Data for motion_event
ENTER_EVENT c_funptr optional Callback for the enter-notify-event signal
DATA_ENTER c_ptr optional Data for enter_event
LEAVE_EVENT c_funptr optional Callback for the leave-notify-event signal
DATA_LEAVE c_ptr optional Data for leave_event
DESTROY c_funptr optional Callback when the widget is destroyed.
DATA_DESTROY c_ptr optional Data to pass to the destroy callback.
EVENT_MASK c_int optional Mask for which events to pass.
EVENT_EXCLUDE c_int optional Mask for events not to pass (this might be used to prevent auto-enabling an event that should only be enabled by user actions)
AUTO_ADD_MASK boolean optional Set to FALSE to disable automatically adding events to the event mask if a handler is provided.
TOOLTIP string optional Tooltip for the drawing area.
HAS_ALPHA boolean optional If a pixbuf is used, should it have an alpha (transparency) channel (default=FALSE)
SIZE_ALLOCATE c_funptr optional Callback for the 'size-allocate' signal
DATA_SIZE_ALLOCATE c_ptr optional Data for size_allocate.

Odd notes on mask interactions and other things.

  • Scroll (wheel) events, are enabled by GDK_SCROLL_MASK or GDK_BUTTON_PRESS_MASK, thus (as far as I can see) there is no way to mask wheel events while allowing button presses to be processed.
  • It does not appear to be possible to remove events by unsetting bits in the event mask.
  • Adding a tooltip looks to implicitly enable some events.
  • An example where an explict EVENT_MASK and EVENT_EXCLUDE might be useful would be to enable motion events only if a button is down.
  • If an explicit size is given then the drawing area cannot be made smaller than that by resizing the containing window

hl_gtk_drawing_area_get_surface

  function hl_gtk_drawing_area_get_surface(area) result(isurface)
    type(c_ptr) :: isurface
    type(c_ptr), intent(in) :: area

Convenience routine to get the backing surface of a drawing area.

Argument Type Required? Description
AREA c_ptr required The drawing area whose surface is required.

hl_gtk_drawing_area_expose_cb

  function hl_gtk_drawing_area_expose_cb(area, event, data) bind(c) &
       & result(rv)
    integer(kind=c_int) :: rv
    type(c_ptr), value :: area, event, data

Default callback for exposing a drawing area. For this to be connected no explicit expose callback should be specified.

Argument Type Required? Description
AREA c_ptr required The drawing area
EVENT c_ptr required GTK2 = event structure, GTK3 = a cairo context Since this differs between versions, we won't use it.
DATA c_ptr required A pointer to user data (not used).

hl_gtk_drawing_area_destroy_cb

  subroutine hl_gtk_drawing_area_destroy_cb(area, data) bind(c)
    type(c_ptr), value :: area, data

Default callback for the destroy signal on the drawing area. Just destroys the backing surface.

Argument Type Required? Description
AREA c_ptr required The drawing area being destroyed.
DATA c_ptr required User data for the callback (not used)

hl_gtk_drawing_area_resize_cb

  subroutine hl_gtk_drawing_area_resize_cb(area, data) bind(c)
    type(c_ptr), value :: area, data

Default call back for resizing the drawing area, just copies the old backing store to the new one

Argument Type Required? Description
AREA c_ptr required The drawing area being destroyed.
DATA c_ptr required User data for the callback (not used)

hl_gtk_drawing_area_cairo_new

  function hl_gtk_drawing_area_cairo_new(area) result(cr)
    type(c_ptr) :: cr
    type(c_ptr), intent(in) :: area

Create a cairo context which will draw into the backing surface

Argument Type Required? Description
AREA c_ptr required The drawing area to which we will draw.

After the drawing operations, you should call gtk_widget_queue_draw to update the plot on the screen and hl_gtk_pixbuf_cairo_destroy to destroy the cairo context.

hl_gtk_drawing_area_cairo_destroy

  subroutine hl_gtk_drawing_area_cairo_destroy(cr, destroy_surface)

    type(c_ptr), intent(inout) :: cr
    integer(kind=c_int), intent(in), optional :: destroy_surface

Update the backing surface and destroy the cairo context

Argument Type Required? Description
CR c_ptr required The cairo context to put in the pixbuf
DESTROY_SURFACE boolean optional Set to TRUE to destroy the cairo_surface as well as the context. Normally the cairo surface is destroyed by the destroy callback of the drawing area, so does not need to be explicitly destroyed.

This is called following drawing operations to the context created by hl_gtk_drawing_area_cairo_new. N.B. This does not update the window, use gtk_widget_queue_draw to do that.

hl_gtk_drawing_area_resize

  subroutine hl_gtk_drawing_area_resize(area, size, copy)
    type(c_ptr), intent(in) :: area
    integer(kind=c_int), intent(in), optional, dimension(2) :: size
    logical, optional, intent(in) :: copy

Resize a drawing area and its backing store.

Argument Type Required? Description
AREA c_ptr required The area to resize.
SIZE int(2) optional The new size, if omitted, then the backing store is resized to match the drawing area (e.g. after resizing the containing window).

GDK_PIXBUF_HL

Some routines to facilitate the use of GDK pixbufs from Fortran. Allows the use of short-int images to avoid the issues that may result from Fortran's 8-bit integers being signed while GdkPixbuf pixels are unsigned.

hl_gdk_pixbuf_new_empty

  function hl_gdk_pixbuf_new_empty(width, height, alpha, bits) &
       & result(pixbuf)
    type(c_ptr) :: pixbuf
    integer(kind=c_int), intent(in) :: width, height
    integer(kind=c_int), intent(in), optional :: alpha, bits

Create a new empty pixbuf of the given size

Argument Type Required? Description
WIDTH int required The width in pixels of the pixbuf
HEIGHT int required The height in pixels of the pixbuf
ALPHA boolean optional Whether to include an alpha channel (default=FALSE)
BITS int optional The nuber of bits per sample (default=8).

This routine will usually be called via the generic interface hl_gdk_pixbuf_new.

hl_gdk_pixbuf_new_file

  function hl_gdk_pixbuf_new_file(file, width, height, aspect, &
       & error) result(pixbuf)
    type(c_ptr) :: pixbuf
    character(len=*), intent(in) :: file
    integer(kind=c_int), optional, intent(in) :: width, height, aspect
    character(len=*), optional, intent(out) :: error

Read an image file into a new pixbuf

Argument Type Required? Description
FILE string required The file to read
WIDTH int optional The desired width for the pixbuf
HEIGHT int optional The desired height for the pixbuf
ASPECT boolean optional If sizing is given then set to TRUE to preserve the aspect ratio, or FALSE not to. If both dimensions are given, then the default is FALSE, if one is given, the default is TRUE.
ERROR gerror optional The error code & message.

This routine will usually be called via the generic interface hl_gdk_pixbuf_new.

hl_gdk_pixbuf_new_data8

  function hl_gdk_pixbuf_new_data8(data) result(pixbuf)
    type(c_ptr) :: pixbuf
    integer(kind=c_int8_t), dimension(:,:,:), intent(in) :: data

Create a pixbuf from an RGB(A) array of values.

Argument Type Required? Description
DATA int8 required The data values as a 1..4 x n x m array.

This routine will usually be called via the generic interface hl_gdk_pixbuf_new.

hl_gdk_pixbuf_new_data8g

  function hl_gdk_pixbuf_new_data8g(data) result(pixbuf)
    type(c_ptr) :: pixbuf
    integer(kind=c_int8_t), dimension(:,:), intent(in) :: data

Create a pixbuf from a greyscale array of values.

Argument Type Required? Description
DATA int8 required The data values as a n x m array.

This routine will usually be called via the generic interface hl_gdk_pixbuf_new.

hl_gdk_pixbuf_new_data16

  function hl_gdk_pixbuf_new_data16(data) result(pixbuf)
    type(c_ptr) :: pixbuf
    integer(kind=c_short), dimension(:,:,:), intent(in) :: data

Create a pixbuf from an RGB(A) array of values. This version uses 2-byte integers to avoid the signing issues of the c_int8_t type.

Argument Type Required? Description
DATA short required The data values as a 1..4 x n x m array.

This routine will usually be called via the generic interface hl_gdk_pixbuf_new.

hl_gdk_pixbuf_new_data16g

  function hl_gdk_pixbuf_new_data16g(data) result(pixbuf)
    type(c_ptr) :: pixbuf
    integer(kind=c_short), dimension(:,:), intent(in) :: data

Create a pixbuf from a greyscale array of values. This version uses 2-byte integers to avoid the signing issues of the c_int8_t type.

Argument Type Required? Description
DATA short required The data values as a n x m array.

This routine will usually be called via the generic interface hl_gdk_pixbuf_new.

hl_gdk_pixbuf_get_pixels8

  subroutine hl_gdk_pixbuf_get_pixels8(pixbuf, pixels)
    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_int8_t), dimension(:,:,:), allocatable, intent(out) :: pixels

Get the pixels of a pixbuf and return them as a Fortran 3xnxm or 4xnxm array

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to read
PIXELS int8 required Will contain the image.

This is normally called via the generic hl_gdk_pixbuf_get_pixels interface. Implemented as a subroutine to allow this.

hl_gdk_pixbuf_get_pixels16

  subroutine hl_gdk_pixbuf_get_pixels16(pixbuf, pixels)
    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_short), dimension(:,:,:), allocatable, intent(out) :: pixels

Get the pixels of a pixbuf and return them as a Fortran 3xnxm or 4xnxm array. This version returns as a short array to evade the signing issues of 8-bit integers in Fortran

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to read
PIXELS short required Will contain the image.

This is normally called via the generic hl_gdk_pixbuf_get_pixels interface. Implemented as a subroutine to allow this.

hl_gdk_pixbuf_set_pixels8

  subroutine hl_gdk_pixbuf_set_pixels8(pixbuf, pixels, xoff, yoff)
    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_int8_t), dimension(:,:,:), intent(in) :: pixels
    integer, intent(in), optional :: xoff, yoff

Set the pixels of a pixbuf from a Fortran array.

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to update
PIXELS int8 required Contains the image to insert.
XOFF int optional The X-offset at which to write the image.
YOFF int optional The Y-offset at which to write the image.

This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.

hl_gdk_pixbuf_set_pixels8g

  subroutine hl_gdk_pixbuf_set_pixels8g(pixbuf, pixels, xoff, yoff)
    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_int8_t), dimension(:,:), intent(in) :: pixels
    integer, intent(in), optional :: xoff, yoff

Set the pixels of a pixbuf from a Fortran array (greyscale).

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to update
PIXELS int8 required Contains the image to insert.
XOFF int optional The X-offset at which to write the image.
YOFF int optional The Y-offset at which to write the image.

This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.

hl_gdk_pixbuf_set_pixels16

  subroutine hl_gdk_pixbuf_set_pixels16(pixbuf, pixels, xoff, yoff)
    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_short), dimension(:,:,:), intent(in) :: pixels
    integer, intent(in), optional :: xoff, yoff

Set the pixels of a pixbuf from a Fortran array (16-bit).

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to update
PIXELS short required Contains the image to insert.
XOFF int optional The X-offset at which to write the image.
YOFF int optional The Y-offset at which to write the image.

This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.

hl_gdk_pixbuf_set_pixels16g

  subroutine hl_gdk_pixbuf_set_pixels16g(pixbuf, pixels, xoff, yoff)
    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_short), dimension(:,:), intent(in) :: pixels
    integer, intent(in), optional :: xoff, yoff

Set the pixels of a pixbuf from a Fortran array (16-bit, greyscale).

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to update
PIXELS short required Contains the image to insert.
XOFF int optional The X-offset at which to write the image.
YOFF int optional The Y-offset at which to write the image.

This is normally called via the generic hl_gdk_pixbuf_set_pixels interface. N.B. To leave a gap at the "high" sides of the pixbuf, just use a smaller input array or array slice than the pixbuf size.

hl_gdk_pixbuf_info

  subroutine hl_gdk_pixbuf_info(pixbuf, nchannels, bits, alpha, &
       & height, width, rowstride)

    type(c_ptr), intent(in) :: pixbuf
    integer(kind=c_int), optional, intent(out) :: nchannels, bits, alpha, &
         & height, width, rowstride

Return information about an existing pixbuf.

Argument Type Required? Description
PIXBUF c_ptr required The pixbuf to be queried.
NCHANNELS int optional How many channels does the pixbuf have?
BITS int optional How many bits per pixel?
ALPHA boolean optional Does the pixbuf have an alpha channel?
HEIGHT int optional How many rows in the image.
WIDTH int optional How many columns in the image.
ROWSTRIDE int optional How many bytes between the start of successive rows.

hl_gdk_pixbuf_get_formats

  subroutine hl_gdk_pixbuf_get_formats(names, writable, description, &
       & scalable, license)

    character(len=*), intent(out), dimension(:), allocatable :: names
    logical, intent(out), dimension(:), allocatable, optional :: writable, &
         & scalable
    character(len=*), intent(out), dimension(:), allocatable, &
         & optional :: license
    character(len=*), intent(out), dimension(:), allocatable, &
         & optional :: description

Get information about the available file formats for reading/writing pixbufs.

Argument Type Required? Description
NAMES f_string() required The names found
WRITABLE logical() optional Whether the formats are writable.
DESCRIPTION f_string() optional Descriptions of the formats.
SCALABLE logical() optional Whether the formats are scalable.
LICENSE f_string() optional The licence of the format module.

hl_gdk_pixbuf_format_info

  function hl_gdk_pixbuf_format_info(name, mime_types, extensions, &
       & writable, scalable, description, license) result(found)

    logical :: found
    character(len=*), intent(in) :: name
    character(len=*), intent(out), optional, allocatable, &
         & dimension(:) :: mime_types, extensions
    logical, intent(out), optional :: writable, scalable
    character(len=*), intent(out), optional :: description, license

Get information about a specific file type.

Argument Type Required? Description
NAME string required The file type to query.
MIME_TYPE fstring() optional Will contain a list of mime-types associated with this file type.
EXTENSIONS fstring() optional Will contain a list of file extensions normally used for this type.
WRITABLE logical optional Whether the type is writable.
SCALABLE logical optional Whether the type is scalable.
DESCRIPTION f_string optional A description of the file type.
LICENSE f_string optional The license of the module for the file type.

Returns .true. if the type is found, .false. if it is not.

hl_gdk_pixbuf_format_find

  function hl_gdk_pixbuf_format_find(mime_type, extension) result(name)
    character(len=hl_gdk_pixbuf_type_len) :: name
    character(len=*), intent(in), optional :: mime_type, extension

Find the format type appropriate to a mime_type or a filename extension.

Argument Type Required? Description
MIME_TYPE f_string optional The mime-type to match.
EXTENSION f_string optional The file extension to match.

If no match is found then an empty string is returned. Mime_type has precedence over extension.