Object Icon’s graphic facilities are based on Icon’s, but with quite a large number of features omitted, and a few added, most notably support for transluscent colours, alpha channels and compositing. Also, the programming interface is re-cast into an object-oriented form, consistent with the rest of the library.

The following notable features in Icon’s graphic facilities are omitted from Object Icon’s :-

Icon’s graphics facilities are described in the following document :-

Opening a window

Use the constructor of graphics.Window to open a window. This gives a hidden window of size 1 pixel by 1 pixel, with default attributes. These can then be modified using setter methods before the window is made visible by setting the canvas type to “normal”. For example :-

   w := Window().
      set_bg("light grey").
      set_canvas("normal") | stop(&why)

The Window class has methods for manipulating the window and drawing in it.

Setting Window attributes

The various setter methods for setting window attributes are summarised in the following table.

Method Parameter(s) Description
set_bg string Background color
set_canvas string Window visibility
clip 4xinteger Clipping region
unclip - Unset clipping region
set_draw_op string Compositing operator
set_dx integer Window horizontal offset
set_dy integer Window vertical offset
set_fg string Foreground color
set_font string Current text font
set_geometry 4xinteger Window position and size
set_height integer Window height
set_icon string or Pixels Window icon
set_image string or Pixels Draw an image and set window size to image size
set_label ucs Window label (title)
set_leading real Proportion of font height to add as vertical inter-line spacing
set_line_style string Line style to use in drawing
set_line_width integer Line width to use in drawing
set_max_height integer Maximum window height
set_max_size 2xinteger Maximum window size
set_max_width integer Maximum window width
set_min_height integer Minimum window height
set_min_size 2xinteger Minimum window size
set_min_width integer Minimum window width
set_pattern string or Pixels Image to use to fill instead of foreground colour
set_pointer string Mouse pointer
set_pos 2xinteger Window position on screen
set_transient_for Window Transient-for window
set_x integer Window x position
set_y integer Window y position
set_resize flag Resizable flag
set_size 2xinteger Window size
set_width integer Window width

Most of the attributes have corresponding get methods.


Fonts follow the same format as in Icon, with some minor enhancements. The environment variable OI_FONT specifies the default font to use in a window, and OI_FONT_SIZE specifies the default fontsize; if not given the default font size is 12. Font sizes need not be integers. Font sizes can also be specified as relative to the default font size, by prefixing with a + or a -, or as a factor of the default font size by prefixing with a *. So for example, if OI_FONT_SIZE was set to “11.5”, then “sans” would be the same as “sans,11.5”, and “sans,+2” would be the same as “sans,13.5”, and “sans,*2” would be the same as “sans,23” A static method, Window.get_default_font_size(), returns the default font size.

On X11, Xft, Fontconfig and Freetype are used for fonts. With fontconfig, further customization can be achieved by editing the user configuration file, found in ~/.config/fontconfig/fonts.conf, and defining patterns for the following family names :-

Icon font family Xft family name Default value
fixed Object Icon fixed mono
mono Object Icon mono mono
typewriter Object Icon typewriter courier
sans Object Icon sans helvetica
serif Object Icon serif times

An example entry, which makes the Icon mono family use the “Deja Vu Sans Mono” font, is as follows :-

<match target="pattern">
   <test name="family">
      <string>Object Icon mono</string>
   <edit name="family" mode="prepend" binding="same">
      <string>Deja Vu Sans Mono</string>

A font specifier may specify a string to be interpreted directly by the platform’s font system. When using fontconfig, this is done by prepending the string “fc:” to the specifier (for example, “fc:Bitstream Vera Sans-11”). The result of the get_font method will in fact always be in this platform-specific format. Note that the setting of OI_FONT_SIZE has no effect on a font specified in this way.

Colours and Palettes

Colour specifications and palettes follow the same format as in Icon, with an enhancement to allow specification of transluscent colours. For a colour specified numerically, a fourth optional value can be added to specify the alpha value. Also, fractions between 0 and 1 may be used instead of exact 16 bit integer values if desired. For a colour specified with a string name, a percentage may be appended to give the transluscency. For example :-

"45874,0,0,52428"   # 70% red, 80% alpha
"0.1,0.2,0.3,0.4"   # 10% red, 20% blue, 30% green 40% alpha
"dark blue 50%"

Images and the Pixels class

Image data is represented using the graphics.Pixels class. This is just a two-dimensional array of pixel data, stored in various formats. Pixel data can come from a number of sources :-

To create an instance from an image file use the Pixels constructor, passing the filename. The constructor is also used to create an instance from raw data. This can easily be done using the preprocessor $load directive to compile image data into the executable. An example of this would be

$load FLINTSTONES "/tmp/flintstones.jpg"

   i := Pixels(FLINTSTONES)

The $load directive defines the preprocessor symbol FLINTSTONES with the value being a string containing the contents of the specified file. An advantage of using this technique is that the image file does not of course have to be present at runtime (only at compile time).

To get pixels from a Window, use its get_pixels method, and to create a new blank image, use the Pixels constructor, passing width, height and optionally the desired underlying format. For example :-

   i := Pixels(3, 3, Pixels.RGBA32)

creates a 3x3 image using 32 bits per pixel. Some formats do not store an alpha channel; in this case reading back from the image always gives an opaque pixel.

