[cairo] Win + Cario + SVG

Simon Flannery simon_flannery at yahoo.com.au
Sun Nov 19 17:24:55 PST 2006


Not wanting to "give-up", I have researched and plugged away to produce a simple SVG loader using Cario with librsvg.

For everyone here is a possible solution that I built. Enjoy.

#include <cairo-win32.h>
#include <librsvg\rsvg.h>
#include <librsvg\rsvg-cairo.h>

#define MY_TIMER 0x01

RsvgHandle*       g_my_svg = NULL;
RsvgDimensionData g_dimension = {0};

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void Paint(HDC hdc, long width, long height);

INT WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT iCmdShow)
{
   WNDCLASS window_class = {0};
   window_class.style         = CS_HREDRAW | CS_VREDRAW;
   window_class.lpfnWndProc   = WndProc;
   window_class.cbClsExtra    = 0;
   window_class.cbWndExtra    = 0;
   window_class.hInstance     = hInstance;
   window_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
   window_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
   window_class.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
   window_class.lpszMenuName  = NULL;
   window_class.lpszClassName = "my_svg";
   RegisterClass(&window_class);
   
/* Compute the window size needed for the desired client area. */
   RECT rect = {0, 0, 400, 400};
   AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE /* No menu. */);
   HWND hWnd = CreateWindow("my_svg", "Simple SVG Test - Esc to quit", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL);
   
   ShowWindow(hWnd, iCmdShow);
   UpdateWindow(hWnd);
/* Start a new timer that fires WM_TIMER events every 500 milliseconds. */
   SetTimer(hWnd, MY_TIMER, 500, (TIMERPROC) NULL);
   GError* pError = NULL;
/* Start the rsvg lib. */
   rsvg_init();
   g_my_svg = rsvg_handle_new_from_file("star.svg", &pError);
   rsvg_handle_get_dimensions (g_my_svg, &g_dimension);
/* Main message loop. */
   MSG message;
   while (GetMessage(&message, NULL, 0, 0) != 0)
   {
      TranslateMessage(&message);
      DispatchMessage(&message);
   }
   rsvg_handle_free(g_my_svg);
   rsvg_term();
   UnregisterClass("my_svg", hInstance);
   return (int) message.wParam;
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message)
   {
      case WM_TIMER:
         InvalidateRect(hWnd, NULL, 0);
         return 0;
         break;
      case WM_ERASEBKGND:
      /* Windows wants to redraw the window background everytime the window is resized.
         This prevents that to avoid flickering during resizing! */
         return 0;
         break;
      case WM_PAINT:
         {
         /* Get the width and height of the window. */
            RECT client;
            GetClientRect(hWnd, &client);
            PAINTSTRUCT ps;
            HDC dc = BeginPaint(hWnd, &ps);
         /* Create an offscreen buffer for painting. Althought not required,
            this stops the flickering! */
            HDC dcBuffer    = CreateCompatibleDC(dc);
            HBITMAP hBuffer = CreateCompatibleBitmap(dc, client.right, client.bottom);
         /* Select the new buffer and use it for painting. */
            SelectObject(dcBuffer, hBuffer); 
            Paint(dcBuffer, client.right, client.bottom);
         /* Now copy the buffer onto the actual window. */
            BitBlt(dc, 0, 0, client.right, client.bottom, dcBuffer, 0, 0, SRCCOPY);
         /* Clean up. */
            DeleteDC(dcBuffer); 
            DeleteObject(hBuffer);
            EndPaint(hWnd, &ps);
            return 0;
         }
         break;
                
      case WM_DESTROY:
      /* The user has closed the window. Stop the timer and quit the application. */
         KillTimer(hWnd, MY_TIMER); 
         PostQuitMessage(0);
         return 0;
         break;
      default:
         break;
   }
/* All other events should be handled by the default event handler. */
   return DefWindowProc (hWnd, message, wParam, lParam);
}

void Paint(HDC hdc, long width, long height)
{
   cairo_surface_t* surface = cairo_win32_surface_create(hdc);
   cairo_t* cr = cairo_create(surface);
   cairo_scale(cr, (double) width / (double) g_dimension.width, (double) height / (double) g_dimension.height);
/* Paint the background context colort white. */
   cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f);
   cairo_paint(cr);
/* Apply our decal. */
   rsvg_handle_render_cairo(g_my_svg, cr);
  
/* Force pipeline out. */
   cairo_surface_flush(surface);
/* Clean up. */
   cairo_destroy(cr);
   cairo_surface_destroy(surface);
   return;
}

Send instant messages to your online friends http://au.messenger.yahoo.com 


More information about the cairo mailing list