[cairo-commit] [cairo-www] src/SDL src/SDL.mdwn
Chris Wilson
ickle at freedesktop.org
Thu Oct 30 10:14:18 PDT 2008
src/SDL.mdwn | 9 +-
src/SDL/Makefile | 16 +++
src/SDL/SDLClock.c | 211 -----------------------------------------------
src/SDL/SDLClockMakefile | 56 ------------
src/SDL/sdl-clock.c | 174 ++++++++++++++++++++++++++++++++++++++
5 files changed, 196 insertions(+), 270 deletions(-)
New commits:
commit c41b5d2f85b3ae6f46e7c17d18a5b54d3e511d30
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Oct 30 17:13:41 2008 +0000
Update SDL tutorial.
diff --git a/src/SDL.mdwn b/src/SDL.mdwn
index d31e5f9..0b1a581 100644
--- a/src/SDL.mdwn
+++ b/src/SDL.mdwn
@@ -6,9 +6,12 @@ development kit from [http://www.libsdl.org](http://www.libsdl.org/).
For Visual Studio unzip it and add the SDL\include directory, SDL.lib
and SDLMain.lib to your project, just like you did with cairo.
-Drawing with cairo to an SDL Surface can be tricky. For demonstration
-purposes, see the SDL/cairo version of the cairo clock
-[[source_code|SDLClock.c]]. A [[makefile|SDLClockMakefile]] for this
+Drawing with cairo to an SDL Surface is quite simple, as all you need to
+do is create a cairo_surface_t from the SDL_Surface using
+cairo_sdl_surface_create(). (This surface is a full cairo surface and so
+may be used as a source for other (non-SDL) contexts, etc.)
+For demonstration purposes, see the SDL/cairo version of the cairo clock
+[[source_code|sdl-clock.c]]. A [[makefile|Makefile]] for this
code is also available.
Visual Studio tip:
diff --git a/src/SDL/Makefile b/src/SDL/Makefile
new file mode 100644
index 0000000..d56d310
--- /dev/null
+++ b/src/SDL/Makefile
@@ -0,0 +1,16 @@
+CFLAGS = -O3 -g -Wall $(shell pkg-config cairo-sdl --cflags)
+LIBS = $(shell pkg-config cairo-sdl --libs)
+
+SOURCES = \
+ sdl-clock.c \
+ $(NULL)
+
+OBJS = $(SOURCES:.c=.o)
+
+default: sdl-clock
+
+sdl-clock: $(OBJS)
+ $(CC) $(OBJS) $(LIBS) -o $@
+
+clean:
+ rm -f core $(OBJS) sdl-clock *~
diff --git a/src/SDL/SDLClock.c b/src/SDL/SDLClock.c
deleted file mode 100644
index cfcb0e7..0000000
--- a/src/SDL/SDLClock.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Cairo SDL clock. Shows how to use Cairo with SDL.
- * Made by Writser Cleveringa, based upon code from Eric Windisch.
- * Minor code clean up by Chris Nystrom (5/21/06)
- */
-
-#include <stdlib.h>
-#include <time.h>
-#include <math.h>
-#include <cairo/cairo.h>
-#include "SDL.h"
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-/* Pixel data for our clock */
-unsigned char *clockData = NULL;
-
-/* Surface constructed from pixel data */
-SDL_Surface *clockSurface = NULL;
-
-/* Clear all stuff on exit */
-void onExit()
-{
- free(clockData);
- SDL_FreeSurface(clockSurface);
- SDL_Quit();
-}
-
-/* Draws a clock on a normalized Cairo context */
-void drawClock(cairo_t * cr)
-{
- /* store the current time */
- time_t rawtime;
- time(&rawtime);
- struct tm *timeinfo;
-
- /* In newer versions of Visual Studio localtime(..) is deprecated. */
- /* Use localtime_s instead. See MSDN. */
- timeinfo = localtime(&rawtime);
-
- /* compute the angles for the indicators of our clock */
- double minutes = timeinfo->tm_min * M_PI / 30;
- double hours = timeinfo->tm_hour * M_PI / 6;
- double seconds = timeinfo->tm_sec * M_PI / 30;
-
- /* draw the entire context white. */
- cairo_set_source_rgba(cr, 1, 1, 1, 1);
- cairo_paint(cr);
-
- /* who doesn't want all those nice line settings :) */
- cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
- cairo_set_line_width(cr, 0.1);
-
- /* translate to the center of the rendering context and draw a black */
- /* clock outline */
- cairo_set_source_rgba(cr, 0, 0, 0, 1);
- cairo_translate(cr, 0.5, 0.5);
- cairo_arc(cr, 0, 0, 0.4, 0, M_PI * 2);
- cairo_stroke(cr);
-
- /* draw a white dot on the current second. */
- cairo_set_source_rgba(cr, 1, 1, 1, 0.6);
- cairo_arc(cr, sin(seconds) * 0.4, -cos(seconds) * 0.4, 0.05, 0,
- M_PI * 2);
- cairo_fill(cr);
-
- /* draw the minutes indicator */
- cairo_set_source_rgba(cr, 0.2, 0.2, 1, 0.6);
- cairo_move_to(cr, 0, 0);
- cairo_line_to(cr, sin(minutes) * 0.4, -cos(minutes) * 0.4);
- cairo_stroke(cr);
-
- /* draw the hours indicator */
- cairo_move_to(cr, 0, 0);
- cairo_line_to(cr, sin(hours) * 0.2, -cos(hours) * 0.2);
- cairo_stroke(cr);
-}
-
-/* Shows how to draw with Cairo on SDL surfaces */
-void drawScreen(SDL_Surface * screen)
-{
- /* The drawing will exactly fit in the screen. */
- int width = screen->w;
- int height = screen->h;
-
- /* The number of bytes used for every scanline. */
- int stride = width * 4;
-
- /* Free old pixel data and allocate new space */
- free(clockData);
- clockData = (unsigned char *) calloc(stride * height, 1);
-
- /* Create a cairo surface for our allocated image. */
- /* We use the CAIRO_FORMAT_ARGB32 to support transparancy. */
- cairo_surface_t *cairo_surface =
- cairo_image_surface_create_for_data(clockData,
- CAIRO_FORMAT_ARGB32, width,
- height, stride);
-
- /* Create a cairo drawing context, normalize it and draw a clock. */
- /* Delete the context afterwards. */
- cairo_t *cr = cairo_create(cairo_surface);
- cairo_scale(cr, width, height);
- drawClock(cr);
- cairo_destroy(cr);
-
- /* We stored our image in ARGB32 format. We have to create a mask */
- /* for this format to tell SDL about our data layout. */
- Uint32 rmask = 0x00ff0000;
- Uint32 gmask = 0x0000ff00;
- Uint32 bmask = 0x000000ff;
- Uint32 amask = 0xff000000;
-
- /* Free old surface and create a new one from our pixel data. */
- SDL_FreeSurface(clockSurface);
- clockSurface =
- SDL_CreateRGBSurfaceFrom((void *) clockData, width, height, 32,
- stride, rmask, gmask, bmask, amask);
-
- /* Blit the clock to the screen and refresh */
- SDL_BlitSurface(clockSurface, NULL, screen, NULL);
- SDL_UpdateRect(screen, 0, 0, 0, 0);
-}
-
-SDL_Surface *initScreen(int width, int height, int bpp)
-{
- /* Initialize SDL */
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
- fprintf(stderr, "Unable to init SDL: %s\n",
- SDL_GetError());
- exit(1);
- }
- atexit(onExit);
-
- /* Open a screen with the specified properties */
- SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp,
- SDL_SWSURFACE |
- SDL_RESIZABLE);
- if (screen == NULL) {
- fprintf(stderr, "Unable to set %ix%i video: %s\n", width,
- height, SDL_GetError());
- exit(1);
- }
-
- SDL_WM_SetCaption("Cairo clock - Press Q to quit", "ICON");
- return screen;
-}
-
-/* This function pushes a custom event onto the SDL event queue.
- * Whenever the main loop receives it, the window will be redrawn.
- * We can't redraw the window here, since this function could be called
- * from another thread.
- */
-Uint32 callback_draw(Uint32 interval, void *param)
-{
- SDL_Event event;
- event.type = SDL_USEREVENT;
- SDL_PushEvent(&event);
-
- /* We want the callback function to be called again in 100 ms. */
- return 100;
-}
-
-int main(int argc, char **argv)
-{
- SDL_Surface *screen;
- SDL_Event event;
-
- /* Initialize SDL, open a screen */
- screen = initScreen(640, 480, 32);
-
- /* Create a timer which will redraw the screen every 100 ms. */
- SDL_AddTimer(100, callback_draw, NULL);
-
- while (1) {
- while (SDL_WaitEvent(&event)) {
- switch (event.type) {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_q) {
- exit(0);
- }
- break;
-
- case SDL_QUIT:
- exit(0);
- break;
-
- case SDL_VIDEORESIZE:
- /* Resize the screen and redraw */
- screen =
- SDL_SetVideoMode(event.resize.w,
- event.resize.h, 32,
- SDL_SWSURFACE |
- SDL_RESIZABLE);
- drawScreen(screen);
- break;
-
- case SDL_USEREVENT:
- /* An event from callback_draw is received. */
- /* Redraw the screen! */
- drawScreen(screen);
- break;
-
- default:
- break;
- }
- }
- }
-}
diff --git a/src/SDL/SDLClockMakefile b/src/SDL/SDLClockMakefile
deleted file mode 100644
index ab7c3c1..0000000
--- a/src/SDL/SDLClockMakefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#the compiler
-CC = gcc
-
-#compiler options
-COPTS = -O3 -g -Wall $(shell sdl-config --cflags)
-
-#header files
-INCLUDES = \
- -I. \
- $(NULL)
-
-#library directories
-LIBDIRS = \
- $(NULL)
-
-#libraries to link with
-LIBS = \
- $(NULL)
-
-#all compiler flags
-CFLAGS = $(COPTS) $(INCLUDES)
-CFLAGS += `pkg-config cairo --cflags`
-
-#all linker options and libs
-LFLAGS = $(LIBDIRS) $(shell sdl-config --libs)
-LFLAGS += `pkg-config cairo --libs`
-
-#default compilation rules
-%.o: %.c
- $(CC) -c $< $(CFLAGS) -o $@
-
-#local headers to depend on
-HEADERS = \
- $(NULL)
-
-#files to compile
-CCFILES = \
- sdl-clock.c \
- $(NULL)
-
-#all local .o files
-OBJS = ${CCFILES:.c=.o}
-
-default: sdl-clock
-
-sdl-clock: $(OBJS) $(HEADERS)
- $(CC) $(LFLAGS) $(OBJS) $(LIBS) -o $@
-
-clean:
- rm -f core $(OBJS) sdl-clock *~
-
-indent:
- indent -kr -i8 *.c
-
-new: clean default
-
diff --git a/src/SDL/sdl-clock.c b/src/SDL/sdl-clock.c
new file mode 100644
index 0000000..f8e3209
--- /dev/null
+++ b/src/SDL/sdl-clock.c
@@ -0,0 +1,174 @@
+/*
+ * Cairo SDL clock. Shows how to use Cairo with SDL.
+ * Made by Writser Cleveringa, based upon code from Eric Windisch.
+ * Minor code clean up by Chris Nystrom (5/21/06) and converted to cairo-sdl
+ * by Chris Wilson.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+#include <SDL.h>
+#include <cairo-sdl.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/* Draws a clock on a normalized Cairo context */
+static void
+draw (cairo_t *cr)
+{
+ time_t t;
+ struct tm *tm;
+ double seconds, minutes, hours;
+
+ /* In newer versions of Visual Studio localtime(..) is deprecated. */
+ /* Use localtime_s instead. See MSDN. */
+ t = time (NULL);
+ tm = localtime (&t);
+
+ /* compute the angles for the indicators of our clock */
+ seconds = tm->tm_sec * M_PI / 30;
+ minutes = tm->tm_min * M_PI / 30;
+ hours = tm->tm_hour * M_PI / 6;
+
+ /* Fill the background with white. */
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ /* who doesn't want all those nice line settings :) */
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_width (cr, 0.1);
+
+ /* translate to the center of the rendering context and draw a black */
+ /* clock outline */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_translate (cr, 0.5, 0.5);
+ cairo_arc (cr, 0, 0, 0.4, 0, M_PI * 2);
+ cairo_stroke (cr);
+
+ /* draw a white dot on the current second. */
+ cairo_set_source_rgba (cr, 1, 1, 1, 0.6);
+ cairo_arc (cr,
+ sin (seconds) * 0.4, -cos (seconds) * 0.4,
+ 0.05, 0, M_PI * 2);
+ cairo_fill (cr);
+
+ /* draw the minutes indicator */
+ cairo_set_source_rgba (cr, 0.2, 0.2, 1, 0.6);
+ cairo_move_to (cr, 0, 0);
+ cairo_line_to (cr, sin (minutes) * 0.4, -cos (minutes) * 0.4);
+ cairo_stroke (cr);
+
+ /* draw the hours indicator */
+ cairo_move_to (cr, 0, 0);
+ cairo_line_to (cr, sin (hours) * 0.2, -cos (hours) * 0.2);
+ cairo_stroke (cr);
+}
+
+/* Shows how to draw with Cairo on SDL surfaces */
+static void
+draw_screen (SDL_Surface *screen)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ /* Create a cairo drawing context, normalize it and draw a clock. */
+
+ surface = cairo_sdl_surface_create (screen);
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+
+ cairo_scale (cr, screen->w, screen->h);
+ draw (cr);
+ cairo_destroy (cr);
+}
+
+static SDL_Surface *
+init_screen (int width, int height, int bpp)
+{
+ SDL_Surface *screen;
+
+ /* Initialize SDL */
+ if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
+ fprintf (stderr, "Unable to initialize SDL: %s\n",
+ SDL_GetError ());
+ exit (1);
+ }
+
+ /* Open a screen with the specified properties */
+ screen = SDL_SetVideoMode (width, height, bpp,
+ SDL_HWSURFACE |
+ SDL_RESIZABLE);
+ if (screen == NULL) {
+ fprintf (stderr, "Unable to set %ix%i video: %s\n",
+ width, height, SDL_GetError ());
+ exit (1);
+ }
+
+ SDL_WM_SetCaption ("Cairo clock - Press Q to quit", "ICON");
+
+ return screen;
+}
+
+/* This function pushes a custom event onto the SDL event queue.
+ * Whenever the main loop receives it, the window will be redrawn.
+ * We can't redraw the window here, since this function could be called
+ * from another thread.
+ */
+static Uint32
+timer_cb (Uint32 interval, void *param)
+{
+ SDL_Event event;
+
+ event.type = SDL_USEREVENT;
+ SDL_PushEvent (&event);
+
+ /* We want the callback function to be called again in 100 ms. */
+ return 100;
+}
+
+int
+main (int argc, char **argv)
+{
+ SDL_Surface *screen;
+ SDL_Event event;
+
+ /* Initialize SDL, open a screen */
+ screen = init_screen (640, 480, 32);
+
+ /* Create a timer which will redraw the screen every 100 ms. */
+ SDL_AddTimer (100, timer_cb, NULL);
+
+ while (SDL_WaitEvent (&event)) {
+ switch (event.type) {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_q) {
+ goto done;
+ }
+ break;
+
+ case SDL_QUIT:
+ goto done;
+
+ case SDL_VIDEORESIZE:
+ screen = SDL_SetVideoMode (event.resize.w,
+ event.resize.h, 32,
+ SDL_HWSURFACE |
+ SDL_RESIZABLE);
+ /* fall-through */
+ case SDL_USEREVENT:
+ draw_screen (screen);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+done:
+ SDL_FreeSurface (screen);
+ SDL_Quit ();
+ return 0;
+}
More information about the cairo-commit
mailing list