Paletted images are supported. Rather than storing pixel data directly, indices into a palette of colours are stored instead. Additional methods in Pixels are provided for editing the palette for such formats.

A Pixels image can be used with a Window in several ways :-

After use, a Pixels instance should be closed in order to free the memory it uses.

Compositing and draw_op

The compositing operator used by the drawing functions can be set using set_draw_op. The possible values are :-

“atop”, “clear”, “dest”, “dest atop”, “dest in”, “dest out”, “dest over”, “in”, “out”, “over”, “source”, “xor”

The default is “over”.

Here is an example (it requires this image to compile) which illustrates how different draw operators can be used. This example creates a circular mask, then combines it with an image using the “in” operator, and finally adds a blue background using the “dest over” operator.

Download cheetah.icn

import io, graphics,

$load CAT "cheetah_cubs.jpg"

procedure circle_mask(d)
   local p, i, j, r2, r, s, a
   p := Pixels(d, d, Pixels.A8)
   r := d / 2
   r2 := r * r
   every j := 0 to d - 1 do
      every i := 0 to d - 1 do
         if (s := (i - r)^2 + (j - r)^2) < r2 then {
            a := ((r2 - s) * 65535) / r2
            p.set_rgba(i, j, 0,0,0, a)
   return p

procedure main()
   local cat, cm, w

   # Create a image of the cheetahs
   cat := Pixels(CAT) | stop(&why)

   # Create a circular mask image.  The parameter gives the diameter.
   # The further away from the centre of the circle, the more
   # transparent is the mask, with the centre being opaque.
   cm := circle_mask(cat.get_width())

   w := Window().
      # Copy the circle mask to w; "source" must be used here so that
      # the mask is copied to w (rather than combined with w's
      # underlying background).
      # Now draw the cat using the "in" operator.  Where the alpha
      # value of the mask (and hence w) is more opaque, more of the
      # cat image is written to w.  Conversely, where it is more
      # transparent, less of the cat image is written.  The alpha
      # values in w are unchanged.
      draw_image(,, cat).
      # Finally set a background colour.  Where w is opaque, less blue
      # is written; where transparent, more.  Afterwards, the alpha
      # values of w will be 100% opaque.
      set_fg("very light blue").
      set_draw_op("dest over").


The cheetah image looks like this in its raw form :-

The resulting window is as follows :-

An alternative way to do the above is to use the mask parameter of the copy_to method. The source window is copied in the usual way, but with the alpha channel being read from corresponding pixels in the mask. The main() procedure can then be re-written as follows :-

procedure main()
   local cat, cm, w, mw

   # Create a Window with the image of the cheetahs
   cat := Window().set_image(CAT)

   # Create a circular mask image.  The parameter gives the diameter.
   # The further away from the centre of the circle, the more
   # transparent is the mask, with the centre being opaque.
   cm := circle_mask(cat.get_width())

   # Create a mask window containing the circle mask; "source" must be
   # used here so that the mask is copied (rather than combined with
   # mw's underlying background).
   mw := Window().set_draw_op("source").set_image(cm)

   # Create a destination window with a light blue background.
   w := Window().
      set_size(cat.get_width(), cat.get_height()).
      set_bg("very light blue").erase_area()

   # Copy the cat window to the destination using the mask window as a
   # mask.  The alpha values of the mask are combined with the colour
   # values of the cat, and then combined with the blue background of
   # the destination window.
   cat.copy_to(,,,, w,,, mw)

   # Display the destination window.


The filter method is used to efficiently transform a rectangular area of pixels, according to one of several pre-defined filters. The available filters are as follows :-


Events are generated from a window as lists. The first element of the list gives the event code, which is one of the following. The number and type of the other elements depends on the code.

Type Description
Mouse.LEFT_PRESS Mouse left button press
Mouse.MIDDLE_PRESS Mouse middle button press
Mouse.RIGHT_PRESS Mouse right button press
Mouse.LEFT_RELEASE Mouse left button release
Mouse.MIDDLE_RELEASE Mouse middle button release
Mouse.RIGHT_RELEASE Mouse right button release
Mouse.DRAG Mouse drag with any button down
Mouse.MOVEMENT Mouse movement with no button down
Mouse.WHEEL_UP Mouse wheel upward direction
Mouse.WHEEL_DOWN Mouse wheel downward direction
Mouse.ENTER Mouse cursor enters window
Mouse.EXIT Mouse cursor leaves window
Window.RESIZE Window resized
Window.CLOSE_BUTTON Window close button pressed
Window.INVOKE_LATER Internal use by gui package
Selection.REQUEST Another application has requested a selection
Selection.RESPONSE Another application has responded to a request for a selection
Selection.CLEAR A selection must be cleared
String or ucs A key representing the given string has been pressed or released
Positive integer A key with the numeric code has been pressed or released

The class graphics.Key contains a several constants which match the numeric key codes in the last class of event in the above table.

The keyboard and mouse events all produce a list of 5 items (including the initial code) :-

  1. Code
  2. Mouse x position
  3. Mouse y position
  4. Timestamp in milliseconds
  5. Keyboard state flags, being a combination of

Cairo graphics library

There is an Object Icon interface to the Cairo 2D graphics library, which can be used as an alternative to the built-in drawing methods.

The various classes can be found in the cairo package. There is a program cairotest in the examples directory which shows the various features in action.