#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x500
#include <windows.h>

#include <cairo-win32.h>
#include <cairo-pdf.h>

static const int fontsize = 20;
static const wchar_t *t1name = L"NimbusRomNo9L", *ttname = L"Arial";
static cairo_scaled_font_t *t1font, *ttfont;

static const int yoffset = 25;
static const char teststr[] = "This is just a test. Foo Bar Baz. Hello World.";

static cairo_scaled_font_t* initFont(const wchar_t* name)
{
    LOGFONTW lf;
    memset(&lf, 0, sizeof LOGFONTW);
    wcscpy(lf.lfFaceName, name);
	cairo_font_face_t* font = cairo_win32_font_face_create_for_logfontw(&lf);

    cairo_matrix_t sm;
    cairo_matrix_init_scale(&sm, fontsize, fontsize);
    cairo_matrix_t dm;
    cairo_matrix_init_identity(&dm);
    cairo_font_options_t* options = cairo_font_options_create();
    cairo_scaled_font_t* ret = cairo_scaled_font_create(font, &sm, &dm, options);

    cairo_font_face_destroy(font);
    cairo_font_options_destroy(options);
    return ret;
}

template<int size>
static void showGlyphs(cairo_t* c, HDC dc, cairo_scaled_font_t* font, const char (&str)[size], double y)
{
    // get the glyph indices
    WORD glyphs[size-1];
    cairo_win32_scaled_font_select_font(font, dc);
    GetGlyphIndicesA(dc, str, size-1, glyphs, 0);
    // position and convert to cairo_glyph_t
    cairo_glyph_t cglyphs[size-1];
    double x = 0;
    for (int i=0; i<size-1; ++i) {
        cglyphs[i].index = glyphs[i];
        cglyphs[i].x = x;
        cglyphs[i].y = y;
        cairo_text_extents_t extents;
        cairo_scaled_font_glyph_extents(font, cglyphs+i, 1, &extents);
        x += extents.x_advance;
    }
    // show glyphs
	cairo_show_glyphs(c, cglyphs, size-1);
}

static void draw(cairo_t* c, HDC dc)
{
    // Type 1
    cairo_set_scaled_font(c, t1font);
    // cairo_show_text
    cairo_move_to(c, 0, yoffset);
    cairo_show_text(c, teststr);
    // cairo_show_glyphs
    showGlyphs(c, dc, t1font, teststr, 2*yoffset);

    // TrueType
    cairo_set_scaled_font(c, ttfont);
    // cairo_show_text
    cairo_move_to(c, 0, 3*yoffset);
    cairo_show_text(c, teststr);
    // cairo_show_glyphs
    showGlyphs(c, dc, ttfont, teststr, 4*yoffset);
}

LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)       
    {
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC dc = BeginPaint(hwnd, &ps);
            cairo_surface_t* surface = cairo_win32_surface_create(dc);
            cairo_t* cairo = cairo_create(surface);
            cairo_surface_destroy(surface);
            draw(cairo, dc);
            cairo_destroy(cairo);
            EndPaint(hwnd, &ps);
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:           
        return DefWindowProc (hwnd, msg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hi, HINSTANCE, LPSTR lpszArgument, int iCmdShow)
{
    t1font = initFont(t1name);
    ttfont = initFont(ttname);

    WNDCLASSA wnd = { 0, WinProc, 0, 0, hi, NULL, LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_BACKGROUND+1), NULL, "MyClass" };
    RegisterClassA(&wnd);
    HWND hwnd = CreateWindowA(
            "MyClass", "CairoTest", WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, hi, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    // PDF output
	cairo_surface_t* pdfs = cairo_pdf_surface_create("out.pdf", 8*72, 2*72);
    cairo_t* pdf = cairo_create(pdfs);
    cairo_surface_destroy(pdfs);
    draw(pdf, GetDC(hwnd));
	cairo_destroy(pdf);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
        DispatchMessage(&msg);

    return 0;
}
