CD - Canvas Draw


Implementation Notes

The CD library is a basic graphic library (GL). In a GL paradigm you use primitives, which have attributes, to draw on a canvas. All the library functions reflect this paradigm.

The canvas is the basic element. It can have several forms: a paper, a video monitor, a graphic file format, etc. The virtual drawing surface where the canvas exists is represented by a driver. Only the driver knows how to draw on its surface. The user does not use the driver directly, but only the canvas.

To make the library simple we use the concept of an active canvas, over which all the primitives are drawn. This also allows the use of an expansion mechanism using function tables. Unfortunately, this very dangerous, because if a function is called without an active canvas a memory invasion will occur. On the other hand, the mechanism allows the library to be expanded with new drivers without limits.

The attributes are also separated from the primitives. They reside in the canvas in a state mechanism. If you change the attribute's state in the canvas all the primitives drawn in that canvas that depend on the attribute will be drawn in a different way.

The set of primitives is very small but complete enough to compose a GL. Some primitives are system dependent for performance reasons. Some drivers (window and device based) use system functions to optimally implement the primitives. Sometimes this implies in a misbehavior of some functions. Also some primitives do not make sense in some drivers, like server images in file-based drivers.

The set of available functions is such that it can be implemented in most drivers. Some drivers have sophisticated resources, which cannot be implemented in other drivers but can be made available for them by means of the target driver's header file. The name of the function must include the driver's prefix, for example: cdDXFSetLayer. If there is no active canvas in the target driver, the function will only be returned, without doing anything. We are currently studying a mechanism to allow more flexible extensions to the library.

Header Files

All the CD functions are declared in the cd.h header file; World Coordinate functions are declared in the wd.h header file; and each driver has a correspondent header file that must be included to create a canvas. It is important to include each driver header after the inclusion of the cd.h header file.

Compiling and Linking

The library does not impose any specific compiler directive. Therefore, using it with the default compiler options would be enough to make things work. The library always has a static linking module, but on some platforms a dynamic linking library is also available.

To compile the library it is necessary to define the symbol "__CD__". Internaly we use the definitions: "WIN32" and "SunOS", that must be defined in the respective systems.

Dinamic Library

In UNIX, dinamic libraries are automatically used by the linker. To force a static link, we suggest the inclusion of the ".a" files from the library directly into the file list for linking in the metafile.

In Windows, all libraries must also be used as DLL in order to avoid linking problems. The most important parameter in this case, Multithreaded DLL or Debug Multithreaded DLL, is at Visual C++ 5 in Project/Settings/C++/Code Generation/Use Run Time Library. This will also make your program depend on the MSVCRT.DLL file, generally available at Windows 95/98/NT4 installation program.

In both cases, the program will only run if the library files are also present somewhere in the PATH, so bear this in mind when you distribute your application.

Environment Variables

CDDIR - This environment variable is used by some drivers to locate useful data files, such as font definition files. It contains the directory path without the final slash.
CD_QUIET - In UNIX, if this variable is defined, it does not show the library's version data on sdtout.

Implementing a Driver

The best way to implement a new driver is based on an existing one. For this reason, we provide the code of the simplest driver in the library, CD_METAFILE. This code is well commented on, in order to make this process easy and to elliminate some doubts. See CDXX.H and CDXX.C.

Also see topic "Internal Architecture" in this user guide.

Intercepting Primitives

To fill data structures of library primitives during a cdPlay call you must implement a driver and activate it before calling cdPlay. Inside your driver primitives you can fill your data structure with the information interpreted by the cdPlay function.

Error Handling

For user feedback purposes you may test the pointer returned by cdCreateCanvas only when activating the drivers that have file access like PS, CGM, etc. For other errors, tests are necessary only for debugging purposes. Never activate a null canvas or call a CD library function without an active canvas (except for cdCreateCanvas, cdKillCanvas, cdActivate, cdActiveCanvas, cdEncodeColor and cdDecodeColor).

