Programming Guide: Canvases

# Programming Guide

## Canvases

Canvases are inherently platform-specific. OpenDoc canvas objects are basically wrappers for structures that differ across platforms. This section discusses how to use canvas objects regardless of the platform for which you are developing.

The class ODCanvas is OpenDoc's wrapper for a platform-specific (or graphics-system-specific) object that represents a drawing environment. A drawing canvas can refer to anything from a bit map or a structured display list to a stream of PostScript code. It represents the destination for drawing commands, the environment for constructing a rendered image; it has a coordinate system and may retain state information (such as pen color) that influences how drawing commands are interpreted.

A canvas object holds a reference to a system-specific object called a platform canvas, and that object is not deleted when the canvas is released. If you create a canvas, you must create the platform canvas separately, and you are responsible for deleting it when the canvas is deleted.

The platform canvas is a SOM class which you create using the ODFacet method CreatePlatformCanvas. An onscreen dynamic canvas is created for every facet for which the parent facet has an onscreen dynamic canvas.

### Platform Canvases

The platform canvas, ODPlatformCanvas, is a platform-independent SOM base class for other objects which wrap the platform-specific drawing context. The methods of ODPlatformCanvas provide generic information about the type of subclass. You can use these methods to determine how to downcast a pointer to an ODPlatformCanvas into the platform canvas object appropriate for that platform. For instance, on the Windows platform, once you have a pointer to an ODPlatformCanvas object you can use GetSystemType and GetPlatformCanvasType to determine whether to downcast to ODWin32StandardCanvas or to ODWin32WindowCanvas. You must downcast to call methods which allow access to the device context (DC), such as GetDC and ReleaseDC. You can also downcast to their parent class, ODWin32Canvas, since they all have exactly the same methods.

On each platform, the unique platform canvas subclasses expose the drawing context and other related information in a platform-specific manner.

- On the Windows platform, the ODWin32Canvas serves as the base class for ODWin32StandardCanvas and ODWin32WindowCanvas. These classes expose the Windows device context (DC) through the GetDC and ReleaseDC methods.

- On the OS/2 platform, the ODOS2Canvas serves as the base class for ODOS2StandardCanvas and ODOS2WindowCanvas. These classes expose the OS/2 presentation space (PS) through the methods GetPS, ReleasePS and SetPS.

- On the AIX platform, the ODAIXCanvas serves as the base class for ODAIXStandardCanvas and ODAIXWindowCanvas. These classes expose the X-Windows graphics context (GC), the Display, and the window or pixmap through the methods GetGC, GetDisplay, GetWindow and GetPixmap.

There are two types of platform canvases, standard and window. The difference between the two is simply whether the drawing context is associated with a window or not. A standard platform canvas is typically used when drawing offscreen and is initialized directly with a platform-specific drawing context. A window platform canvas is used when drawing onscreen and is initialized with a reference to the window associated with the drawing context. In other words, the drawing context is inferred by the window itself. A window platform canvas is created for you by CreateEmbeddedFacet of ODFacet when you specify kODNULL for the canvas parameter. There are very few instances when you will need to create a window platform canvas yourself.

You can create platform canvases several ways. One method is to use the CreateConcreteCanvas method of the ODPlatformCanvas class or one of the platform-specific base classes such as ODWin32Canvas on the Windows platform. When you use this method you must downcast the pointer of the new ODPlatformCanvas to one of its subclasses and call the appropriate initialization method. Use the InitPlatformCanvas method to initialize a standard platform canvas, while the InitPlatformWindowCanvas methods to initialize a window platform canvas. You can also create a standard platform canvas by using the ODFacet method CreatePlatformCanvas and passing a platform-specific drawing context.

### Canvas Features

Canvases can be dynamic or static, meaning that they are used for video display or printing display, respectively. Your part editor can determine whether it is drawing to a static or dynamic canvas and can adjust its procedures accordingly.

Canvases can be onscreen or offscreen. Your part editor can create special effects or improve performance by drawing a complex image to an offscreen cache and then quickly transferring the completed image to the screen. For added convenience, offscreen canvases maintain clipping and updating information that mirrors their onscreen equivalents.

Canvases are attached to individual facets. In Figure 27, for example, which shows the same document with the same facet hierarchy as in Figure 24, the document has two attached canvases:

