CD - Canvas Draw

Lua 3.2 Binding

Overview

CDLua was developed to make all functionalities of the CD library available to Lua programmers. It was written in C, with the aid of the toLua utility (a tool to automatically generate C/C++ bindings for Lua).

To use the CDLua bindings, your executable must be linked with the CDLua library, and you must call the initialization function cdlua_open() declared in the header file cdlua.h, as seen in the example below:

#include <iup.h>
#include <lua.h>
#include <lualib.h>
#include <iuplua.h>
#include <cdlua.h>
void main(void)
{
  IupOpen();
  iolib_open();
  strlib_open();
  mathlib_open();
  cdlua_open();
  iuplua_open();
  lua_dofile("myprog.lua");
  IupMainLoop();
  IupClose();
}

The cdlua_open() function registers all CD functions and constants your Lua program will need. The use of the CDLua functions in Lua is generally identical to their equivalents in C. Nevertheless, there are several exceptions due to differences between the two languages.

As with CD, it is important to make sure there is a currently active canvas before calling any CDLua function. Otherwise, the Lua program will be aborted with an error message. Canvases are created and activated as in C:

cdlua_canvas = cdCreateCanvas(CD_IUP, iuplua_canvas)
if cdlua_canvas == nil then
  -- deal with error
  ...
else
  cdActivate(cdlua_canvas)
end

Notice that, as opposed to C, in which the flags are combined with the bitwise operator OR, in Lua the flags are added arithmetically.

In order to print the version of the CD library, use the global variable CDLUA_VERSION, which contains a description as in LUA_VERSION, for instance: "CDLua 4.3". The number is the same returned by the cdVersion() function.

Data Types

Lua native data types were not enough for the CDLua bind, because CD deals with a series of data types other than strings and numbers. Therefore, to provide the eficiency required, usertags were used to implement such data types. They are:

color_tag: type used by functions cdEncodeColor, cdDecodeColor, cdPixel, cdForeground and cdBackground.
imageex_tag: type used by functions cdCreateImageEx, cdKillImageEx, cdGetImageEx, cdPutImage and cdPutImageEx.
image_tag: type used by functions cdCreateImage, cdKillImage, cdGetImage, cdPutImage and cdPutImage.
imagergb_tag: type used by functions cdCreateImageRGB, cdKillImageRGB, cdGetImageRGB and cdPutImageRGB.
imagergba_tag: type used by functions cdCreateImageRGBA, cdKillImageRGBA and cdPutImageRGBA.
imagemap_tag: type used by functions cdCreateImageMap, cdKillImageMap and cdPutImageMap.
palette_tag: type used by functions cdCreatePalette, cdKillPalette, cdPalette and cdPutImageMap.
pattern_tag: type used by functions cdCreatePattern, cdKillPattern and cdPattern.
stipple_tag: type used by functions cdCreateStipple, cdKillStipple and cdStipple.
channel_tag: type used by channel image access methods. Internal use only.
canvas_tag: type used by cdCreateCanvas, cdActivate, cdKillCanvas, cdGetContext and cdContextCaps.
state_tag: type used bycdSaveState and cdRestoreState.

All the usertags are available to the C programmer in Lua global variables such as CDLUA_COLOR_TAG, CDLUA_IMAGEEX_TAG, and so on. The respective structures are defined in the cdluapvt.h header.

Note that the structure cdContext is stored as a number, and did not need a usertag.

Beacause of some applications that interchange the use of CD canvases in Lua and C, we build a simple C function to retreive the pointer of a CD canvas created in Lua: cdCanvas* cdlua_getcanvas(void). It is declared in the cdlua.h header. The canvas to be retreived must be in the Lua stack before calling this function. Usually you will do a lua_pushobject(lua_getglobal("mycanvas")) call before it.
 

New Functions

New functions (without equivalents in C) were implemented to create and to destroy objects of the new data types. Functions were developed to create and remove images, pattern, stipple and palette.

In case of error (for example, lack of memory), the creation functions return nil. The user must verify its return value. See the example below:

pattern = cdCreatePattern(16, 16)
if pattern == nil then
  ...
end

All new types can have their values checked or changed directly as if they were Lua tables:

