Copyright (c) Hyperion Entertainment and contributors.

BOOPSI Images

From AmigaOS Documentation Wiki
Jump to navigation Jump to search

Introduction

BOOPSI's imageclass is one of the standard classes built into Intuition. As its name implies, it is a class of Intuition Images. These BOOPSI images can be used in place of traditional Image structure (as they contain an Intuition Image structure), but they are much more powerful. By using BOOPSI methods, an application or Intuition can tell an imageclass object to render itself. Because it renders itself (rather than Intuition rendering it), the imageclass object is free to render whatever it wants (well, within reason). For example, a BOOPSI image object can render itself according to the current display resolution, or to scale itself to any size an application requests.

BOOPSI Image Methods

Imageclass defines several methods of its own which subclasses of imageclass either have to implement or pass on to their superclass. The method IDs for imageclass are defined in <intuition/imageclass.h>. Each method requires some parameters.

Method Description
IM_DRAW Draw image with state.
IM_DRAWFRAME Draw image within frame limits.
IM_ERASE Erase image with state.
IM_ERASEFRAME Erase image within frame.
IM_HITFRAME Determine if image was hit within frame.
IM_HITTEST Determine if image was hit.

The following methods are described at the imageclass level although it's up to the subclasses to actually implement them. If a class does not implement these methods it should either return zero, indicating that this class does not support the method, or defer processing on to its superclass.

Method Description
IM_FRAMEBOX Get recommended frame around some box.
IM_EXTENT Inquire about rendering extent.
IM_EXTENTFRAME Inquire about rendering extent with dimensions.

The formats of each of these BOOPSI messages all differ. The MethodID is the only parameter common to each method.

IM_DRAW

The IM_DRAW method is used to tell the image to render itself. The Intuition function DrawImageState() uses this method. IM_DRAW receives the following parameters:

struct impDraw
{
    uint32 MethodID;
    struct RastPort *imp_RPort;
    struct
    {
        int16 X;
        int16 Y;
    } imp_Offset;
 
    uint32 imp_State;
    struct DrawInfo *imp_DrInfo;
};

The imp_State field contains the visual state to render the image. The visual states (defined in <intuition/imageclass.h>) are:

IDS_NORMAL idle state
IDS_SELECTED for selected gadgets.
IDS_DISABLED for disabled gadgets.
IDS_BUSY for future functionality
IDS_INDETERMINATE for future functionality
IDS_INACTIVENORMAL normal, in inactive window border.
IDS_INACTIVESELECTED selected, in inactive border.
IDS_INACTIVEDISABLED disabled, in inactive border.

When setting the pens to render an image, use the values from the imp_DrInfo->dri_Pens pen array (Note that it is possible that imp_DrInfo will be NULL). The possible pen values are defined in <intuition/screens.h>.

The following code fragment shows how to use the shadow color for rendering.

uint16 *pens = (imp->imp_DrInfo) ? imp->imp_DrInfo->dri_Pens : NULL;
 
if (pens)
{
    IIntuition->SetAPen (imp->imp_RPort, pens[SHADOWPEN]);
}

IM_DRAWFRAME

The IM_DRAWFRAME method instructs the image to render itself within the confines of the given rectangle. It receives the following parameters:

struct impDraw
{
    uint32 MethodID;
    struct RastPort *imp_RPort;
    struct
    {
        int16 X;
        int16 Y;
    } imp_Offset;
 
    uint32 imp_State;
    struct DrawInfo *imp_DrInfo;
 
    struct
    {
        int16 Width;
        int16 Height;
    } imp_Dimensions;
};

The Width and Height fields provide the object's rectangular bounds. How the image object deals with the frame is implementation specific. Typically, a scaleable image will scale itself as best it can to fit into the rectangle. The mytextlabelclass.c example does not actually implement this method, instead mytextlabelclass treats IM_DRAWFRAME like the IM_DRAW method.