- An offscreen canvas is attached to the movie part's facet.

- An onscreen canvas is attached to the root part's facet. (A canvas attached to the root facet of a window is also called a window canvas; every window has an onscreen dynamic window canvas.)

Figure 27. Facets and Canvases

View figure.

If a particular facet in a window's facet hierarchy has an attached canvas, all of its embedded facets (and their embedded facets, and so on) draw to that canvas. In Figure 27, for example, any drawing done to the text facet uses text canvas, draw facet uses draw canvas, and clock facet uses clock canvas.

OpenDoc creates an onscreen dynamic canvas for every facet for which the parent facet has an onscreen dynamic canvas. However, if a particular part needs an offscreen canvas, for itself or for an embedded part, it can attach a canvas to a facet anywhere within the hierarchy. Any drawing done to the movie facet in Figure 27, for example, is rendered on the offscreen canvas.

For each platform, a window canvas consists of a platform-specific window heirarchy that parallels the facet hierarchy. On the OS/2 platform, there is a Presentation Manager (PM) window for each facet in the window canvas. Similarly, on Windows and AIX, sibling windows are created for each facet in the window canvas.

Every canvas has an owner, a part that is responsible for transferring images drawn on its canvas to the parent of that canvas. In Figure 27, for example, the movie images drawn to the offscreen canvas must be transferred to the window canvas in order to be viewed onscreen. The owner decides when and how to transfer images from a canvas to its parent. The owner of the offscreen canvas in Figure 27 might be the movie part or the text part that contains the movie part.

### Adding and Removing Canvases

This section describes how to create and delete canvases for your parts. For specific information on using canvases for offscreen drawing, see "Offscreen Drawing". If you want to create a canvas and attach it to a facet, take these steps:

1. Create and initialize a drawing context for your platform. On the OS/2 platform, you would create and initialize a GPI presentation space and associate it with a memory DC. On the Windows platform, create and initialize a device context (DC). On the AIX platform, create and initialize a graphics context (GC). You will also need a pixmap (for offscreen) or Window ID (for onscreen) and a pointer to your display.

2. Create an ODPlatformCanvas object using the CreatePlatformCanvas method of ODFacet.

3. Create a canvas object, using the CreateCanvas method of ODFacet or ODWindowState. In calling the method, you assign the platform canvas to the new canvas, and you also define the canvas as static or dynamic and onscreen or offscreen. (These values cannot change for the lifetime of the canvas). You should not try to change an onscreen dynamic canvas because OpenDoc has already created one for every facet.

4. Designate your part as owner of the canvas by calling the SetOwner method of the canvas.

5. Assign the canvas to a facet. Because only the owner of a canvas can remove it from a facet, the timing of assigning the canvas is important:

   - If your part is a containing part assigning an offscreen canvas to one of its embedded parts, you should assign the canvas when you first create the embedded facet that is, when you first call the CreateEmbeddedFacet method of the embedded part's containing facet. Otherwise, the embedded part may assign a canvas to the facet, precluding you from doing so.

   - If your part is a containing part and one of its embedded parts has an existing facet with no assigned canvas, you can add one by calling the ChangeCanvas method of the embedded facet. When you do so, OpenDoc communicates the change to all embedded parts that use that facet, by calling their CanvasChanged methods.

   - Your part can add a canvas to any of its own display frames' facets at any time, as long as the facet does not already have an assigned canvas. It is probably best to attach the canvas as soon as the facet is created, by calling ChangeCanvas from within your part's FacetAdded method. If the containing part of your part has already attached a canvas to your new facet, you cannot assign a different canvas to it.

   - If your part absolutely needs to attach its own canvas to a facet that already has an assigned canvas, you can get around this restriction by creating a subframe of the facet's frame, creating a facet for that frame, and assigning the canvas to that facet.

To remove a canvas from a facet, take these steps:

1. Call the facet's ChangeCanvas method, passing it a null value for the canvas reference.

2. Delete the PS and memory DC that the platform canvas had referenced.

3. Delete the canvas object, by calling delete (in C++).

4. Delete the platform canvas object, by calling delete in C++.

[ Top | Previous | Next | Contents | Index | Documentation Homepage ]