Search code examples
c++macosquartz-graphicscairo

Simple Cairo/Quartz C++ example


I need to create and run a simple interactive C++ Cairo (graphics) app on MacOS, which presumably means using the Quartz backend.

I feel really silly asking this, but I cannot seem to locate a simple example on the Web. Everything uses Cocoa (which is ObjectiveC) or Swift.

Here's what I have so far, and it links properly but does nothing... but it's because I'm missing some stuff I'm sure:

#include <cairo/cairo-quartz.h>
#include <cairo/cairo.h>

int main()
{
    cairo_surface_t* surface = cairo_quartz_surface_create (
              CAIRO_FORMAT_RGB24
            , 640
            , 480
            );

    cairo_t* cr = cairo_create(surface);

    // What next?  How do I get the window to show up?
    // What do I use for my event loop?
}

Command to build:

clang++ $(pkg-config --cflags --libs cairo) main.cpp

(Obviously this assumes you have correctly installed Cairo)


Solution

  • Cairo doesn't know about windows or event loops. It just knows how to draw into “surfaces”, where a surface is somewhat circularly defined as “something Cairo can draw into”. It can create various system-independent surfaces, like in-memory bitmaps, PDFs, and PostScript files, and it can wrap a surface around some system-dependent drawing targets, like a Quartz CGContext, a Windows HDC, or an X11 Drawable.

    If you want to create an interactive application, you need to use some other system to create an on-screen drawing target and to respond to user input. Then you can wrap the system's on-screen drawing target in a cairo_surface_t and use Cairo to draw.

    So, you can use the native macOS Cocoa frameworks for interaction, and use cairo_quartz_surface_create_for_cg_context to wrap a cairo_surface_t around a macOS-native CGContext. Cocoa applications tend to provide the best user experience on macOS.

    Or you can use the cross-platform Qt system for interaction, and use cairo_qt_surface_create to wrap a cairo_surface_t around a QPainter. Qt is a C++ system, so this might be your easiest solution.

    Or you can use SDL with the cairosdl helpers.

    Or, for any framework that provides access to simple RGB bitmaps, you can use cairo_image_surface_create_for_data to wrap a cairo_surface_t around the bitmap.

    Or, for any framework that can import a simple RGB bitmap, you can use cairo_image_surface_create to create a bitmap, and then hand it off to the system using the system's API.