Chapter 4. Implementing a New Application

This chapter details the minimal steps that are required to develop an application using Heidi. It outlines the construction of a renderer stack, its configuration for drawing, and the commands issued for drawing purposes.


    Each Heidi device supplies the HD_Device entry point. Likewise, each Heidi renderer supplies the HD_Renderer entry point. These functions return a Heidi device or renderer object, respectively. These are subsequently used in driver configuration and drawing. Construction of the renderer stack is shown in the following example.

HT_Create_Device device_generator = (HT_Create_Device) HD_Load_Dynamic_Routine 
                         ("gdi10.hdi", "HD_Device");

HD_Assert (device_generator != null); // make sure we find the 10.hdi.hdi

HT_Create_Renderer renderer_generator = (HT_Create_Renderer) HD_Load_Dynamic_Routine 
                                        ("szb10.hdi", "HD_Renderer");

HD_Assert (renderer_generator != null); // make sure we find the szb10.hdi

HT_Device m_device = (*device_generator)(); // create the device. 

// use the device as the sink of the renderer szb10.hdi 
HT_Renderer m_renderer = (*renderer_generator) (m_device); 

     Note: The renderer_generator function takes a renderer: this is the sink of the renderer in question. In other words, the stack must be constructed from the device up.

    Configuring the Renderer Stack
    The next step in preparing your application for using Heidi is to configure the renderers in your renderer stack. This involves setting the various renderer options used to facilitate the renderer’s interaction with your program, the operating system, and the hardware. For instance, you need to indicate to the GDI driver which window handle and device context to use in its drawing operations. Similarly, the software Z-buffer renderer needs to know which Z-buffer depth to use. There is a set of options that all renderers inherit. Renderers may also extend this set with custom options.

    Here is an example of configuring the renderer stack from the file heidi_glue.cpp, in the sample SimpleNoMFC, located under the heididk\samples directory. The local variable window holds the application window handle.

// set window id
m_device.set_configure ("Window ID", HT_Option_Value((long)window));
//.get the window dc from the system and set it to the device contex id.
m_device.set_configure ("Context ID", HT_Option_Value((long) GetDC (window)));
// typically the window origin is at 0,0
m_device.set_configure ("Window Origin", HT_Option_Value(0, 0)); 

RECT client;
int rx,ry;
// find the window.size
GetClientRect (window, &client);
rx = client.right - client.left +1;
ry = client.bottom - client.top +1;
// set the window size
m_device.set_configure ("Window Size", HT_Option_Value(rx, ry));

// create a palette containing a color cube
stack       HT_Color_Cube        cube;
stack       HT_Palette           pal;
// typically Win95 and NT reserves 20 system colors so we usually use
// 216 colors as the Heidi color cube
cube.set_resolution (HT_Int_RGB (6, 6, 6));

// are we on an 8-bit device?
int has_palette = GetDeviceCaps(GetDC(window), RASTERCAPS) & RC_PALETTE;
if (has_palette) {
    pal = m_device.physical ("Palette").as_palette (0);
    cube.set_base_index (pal.first_available_block (cube.total()));
    pal.install (cube);

    m_device.set_configure ("Palette", HT_Option_Value (pal));
    m_device.set_configure ("Color System", HT_Option_Value 
        (HT_Color_System::Mapped_RGB));

}
else
    m_device.set_configure ("Color System", HT_Option_Value 
        (HT_Color_System::Direct_RGB));


m_device.establish ();


// get the z buffer going
m_render = (*mx_render) (m_device);
HD_Assert (m_render != null);

m_render.establish ();
stack        HT_Rendition        rend(m_render);
stack        HT_DC_Point         points[3];
m_device.begin_picture();
    m_render.begin_picture();
        m_render.clear_z_buffer (rend);
        rend.set_background_color(HT_RGB32 (0x23f, 0x3f, 0x0F));
        m_render.clear_drawing_buffer (rend);
        rend.set_color (HT_RGB32(0X4F, 0XaF, 0XFF));
        points[0] = HT_DC_Point (300.0f, 100.0f, 0.0f);
        points[1] = HT_DC_Point (700.0f, 100.0f, 0.0f);
        for (int i = 0; i < 8; i++) {
            points[0].y +=(i+50);
            points[1].y +=(i+50);
            m_render.draw_2d_polyline (rend,2, points);
        }
        m_render.update();
    m_render.end_picture();
    m_device.update();
m_device.end_picture();

    Application Writing Tips
    The application writer cannot issue the establish() command inside the drawing loop. You must also refrain from issuing the set_configure() command inside the drawing loop as it does not produce any results without issuing an establish() command.

    Another tip is to reuse the rendition when possible. Besides avoiding context switching, this also prevents unnecessary memory allocation.