In general, applications that use this method to draw an object should use the IM_ERASEFRAME method (see below) to erase it. This will ensure that the image was erased at the proper scale.

IM_ERASE

The IM_ERASE method tells an image to erase itself. The Intuition function EraseImage() uses this method. IM_ERASE receives the following parameters:

struct impErase
{
    uint32 MethodID;
    struct RastPort *imp_RPort;
    struct
    {
        int16 X;
        int16 Y;
    } imp_Offset;
};

The mytextlabelclass example doesn't know anything about this method, so it blindly passes this message on to the superclass. The superclass, imageclass, will call the graphics.library function EraseRect() using the dimensions found in the imageclass object's Image structure.

IM_ERASEFRAME

The IM_ERASEFRAME method instructs an image confined to a given rectangle to erase itself. Normally this method is used to erase an image drawn using the IM_DRAWFRAME method. This method expects the following parameters:

struct impEraseFrame
{
    uint32 MethodID;
    struct RastPort *imp_RPort;
    struct
    {
        int16 X;
        int16 Y;
    } imp_Offset;
 
    /* these parameters only valid for IM_ERASEFRAME */
    struct
    {
        int16 Width;
        int16 Height;
    } imp_Dimensions;
};

The mytextlabelclass example blindly passes this method on to its superclass. The superclass treats IM_ERASEFRAME just like IM_ERASE.

IM_HITFRAME

The IM_HITFRAME method is used to determine if a point is within an image that is contained within (or scaled to) the given rectangle. This method is intended to test images that were rendered using IM_DRAWFRAME. This method receives the following parameters:

struct impHitFrame
{
    uint32 MethodID;
    struct
    {
        int16 X;
        int16 Y;
    } imp_Point;
 
    struct
    {
        int16 Width;
        int16 Height;
    } imp_Dimensions;
};

The mytextlabelclass example blindly passes this method on to its superclass. The superclass treat this meothd just like the IM_HITTEST method.

IM_HITTEST

IM_HITTEST returns true if a point is within the image. The Intuition function PointInImage() uses this method. IM_HITTEST requires the following parameters:

struct impHitTest
{
    uint16 MethodID;
    struct
    {
        int16 X;
        int16 Y;
    } imp_Point;
};

The mytextlabelclass example blindly passes this method on to its superclass. The superclass, imageclass, will return TRUE if the point is within the old Image structure box.

IM_FRAMEBOX

The IM_FRAMEBOX method returns size information for an image (usually some sort of frame image). The following parameters are associated with the IM_FRAMEBOX method.

struct impFrameBox
{
    uint32 MethodID;
    struct IBox *imp_ContentsBox;  /* Application supplied IBox for the result */
    struct IBox *imp_FrameBox;     /* Rectangle to frame */
    struct DrawInfo *imp_DrInfo;
    uint32 imp_FrameFlags;
};

This method is used to ask the image what size it would like to be, if it had to frame the rectangle in the imp_FrameBox field. This method normally applies only to image classes that put a frame around some object (like frameiclass). By passing the dimensions and position of a rectangle, the framing image determines the position and size it should be to properly "frame" the object bounded by the imp_FrameBox rectangle. IM_FRAMEBOX stores the result in the IBox structure pointed to by imp_ContentsBox. This method allows an application to use a framing image without having to worry about image specific details such as accounting for the thickness of the frame or centering the frame around the object.

The imp_FrameFlags field is a bit field used to specify certain options for the IM_FRAMEBOX method. Currently, there is only one defined for it, FRAMEF_SPECIFY. If this bit is set, IM_FRAMEBOX has to use the width and height supplied to it in the imp_FrameBox field (even if these are too small!) as the frame dimensions. It can only adjust its position, typically to center the object as best as possible.

This method is not supported by the mytextlabelclass example. It passes this message to its superclass which does not support this method either. When the message returns from the superclass, the return value will be zero, indicating to the application that this method is not supported.