[cairo-commit] [cairo-www] src/SDL src/SDL.mdwn
Carl Worth
cworth at freedesktop.org
Thu Jul 5 08:08:29 PDT 2007
src/SDL.mdwn | 2
src/SDL/SDLClock.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++
src/SDL/SDLClockMakefile | 56 ++++++++++++
3 files changed, 268 insertions(+), 1 deletion(-)
New commits:
commit 4628281c7b7e06aafd802bfaa662c520e24f81b3
Author: Carl Worth <cworth at cworth.org>
Date: Thu Jul 5 08:07:19 2007 -0700
Add rescued SDL clock example
diff --git a/src/SDL.mdwn b/src/SDL.mdwn
index a37414c..d361b8c 100644
--- a/src/SDL.mdwn
+++ b/src/SDL.mdwn
@@ -8,7 +8,7 @@ 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]]. A [[makefile|SDLClockMakefile]] for this
+[[source_code|SDLClock.c]]. A [[makefile|SDLClockMakefile]] for this
code is also available.
Visual Studio tip:
diff --git a/src/SDL/SDLClock.c b/src/SDL/SDLClock.c
new file mode 100644
index 0000000..cfcb0e7
--- /dev/null
+++ b/src/SDL/SDLClock.c
@@ -0,0 +1,211 @@
+/*
+ * 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
new file mode 100644
index 0000000..ab7c3c1
--- /dev/null
+++ b/src/SDL/SDLClockMakefile
@@ -0,0 +1,56 @@
+#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
+
More information about the cairo-commit
mailing list