pattern[y*16 + x] = cdEncodeColor(r, g, b)
...
color = pattern[y*16 + x]
r, g, b = cdDecodeColor(color)
...
cdPattern(pattern)

Notice that the type of value returned or received by pattern[i] and palette[i] is color_tag, the same type used with functions cdEncodeColor, cdDecodeColor, cdPixel, cdForeground and cdBackground.

Types imagergb and imagergba are more complex. They work as channel tables. Each channel works as a value table which should be consulted or modified in the following way:

imagergb = cdCreateImageRGB(100, 200)
...
imagergb.r[y*100 + x] = red
...
green = imagergb.g[y*100 + x]

Notice also that it is always important to define the index in the channels, because, for instance, the type of imagergb.r (without index), channel_tag, is internal to the implementation of CDLua and it is useless for the end user. The order of the tables is important, so that imagergb[n].r has no meaning to CDLua and the expression will cause a fatal error. Finally, the user could expect the value of imagergb[n] to be of type color_tag. Unfortunately, this is not the case, and such expression will cause the same fatal error.

Known channel names are: r, g, b, a, i, c (the two last ones are used only with imageex).

Modified Functions

Some functions were modified to receive parameters of the types imagergb_tag, imagergba_tag, imagemap_tag, palette_tag, stipple_tag and pattern_tag. These objects already have their dimensions stored internally and, therefore, the user does not need to pass them as parameters.

The functions which receive values by referencing to C were also modified in Lua. Generally, the values of parameters that would have their values modified are now returned by the function in the same order.

The functions still have the same functionality, but they are now used differently:

w, h = cdGetCanvasSize()
red, green, blue = cdDecodeColor(CD_DARK_MAGENTA)
x, y = cdCanvas2Raster(x, y)

Error Checking

Rigorous parameter checking is performed by CDLua functions before passing the parameters to CD. When an error is considered fatal, the library interrupts the Lua program and shows an explanatory error message. Errors in the number and types of parameters, and inconsistency in the values of parameters are considered as fatal errors. In general, fatal errors are those that require a change in the Lua code and would cause an equivalent C program to crash.

All fatal errors result in a call to lua_error with a message with format "function: message", where function is the name of the function that detected the fatal error and message is a message that identifies the error. Some of the most important errors are seen in the examples below:

"cdlua: there is no active canvas!"
"cdActivate: attempt to activate a killed canvas!"
"cdCreateCanvas: unknown driver!"
"cdKillStipple: attempt to kill a killed stipple!" 
"cdCreateCanvas CD_IUP: data should be an iuplua canvas object!"
"cdCreateCanvas CD_IMAGE: data is a NIL image!"
"cdCreateCanvas CD_PRINTER: data should be of type string!"
"cdPlay: CD_SIZECB: invalid return value!"
"cdCreateCanvas CD_SIMULATE: too many parameters!"
"cdRegisterCallback: unknown callback!"
"cdPlay: driver does not implement the play function or unknown driver!"
"cdKillCanvas: attempt to kill a NIL canvas!"
"cdEncodeColor: color components values should be in range [0, 255]!"
"cdCreateStipple: stipple dimensions should be positive integers!"

The fallbacks used to modify and to check the values of types imagergb_tag, imagergba_tag, imagemap_tag, palette_tag, pattern_tag and stipple_tag also perform error checking and can detect fatal errors. The methods check for vector bounds, and for parameter types and values. The messages have the format "type 'fallback': message", as seen below:

"pattern_tag "settable": index should be a number!"
"imagemap_tag "gettable": index out of bounds!"
"stipple_tag "settable": value should belong to {0, 1}!"
"pattern_tag "settable": value should be of type color_tag!"

Integration with IMLua

CDLua is fully integrated with IMLua. Yet, both libraries are completely independent. Whenever both libraries are initialized (the order is not important), each library can detect the presence of the other and enable the interaction. Being independent, each library provides its own set of functions to create, access, modify and destroy the new data types. Actually, they share the same tag values for the data types common to CD and IM, so that objects created by CDLua are indistinguishable from objects created by IMLua. The example below shows a perfectly valid CDLua/IMLua code:

...
w, h = imImageInfo(filename)
image = cdCreateImageRGB(w, h)
imLoadRGB(filename, image)
cdPutImageRGB(image, x, y, w, h) 
imKillImageRGB(image)