For a better parameter check, the library is also available with debug information, since all functions have ASSERT directives.

Global Names

The library has some structures and enumerations that may conflict with the application's code.
Structures and typedefs: cdContex and cdCanvas.
See the cd.h header file for enumerations.

IUP Compatibility

The IupCanvas element of the IUP interface toolkit can be used as a visualization surface for a CD canvas. There are two moments in which one must be careful when an application is using both libraries: when creating the CD canvas, and when changing the size of the IUP canvas.

Creating the CD Canvas

The creation of the CD canvas must be made always after the IupCanvas element has been mapped in the system's native control. This happens when the application calls function IupShow or when the function IupMap is explicitally called.

Since a call to IupShow generates a call to the ACTION callback of the IUP canvas, we have a peculiar situation. The CD canvas cannot be created before IupShow, but if it is created after it one cannot draw on the first time the redrawing callback of the IUP canvas is called.

We can address this problem in several ways:

  • We can force the mapping prior to IupShow by calling the IupMap function before creating the CD canvas.
  • We can create the CD canvas after IupShow, but associating the canvas' redrawing callback also after IupShow and forcing a call to this function.
  • We can create the CD canvas during the redrawing callback or during the size change callback, which is also called during a IupShow.
  • We can create the canvas during the MAP_CB callback, which is called after the IupCanvas element has been mapped in the native control.

Any of the above solutions works perfectly. The most elegant solution seems to be the one that uses the MAP_CB callback.

Creating the CD canvas also requires some parameters to be passed to the Native Window driver. These parameters are obtained from the IUP canvas by means of the CONID attribute. Therefore, the canvas creation is:

myCdCanvas = cdCreateCanvas(CD_NATIVEWINDOW, IupGetAttribute(myIupCanvas, "CONID"));
IupSetAttribute(myIupCanvas, "_CD_CANVAS", myCdCanvas);

The CD_IUP driver can still be used, but it must be linked with the cdiup library.

Resizing the IUP Canvas

If the application always activates the canvas before drawing, even if it is already active, then it is not necessary to worry about this situation. If this is not so, then the CD canvas mut be activated in the IUP canvas resize callback.

Comparing CD with Other Graphic Toolkits

There are other graphic toolkits, with some portability among operational systems, available on the Internet. Among them we can highlight:

  • VOGL - A Very Ordinary GL-Like Library. It is very similar to the CD library, but it has no longer been updated since 1995. It has several drivers, 2D and 3D routines, and illumination.
  • SRGP - Based on Foley's book, the code has not been found. It is aimed only at display.
  • GGI - 2D graphic library aimed only at display.
  • GKS - Very complete 2D and 3D graphic library, but with limited image resources. It is an ISO standard, and it implementations are usually commercial. Tecgraf has an implementation of GKS which is no longer used, being replaced by CD.
  • Mesa - 3D graphic library with support to the OpenGL standard. Implemented in C. Aimed only at display, with attribute functions for illumination and shading features.
  • OpenGL - 3D graphic library with some 2D support. Aimed only at display. A window CD canvas can coexist with an OpenGL canvas at the same time. Note: When Double Buffer is used, do not forget to swap buffer before redrawing with the CD library.
  • GD - Library only for drawing on images, saves PNG files. Implemented in C.
  • GDK - Used by the GTK user interface toolkit. Implemented in C. Aimed only at display, and contains several functions for managing windows, keyboard and mouse.
  • There are several other user interface libraries containing drawing functions. Most of them are implemented in C++ and are aimed only at display.

We can see that the concept of abstract drawing surfaces was little used in these libraries. Therefore they are aimed only at display, and user interface routines were also included. Others add 3D drawing routines, as well as scene illumination routines. All this unnecessarily increases their complexity and does not make them more complete as 2D graphic libraries.

As to performance, CD is as good as any other, in some cases having a better performance.

Thus, the CD library offers unique features and quality as a portable 2D graphic library.