From 78e1f63fcd25635e88c0a92866bbb86b63a115bd Mon Sep 17 00:00:00 2001 From: Tommi Komulainen Date: Mon, 9 Jun 2008 21:15:12 +0000 Subject: [PATCH] cogl: add support for quartz imagebackend Bug #930 - add support for quartz imagebackend * clutter/cogl/common/cogl-bitmap-pixbuf.c (_cogl_bitmap_from_file): When USE_QUARTZ is defined implement using Core Graphics. * configure.ac: support --with-imagebackend=quartz and print which imagebackend is selected. Make quartz default on OSX --- ChangeLog | 10 ++ clutter/cogl/common/cogl-bitmap-pixbuf.c | 114 ++++++++++++++++++++++- configure.ac | 16 +++- 3 files changed, 136 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91a6e7cba..3650147c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-06-09 Tommi Komulainen + + Bug #930 - add support for quartz imagebackend + + * clutter/cogl/common/cogl-bitmap-pixbuf.c + (_cogl_bitmap_from_file): When USE_QUARTZ is defined implement + using Core Graphics. + * configure.ac: support --with-imagebackend=quartz and print + which imagebackend is selected. Make quartz default on OSX + 2008-06-09 Øyvind Kolås * clutter/cogl/common/cogl-primitives.c: (cogl_path_rel_curve_to): diff --git a/clutter/cogl/common/cogl-bitmap-pixbuf.c b/clutter/cogl/common/cogl-bitmap-pixbuf.c index 906cee01b..dd9dd0277 100644 --- a/clutter/cogl/common/cogl-bitmap-pixbuf.c +++ b/clutter/cogl/common/cogl-bitmap-pixbuf.c @@ -33,7 +33,9 @@ #include -#ifdef USE_GDKPIXBUF +#ifdef USE_QUARTZ +#include +#elif defined(USE_GDKPIXBUF) #include #endif @@ -64,7 +66,115 @@ _cogl_bitmap_unpremult (const CoglBitmap *bmp, return FALSE; } -#ifdef USE_GDKPIXBUF +#ifdef USE_QUARTZ + +/* lacking GdkPixbuf and other useful GError domains, define one of our own */ + +#define COGL_BITMAP_ERROR cogl_bitmap_error_quark () + +typedef enum { + COGL_BITMAP_ERROR_FAILED, + COGL_BITMAP_ERROR_UNKNOWN_TYPE, + COGL_BITMAP_ERROR_CORRUPT_IMAGE +} CoglBitmapError; + +GQuark +cogl_bitmap_error_quark (void) +{ + return g_quark_from_static_string ("cogl-bitmap-error-quark"); +} + +/* the error does not contain the filename as the caller already has it */ +gboolean +_cogl_bitmap_from_file (CoglBitmap *bmp, + const gchar *filename, + GError **error) +{ + g_assert (bmp != NULL); + g_assert (filename != NULL); + g_assert (error == NULL || *error == NULL); + + CFURLRef url = CFURLCreateFromFileSystemRepresentation (NULL, (guchar*)filename, strlen(filename), false); + CGImageSourceRef image_source = CGImageSourceCreateWithURL (url, NULL); + int save_errno = errno; + CFRelease (url); + if (image_source == NULL) + { + /* doesn't exist, not readable, etc. */ + g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED, + "%s", g_strerror (save_errno)); + return FALSE; + } + + /* Unknown images would be cleanly caught as zero width/height below, but try + * to provide better error message + */ + CFStringRef type = CGImageSourceGetType (image_source); + if (type == NULL) + { + CFRelease (image_source); + g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_UNKNOWN_TYPE, + "Unknown image type"); + return FALSE; + } + CFRelease (type); + + CGImageRef image = CGImageSourceCreateImageAtIndex (image_source, 0, NULL); + CFRelease (image_source); + + size_t width = CGImageGetWidth (image); + size_t height = CGImageGetHeight (image); + if (width == 0 || height == 0) + { + /* incomplete or corrupt */ + CFRelease (image); + g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_CORRUPT_IMAGE, + "Image has zero width or height"); + return FALSE; + } + + /* allocate buffer big enough to hold pixel data */ + size_t rowstride; + CGBitmapInfo bitmap_info = CGImageGetBitmapInfo (image); + if ((bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaNone) + { + bitmap_info = kCGImageAlphaNone; + rowstride = 3 * width; + } + else + { + bitmap_info = kCGImageAlphaPremultipliedFirst; + rowstride = 4 * width; + } + guint8 *out_data = g_malloc0 (height * rowstride); + + /* render to buffer */ + CGColorSpaceRef color_space = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); + CGContextRef bitmap_context = CGBitmapContextCreate (out_data, + width, height, 8, + rowstride, color_space, + bitmap_info); + CGColorSpaceRelease (color_space); + + const CGRect rect = {{0, 0}, {width, height}}; + CGContextDrawImage (bitmap_context, rect, image); + + CGImageRelease (image); + CGContextRelease (bitmap_context); + + /* store bitmap info */ + bmp->data = out_data; + bmp->format = bitmap_info == kCGImageAlphaPremultipliedFirst + ? COGL_PIXEL_FORMAT_ARGB_8888 + : COGL_PIXEL_FORMAT_RGB_888; + bmp->width = width; + bmp->height = height; + bmp->rowstride = rowstride; + + return TRUE; +} + +#elif defined(USE_GDKPIXBUF) gboolean _cogl_bitmap_from_file (CoglBitmap *bmp, diff --git a/configure.ac b/configure.ac index 5693774a9..56ae83ae1 100644 --- a/configure.ac +++ b/configure.ac @@ -85,14 +85,25 @@ PKG_PROG_PKG_CONFIG dnl ======================================================================== -imagebackend="gdk-pixbuf" +# Peek which flavour the user wants so that we can couple the osx flavour with +# quartz imageloader. +if test "x$with_flavour" = "xosx"; then + imagebackend="quartz" +else + imagebackend="gdk-pixbuf" +fi + AC_ARG_WITH([imagebackend], - AC_HELP_STRING([--with-imagebackend=@<:@gdk-pixbuf/internal@:>@], + AC_HELP_STRING([--with-imagebackend=@<:@gdk-pixbuf/quartz/internal@:>@], [Select COGL image loading backend]), imagebackend=$with_imagebackend) case $imagebackend in + quartz) + AC_DEFINE([USE_QUARTZ], 1, [Use Core Graphics (Quartz) for loading image files]) + ;; + gdk-pixbuf) AC_DEFINE([USE_GDKPIXBUF], 1, [Use GdkPixbuf for loading image files]) ;; @@ -629,6 +640,7 @@ echo " prefix: ${prefix}" echo "" echo " Flavour: ${clutterbackend}/${CLUTTER_COGL}" echo " GL Headers: ${CLUTTER_GL_HEADER}" +echo " Image backend: ${imagebackend}" echo " Target library: ${clutterbackendlib}" echo " Debug level: ${enable_debug}" echo " Compiler flags: ${CPPFLAGS}"