drawing with Quartz

Rainer.Buerck's icon

On 16 February I posted the topic "porting QuickDraw code" to the forum, asking how I could replace my QuickDraw routines by Quartz routines.

Now I want to post a simple example to the forum, which may seem trivial to many or most of you. It is a very simple object which draws into a window, using Quartz. I actually used the example from the "Quartz 2D Programming Guide" (which you can find at http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/chapter_3_section_2.html#//apple_ref/doc/uid/TP30001066-CH203-CJBDCHAC , on this page move to " Windows Graphics Context: QuickDraw") and applied it to a window of a Max external.

The only thing this object does is create a window which you can open and close by sending a bang to the input, and do the drawing into this window provided by the example I refer to.

The struct of the "test" object includes only a t_wind pointer (t_wind *m_myWindow) and a flag to indicate whether the window is open or not (Boolean myWindowIsOpen).

When the object is created, by the *test_new (...) function, the function "CreateMyWindow" is called to create the window, using "wind_new (...)". The flag "x->myWindowIsOpen" is set to false (since the window hasn't been opened yet at the time it was created).

When a bang is sent to the inlet, either the funcion "OpenMyWindow" or the function "CloseMyWindow" is called, depending on whether it is currently open or not.

When the function "OpenMyWindow" is called, the window is opened, using wind_vis (x->myWindow). The flag "x->myWindowIsOpen" is set to true, since the window is open now. After this, the function "DrawInMyWindow" is called to do the drawing, using Quartz functions.

To do this, a window grahics context must be created. To create this context, a WindowRef is required. This WindowRef is obtained from the t_wind pointer "x->m_myWindow" by calling the function "wind_syswind" (thanks Joshua for the tip). The function "SetPortWindowPort" sets the window port. The function "QDBeginCGContext" creates the graphics context required for the drawing. After this, the actual drawing is done, using several Quartz functions. Then the function " QDEndCGContext" is used to signal the end of Quartz 2D drawing calls and to restore the window port.

Here is the code of my simle example:

#include
#include "ext.h"

#define MAXSIZE 256

typedef struct _test
{
    struct object m_ob;

    t_wind *m_myWindow;

    Boolean myWindowIsOpen;

} t_test;

void *test_class;

void test_bang(t_test *x);
void *test_new(t_symbol *s, short ac, t_atom *av);

void CreateMyWindow (t_test *x);
void OpenMyWindow (t_test *x);
void DrawInMyWindow (t_test *x);
void CloseMyWindow (t_test *x);

int main()
{
    setup((t_messlist **)&test_class, (method)test_new,0L, (short)sizeof(t_test), 0L, A_GIMME, 0);
    addbang((method)test_bang);

    return (0);
}

void *test_new(t_symbol *s, short ac, t_atom *av)
{
    t_test *x;

    x = (t_test *)newobject(test_class);

    CreateMyWindow (x);

    return x;
}

void test_bang(t_test *x)
{
    if ( x->myWindowIsOpen == false )
    {

        OpenMyWindow (x);
    }
    else
    {
        CloseMyWindow(x);
    }

}

void CreateMyWindow (t_test *x)
{
    x->m_myWindow = wind_new ( x, 100, 100, 600, 600, 0);

    x->myWindowIsOpen = false;
}

void OpenMyWindow (t_test *x)
{
    x->myWindowIsOpen = true;
    wind_vis (x->m_myWindow);
    DrawInMyWindow (x);
}

void DrawInMyWindow (t_test *x)
{
    CGContextRef myContext;
    WindowRef myWindowRef;

    myWindowRef = wind_syswind (x->m_myWindow);

    SetPortWindowPort (myWindowRef);

    QDBeginCGContext (GetWindowPort (myWindowRef), &myContext);

    CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);
    CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100));
    CGContextSetRGBFillColor (myContext, 0, 0, 1, .5);
    CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200));

    CGContextFlush(myContext);
    QDEndCGContext (GetWindowPort (myWindowRef), &myContext);

}

void CloseMyWindow (t_test *x)
{
    x->myWindowIsOpen = false;
    wind_invis (x->m_myWindow);
}

grimepoch's icon

wow, that worked REALLY easy! Thanks for providing this sample code, cannot believe how nice it runs.

I do have a simple question. Is there any way that I can get the window that comes up to exist in the parent? Or, because I am using quartz, am I stuck using it as a separate window?

In any case, thanks for sharing!!