AbiWord Graphics Layer

Tomas Frydrych <tomasfrydrych@yahoo.co.uk>

March 1, 2004

Overview

Most of graphic operations are done in AbiWord through a portable graphics layer encapsulated by GR_Graphics. In itself, GR_Graphics is an abstract class providing only limited functionality; instead, a derrived class or classes, such as GR_Win32Graphics, is defined on each platform which implements the various virtual methods of GR_Graphics for both output to screen context and a printer context -- on some platforms (e.g., win32) both contexts are handled by a single class, on other platforms two different classes are need (e.g., on Unix GR_UnixGraphics for screen and PS_Graphics for printing).

In addition to the main derrived classes on each platform, an unspecified number of specialised graphics classes may exist on any platform. These classes can implement functionality that goes beyond that to the platform base class, for example provide advanced shaping capabilities through a third-party library. Such additional classes can even be implemented as plugins. All of these additional classes must be derived from the the platform basic class, and must provide the same number of constructors as the basic class with signatures identical to the basic class constructor signatures (this allows for transparent replacement of the basic platform class with one of the additional classes).

The allocation of instances of graphic classes is done through a graphics factory implemented in GR_GraphicsFactory which is made accessible to the outside world through XAP_App. The process looks as follows:

At start-up XAP_FEApp constructor registers all known graphic classes with the factory

Any graphics classes contained in plugins register themselves with the factory as they load.

On request XAP_App allocates transparently an instance of a graphics class.

Class Registration

Each built-in graphics class has to be registered with the graphics factory by call to GR_GraphicsFactory::registerClass(UT_uint32 id, GR_Allocator a, GR_Decsriptor d), where id defines numerical id assigned to the class in gr_graphics.h, GR_Allocator is a static function used to allocate instances of that class and GR_Descriptor is a static function providing human readeable description of the class.

Each plugin class too has to register with the factory. It can either use the registerClass() function if it has a fixed id assigned which is found in gr_graphics.h, or it can use registerPluginClass(GR_Allocator, GR_Descriptor) which will allocate to it id dynamically. (There are advantages to plugin classes having a fixed id assigned to them, such making it possible to store such ids in preference files.)

In addition to each class being registered as described above, the default screen and printer classes have to be registered with the ids GRID_DEFAULT and GRID_DEFAULT_PRINT respectively. The XAP_FEApp constructor does the initial registration, but different classes can be registered under these ids later (for example a plugin class might install itself as the default handler).

Class Instance Allocation

Instances of graphics classes are allocated through newGraphics() functions of XAP_App. Virtually all allocations should be done through XAP_App::newGraphics(GR_AllocInfo & ai), to which the caller needs to supply an instance of GR_AllocInfo derrived class that is then passed by the factory to the class allocator GR_Allocator.

The derrived class GR_FEAllocInfo is platform specific (not graphics specific!) and is capable of holding information needed by any of the graphics class constructors used on that platform. GR_AllocInfo also provides two virtual functions: getType() that allows the allocators to check that the actual instance it was passed is what it expects, and isPrinterGraphics() which is used by XAP_App to decide whether printer or screen graphics should be allocated by call to newGraphics().

The call to XAP_App::newGraphics(GR_AllocInfo &ai) will allocate a new instance of a graphics class registered with GRID_DEFAULT if screen graphics is needed or GRID_DEFAULT_PRINTER if printer graphics is needed.

In addition to this function, there is also XAP_App::newGraphics(UT_uint id, GR_AllocInfo ) which will allocate an instance of the class registered with the given id. This function should only be used when there is a good reason why a specific class must be allocated; in the present AbiWord code, the only place it is needed is for allocation of UnixNull_Graphics.

Notes on Shaping

TO BE WRITTEN.