diff -Naur DirectFB-1.2.10/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c DirectFB-1.2.10-magellan/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c --- DirectFB-1.2.10/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c 2009-08-27 21:54:18.000000000 +0200 +++ DirectFB-1.2.10-magellan/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c 2011-03-12 00:13:13.000000000 +0100 @@ -204,7 +204,7 @@ if (!data->png_ptr) goto error; - if (setjmp( data->png_ptr->jmpbuf )) { + if (png_jmpbuf( data->png_ptr )) { D_ERROR( "ImageProvider/PNG: Error reading header!\n" ); goto error; } @@ -331,7 +331,7 @@ rect = dst_data->area.wanted; } - if (setjmp( data->png_ptr->jmpbuf )) { + if (png_jmpbuf( data->png_ptr )) { D_ERROR( "ImageProvider/PNG: Error during decoding!\n" ); if (data->stage < STAGE_IMAGE) @@ -350,6 +350,7 @@ /* actual rendering */ if (dfb_rectangle_region_intersects( &rect, &clip )) { CoreSurfaceBufferLock lock; + png_byte bit_depth = png_get_bit_depth( data->png_ptr, data->info_ptr ); ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAF_CPU_WRITE, &lock ); if (ret) @@ -357,7 +358,7 @@ switch (data->color_type) { case PNG_COLOR_TYPE_PALETTE: - if (dst_surface->config.format == DSPF_LUT8 && data->info_ptr->bit_depth == 8) { + if (dst_surface->config.format == DSPF_LUT8 && bit_depth == 8) { /* * Special indexed PNG to LUT8 loading. */ @@ -400,7 +401,7 @@ } else { if (data->color_type == PNG_COLOR_TYPE_GRAY) { - int num = 1 << data->info_ptr->bit_depth; + int num = 1 << bit_depth; for (x=0; xinfo_ptr->bit_depth) { + switch (bit_depth) { case 8: for (y=0; yheight; y++) { u8 *S = data->image + data->pitch * y; @@ -464,7 +465,7 @@ default: D_ERROR( "ImageProvider/PNG: Unsupported indexed bit depth %d!\n", - data->info_ptr->bit_depth ); + bit_depth ); } dfb_scale_linear_32( image_argb, data->width, data->height, @@ -630,16 +631,26 @@ NULL, NULL, NULL ); if (png_get_valid( data->png_ptr, data->info_ptr, PNG_INFO_tRNS )) { + png_bytep trans; + png_color_16p trans_color; + int num_trans; + + png_get_tRNS( data->png_ptr, data->info_ptr, &trans, &num_trans, &trans_color ); + data->color_keyed = true; /* generate color key based on palette... */ if (data->color_type == PNG_COLOR_TYPE_PALETTE) { u32 key; - png_colorp palette = data->info_ptr->palette; - png_bytep trans = data->info_ptr->trans; - int num_colors = MIN( MAXCOLORMAPSIZE, - data->info_ptr->num_palette ); - u8 cmap[3][num_colors]; + png_colorp palette; + int num_colors; + u8 *cmap[3]; + + png_get_PLTE( data->png_ptr, data->info_ptr, &palette, &num_colors ); + num_colors = MIN( MAXCOLORMAPSIZE, num_colors ); + cmap[0] = alloca (num_colors); + cmap[1] = alloca (num_colors); + cmap[2] = alloca (num_colors); for (i=0; iinfo_ptr->num_trans; i++) { + for (i=0; i> 16; palette[i].green = (key & 0x00ff00) >> 8; @@ -661,20 +672,23 @@ } else { /* ...or based on trans rgb value */ - png_color_16p trans = &data->info_ptr->trans_values; - - data->color_key = (((trans->red & 0xff00) << 8) | - ((trans->green & 0xff00)) | - ((trans->blue & 0xff00) >> 8)); + data->color_key = (((trans_color->red & 0xff00) << 8) | + ((trans_color->green & 0xff00)) | + ((trans_color->blue & 0xff00) >> 8)); } } switch (data->color_type) { case PNG_COLOR_TYPE_PALETTE: { - png_colorp palette = data->info_ptr->palette; - png_bytep trans = data->info_ptr->trans; - int num_trans = data->info_ptr->num_trans; - int num_colors = MIN( MAXCOLORMAPSIZE, data->info_ptr->num_palette ); + png_colorp palette; + png_bytep trans; + png_color_16p trans_color; + int num_trans; + int num_colors; + + png_get_PLTE( data->png_ptr, data->info_ptr, &palette, &num_colors ); + num_colors = MIN( MAXCOLORMAPSIZE, num_colors ); + png_get_tRNS( data->png_ptr, data->info_ptr, &trans, &num_trans, &trans_color ); for (i=0; icolors[i].a = (i < num_trans) ? trans[i] : 0xff; diff -Naur DirectFB-1.2.10/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c~ DirectFB-1.2.10-magellan/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c~ --- DirectFB-1.2.10/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c~ 1970-01-01 01:00:00.000000000 +0100 +++ DirectFB-1.2.10-magellan/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c~ 2011-03-12 00:13:13.000000000 +0100 @@ -0,0 +1,861 @@ +/* + (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "config.h" + +static DFBResult +Probe( IDirectFBImageProvider_ProbeContext *ctx ); + +static DFBResult +Construct( IDirectFBImageProvider *thiz, + ... ); + +#include + +DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, PNG ) + + +enum { + STAGE_ABORT = -2, + STAGE_ERROR = -1, + STAGE_START = 0, + STAGE_INFO, + STAGE_IMAGE, + STAGE_END +}; + +/* + * private data struct of IDirectFBImageProvider_PNG + */ +typedef struct { + int ref; /* reference counter */ + IDirectFBDataBuffer *buffer; + + int stage; + int rows; + + png_structp png_ptr; + png_infop info_ptr; + + png_uint_32 width; + png_uint_32 height; + int bpp; + int color_type; + png_uint_32 color_key; + bool color_keyed; + + void *image; + int pitch; + u32 palette[256]; + DFBColor colors[256]; + + DIRenderCallback render_callback; + void *render_callback_context; + + CoreDFB *core; +} IDirectFBImageProvider_PNG_data; + +static DirectResult +IDirectFBImageProvider_PNG_AddRef ( IDirectFBImageProvider *thiz ); + +static DirectResult +IDirectFBImageProvider_PNG_Release ( IDirectFBImageProvider *thiz ); + +static DFBResult +IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + IDirectFBSurface *destination, + const DFBRectangle *destination_rect ); + +static DFBResult +IDirectFBImageProvider_PNG_SetRenderCallback( IDirectFBImageProvider *thiz, + DIRenderCallback callback, + void *context ); + +static DFBResult +IDirectFBImageProvider_PNG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *dsc ); + +static DFBResult +IDirectFBImageProvider_PNG_GetImageDescription( IDirectFBImageProvider *thiz, + DFBImageDescription *dsc ); + +/* Called at the start of the progressive load, once we have image info */ +static void +png_info_callback (png_structp png_read_ptr, + png_infop png_info_ptr); + +/* Called for each row; note that you will get duplicate row numbers + for interlaced PNGs */ +static void +png_row_callback (png_structp png_read_ptr, + png_bytep new_row, + png_uint_32 row_num, + int pass_num); + +/* Called after reading the entire image */ +static void +png_end_callback (png_structp png_read_ptr, + png_infop png_info_ptr); + +/* Pipes data into libpng until stage is different from the one specified. */ +static DFBResult +push_data_until_stage (IDirectFBImageProvider_PNG_data *data, + int stage, + int buffer_size); + +/**********************************************************************************************************************/ + +static DFBResult +Probe( IDirectFBImageProvider_ProbeContext *ctx ) +{ + if (png_check_sig( ctx->header, 8 )) + return DFB_OK; + + return DFB_UNSUPPORTED; +} + +static DFBResult +Construct( IDirectFBImageProvider *thiz, + ... ) +{ + DFBResult ret = DFB_FAILURE; + + IDirectFBDataBuffer *buffer; + CoreDFB *core; + va_list tag; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBImageProvider_PNG) + + va_start( tag, thiz ); + buffer = va_arg( tag, IDirectFBDataBuffer * ); + core = va_arg( tag, CoreDFB * ); + va_end( tag ); + + data->ref = 1; + data->buffer = buffer; + data->core = core; + + /* Increase the data buffer reference counter. */ + buffer->AddRef( buffer ); + + /* Create the PNG read handle. */ + data->png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL ); + if (!data->png_ptr) + goto error; + + if (png_jmpbuf( data->png_ptr )) { + D_ERROR( "ImageProvider/PNG: Error reading header!\n" ); + goto error; + } + + /* Create the PNG info handle. */ + data->info_ptr = png_create_info_struct( data->png_ptr ); + if (!data->info_ptr) + goto error; + + /* Setup progressive image loading. */ + png_set_progressive_read_fn( data->png_ptr, data, + png_info_callback, + png_row_callback, + png_end_callback ); + + + /* Read until info callback is called. */ + ret = push_data_until_stage( data, STAGE_INFO, 64 ); + if (ret) + goto error; + + thiz->AddRef = IDirectFBImageProvider_PNG_AddRef; + thiz->Release = IDirectFBImageProvider_PNG_Release; + thiz->RenderTo = IDirectFBImageProvider_PNG_RenderTo; + thiz->SetRenderCallback = IDirectFBImageProvider_PNG_SetRenderCallback; + thiz->GetImageDescription = IDirectFBImageProvider_PNG_GetImageDescription; + thiz->GetSurfaceDescription = IDirectFBImageProvider_PNG_GetSurfaceDescription; + + return DFB_OK; + +error: + if (data->png_ptr) + png_destroy_read_struct( &data->png_ptr, &data->info_ptr, NULL ); + + buffer->Release( buffer ); + + if (data->image) + D_FREE( data->image ); + + DIRECT_DEALLOCATE_INTERFACE(thiz); + + return ret; +} + +/**********************************************************************************************************************/ + +static void +IDirectFBImageProvider_PNG_Destruct( IDirectFBImageProvider *thiz ) +{ + IDirectFBImageProvider_PNG_data *data = + (IDirectFBImageProvider_PNG_data*)thiz->priv; + + png_destroy_read_struct( &data->png_ptr, &data->info_ptr, NULL ); + + /* Decrease the data buffer reference counter. */ + data->buffer->Release( data->buffer ); + + /* Deallocate image data. */ + if (data->image) + D_FREE( data->image ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +static DirectResult +IDirectFBImageProvider_PNG_AddRef( IDirectFBImageProvider *thiz ) +{ + DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBImageProvider_PNG_Release( IDirectFBImageProvider *thiz ) +{ + DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) + + if (--data->ref == 0) { + IDirectFBImageProvider_PNG_Destruct( thiz ); + } + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static DFBResult +IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + IDirectFBSurface *destination, + const DFBRectangle *dest_rect ) +{ + DFBResult ret = DFB_OK; + IDirectFBSurface_data *dst_data; + CoreSurface *dst_surface; + DFBRegion clip; + DFBRectangle rect; + png_infop info; + int x, y; + + DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) + + info = data->info_ptr; + + dst_data = (IDirectFBSurface_data*) destination->priv; + if (!dst_data) + return DFB_DEAD; + + dst_surface = dst_data->surface; + if (!dst_surface) + return DFB_DESTROYED; + + dfb_region_from_rectangle( &clip, &dst_data->area.current ); + + if (dest_rect) { + if (dest_rect->w < 1 || dest_rect->h < 1) + return DFB_INVARG; + rect = *dest_rect; + rect.x += dst_data->area.wanted.x; + rect.y += dst_data->area.wanted.y; + } + else { + rect = dst_data->area.wanted; + } + + if (png_jmpbuf( data->png_ptr )) { + D_ERROR( "ImageProvider/PNG: Error during decoding!\n" ); + + if (data->stage < STAGE_IMAGE) + return DFB_FAILURE; + + data->stage = STAGE_ERROR; + } + + /* Read until image is completely decoded. */ + if (data->stage != STAGE_ERROR) { + ret = push_data_until_stage( data, STAGE_END, 16384 ); + if (ret) + return ret; + } + + /* actual rendering */ + if (dfb_rectangle_region_intersects( &rect, &clip )) { + CoreSurfaceBufferLock lock; + png_byte bit_depth = png_get_bit_depth( data->png_ptr, data->info_ptr ); + + ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAF_CPU_WRITE, &lock ); + if (ret) + return ret; + + switch (data->color_type) { + case PNG_COLOR_TYPE_PALETTE: + if (dst_surface->config.format == DSPF_LUT8 && bit_depth == 8) { + /* + * Special indexed PNG to LUT8 loading. + */ + + /* FIXME: Limitation for LUT8 is to load complete surface only. */ + dfb_clip_rectangle( &clip, &rect ); + if (rect.x == 0 && rect.y == 0 && + rect.w == dst_surface->config.size.w && + rect.h == dst_surface->config.size.h && + rect.w == data->width && + rect.h == data->height) + { + for (y=0; yheight; y++) + direct_memcpy( lock.addr + lock.pitch * y, + data->image + data->pitch * y, + data->width ); + + break; + } + } + /* fall through */ + + case PNG_COLOR_TYPE_GRAY: { + /* + * Convert to ARGB and use generic loading code. + */ + + // FIXME: allocates four additional bytes because the scaling functions + // in src/misc/gfx_util.c have an off-by-one bug which causes + // segfaults on darwin/osx (not on linux) + int size = data->width * data->height * 4 + 4; + + /* allocate image data */ + void *image_argb = D_MALLOC( size ); + + if (!image_argb) { + D_ERROR( "DirectFB/ImageProvider_PNG: Could not " + "allocate %d bytes of system memory!\n", size ); + ret = DFB_NOSYSTEMMEMORY; + } + else { + if (data->color_type == PNG_COLOR_TYPE_GRAY) { + int num = 1 << bit_depth; + + for (x=0; xpalette[x] = 0xff000000 | (value << 16) | (value << 8) | value; + } + } + + switch (bit_depth) { + case 8: + for (y=0; yheight; y++) { + u8 *S = data->image + data->pitch * y; + u32 *D = image_argb + data->width * y * 4; + + for (x=0; xwidth; x++) + D[x] = data->palette[ S[x] ]; + } + break; + + case 4: + for (y=0; yheight; y++) { + u8 *S = data->image + data->pitch * y; + u32 *D = image_argb + data->width * y * 4; + + for (x=0; xwidth; x++) { + if (x & 1) + D[x] = data->palette[ S[x>>1] & 0xf ]; + else + D[x] = data->palette[ S[x>>1] >> 4 ]; + } + } + break; + + case 2: + for (y=0; yheight; y++) { + int n = 6; + u8 *S = data->image + data->pitch * y; + u32 *D = image_argb + data->width * y * 4; + + for (x=0; xwidth; x++) { + D[x] = data->palette[ (S[x>>2] >> n) & 3 ]; + + n = (n ? n - 2 : 6); + } + } + break; + + case 1: + for (y=0; yheight; y++) { + int n = 7; + u8 *S = data->image + data->pitch * y; + u32 *D = image_argb + data->width * y * 4; + + for (x=0; xwidth; x++) { + D[x] = data->palette[ (S[x>>3] >> n) & 1 ]; + + n = (n ? n - 1 : 7); + } + } + break; + + default: + D_ERROR( "ImageProvider/PNG: Unsupported indexed bit depth %d!\n", + bit_depth ); + } + + dfb_scale_linear_32( image_argb, data->width, data->height, + lock.addr, lock.pitch, &rect, dst_surface, &clip ); + + D_FREE( image_argb ); + } + break; + } + default: + /* + * Generic loading code. + */ + dfb_scale_linear_32( data->image, data->width, data->height, + lock.addr, lock.pitch, &rect, dst_surface, &clip ); + break; + } + + dfb_surface_unlock_buffer( dst_surface, &lock ); + } + + if (data->stage != STAGE_END) + ret = DFB_INCOMPLETE; + + return ret; +} + +static DFBResult +IDirectFBImageProvider_PNG_SetRenderCallback( IDirectFBImageProvider *thiz, + DIRenderCallback callback, + void *context ) +{ + DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) + + data->render_callback = callback; + data->render_callback_context = context; + + return DFB_OK; +} + +static DFBResult +IDirectFBImageProvider_PNG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *dsc ) +{ + DFBSurfacePixelFormat primary_format = dfb_primary_layer_pixelformat(); + + DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) + + dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; + dsc->width = data->width; + dsc->height = data->height; + + if (data->color_type & PNG_COLOR_MASK_ALPHA) + dsc->pixelformat = DFB_PIXELFORMAT_HAS_ALPHA(primary_format) ? primary_format : DSPF_ARGB; + else + dsc->pixelformat = primary_format; + + if (data->color_type == PNG_COLOR_TYPE_PALETTE) { + dsc->flags |= DSDESC_PALETTE; + + dsc->palette.entries = data->colors; /* FIXME */ + dsc->palette.size = 256; + } + + return DFB_OK; +} + +static DFBResult +IDirectFBImageProvider_PNG_GetImageDescription( IDirectFBImageProvider *thiz, + DFBImageDescription *dsc ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_PNG) + + if (!dsc) + return DFB_INVARG; + + dsc->caps = DICAPS_NONE; + + if (data->color_type & PNG_COLOR_MASK_ALPHA) + dsc->caps |= DICAPS_ALPHACHANNEL; + + if (data->color_keyed) { + dsc->caps |= DICAPS_COLORKEY; + + dsc->colorkey_r = (data->color_key & 0xff0000) >> 16; + dsc->colorkey_g = (data->color_key & 0x00ff00) >> 8; + dsc->colorkey_b = (data->color_key & 0x0000ff); + } + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +#define MAXCOLORMAPSIZE 256 + +static int SortColors (const void *a, const void *b) +{ + return (*((const u8 *) a) - *((const u8 *) b)); +} + +/* looks for a color that is not in the colormap and ideally not + even close to the colors used in the colormap */ +static u32 FindColorKey( int n_colors, u8 *cmap ) +{ + u32 color = 0xFF000000; + u8 csort[n_colors]; + int i, j, index, d; + + if (n_colors < 1) + return color; + + for (i = 0; i < 3; i++) { + direct_memcpy( csort, cmap + (n_colors * i), n_colors ); + qsort( csort, n_colors, 1, SortColors ); + + for (j = 1, index = 0, d = 0; j < n_colors; j++) { + if (csort[j] - csort[j-1] > d) { + d = csort[j] - csort[j-1]; + index = j; + } + } + if ((csort[0] - 0x0) > d) { + d = csort[0] - 0x0; + index = n_colors; + } + if (0xFF - (csort[n_colors - 1]) > d) { + index = n_colors + 1; + } + + if (index < n_colors) + csort[0] = csort[index] - (d/2); + else if (index == n_colors) + csort[0] = 0x0; + else + csort[0] = 0xFF; + + color |= (csort[0] << (8 * (2 - i))); + } + + return color; +} + +/* Called at the start of the progressive load, once we have image info */ +static void +png_info_callback( png_structp png_read_ptr, + png_infop png_info_ptr ) +{ + int i; + IDirectFBImageProvider_PNG_data *data; + + data = png_get_progressive_ptr( png_read_ptr ); + + /* error stage? */ + if (data->stage < 0) + return; + + /* set info stage */ + data->stage = STAGE_INFO; + + png_get_IHDR( data->png_ptr, data->info_ptr, + &data->width, &data->height, &data->bpp, &data->color_type, + NULL, NULL, NULL ); + + if (png_get_valid( data->png_ptr, data->info_ptr, PNG_INFO_tRNS )) { + png_bytep trans; + png_color_16p trans_color; + int num_trans; + + png_get_tRNS( data->png_ptr, data->info_ptr, &trans, &num_trans, &trans_color ); + + data->color_keyed = true; + + /* generate color key based on palette... */ + if (data->color_type == PNG_COLOR_TYPE_PALETTE) { + u32 key; + png_colorp palette; + int num_colors; + u8 *cmap[3]; + + png_get_PLTE( data->png_ptr, data->info_ptr, &palette, &num_colors ); + num_colors = MIN( MAXCOLORMAPSIZE, num_colors ); + cmap[0] = alloca (num_colors); + cmap[1] = alloca (num_colors); + cmap[2] = alloca (num_colors); + + for (i=0; i> 16; + palette[i].green = (key & 0x00ff00) >> 8; + palette[i].blue = (key & 0x0000ff); + } + } + + data->color_key = key; + } + else { + /* ...or based on trans rgb value */ + data->color_key = (((trans_color->red & 0xff00) << 8) | + ((trans_color->green & 0xff00)) | + ((trans_color->blue & 0xff00) >> 8)); + } + } + + switch (data->color_type) { + case PNG_COLOR_TYPE_PALETTE: { + png_colorp palette = data->info_ptr->palette; + png_bytep trans = data->info_ptr->trans; + int num_trans = data->info_ptr->num_trans; + int num_colors = MIN( MAXCOLORMAPSIZE, data->info_ptr->num_palette ); + + for (i=0; icolors[i].a = (i < num_trans) ? trans[i] : 0xff; + data->colors[i].r = palette[i].red; + data->colors[i].g = palette[i].green; + data->colors[i].b = palette[i].blue; + + data->palette[i] = PIXEL_ARGB( data->colors[i].a, + data->colors[i].r, + data->colors[i].g, + data->colors[i].b ); + } + + data->pitch = (data->width + 7) & ~7; + break; + } + + case PNG_COLOR_TYPE_GRAY: + data->pitch = data->width; + + if (data->bpp == 16) + png_set_strip_16( data->png_ptr ); + + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_set_gray_to_rgb( data->png_ptr ); + /* fall through */ + + default: + data->pitch = data->width * 4; + + if (data->bpp == 16) + png_set_strip_16( data->png_ptr ); + +#ifdef WORDS_BIGENDIAN + if (!(data->color_type & PNG_COLOR_MASK_ALPHA)) + png_set_filler( data->png_ptr, 0xFF, PNG_FILLER_BEFORE ); + + png_set_swap_alpha( data->png_ptr ); +#else + if (!(data->color_type & PNG_COLOR_MASK_ALPHA)) + png_set_filler( data->png_ptr, 0xFF, PNG_FILLER_AFTER ); + + png_set_bgr( data->png_ptr ); +#endif + break; + } + + png_set_interlace_handling( data->png_ptr ); + + /* Update the info to reflect our transformations */ + png_read_update_info( data->png_ptr, data->info_ptr ); +} + +/* Called for each row; note that you will get duplicate row numbers + for interlaced PNGs */ +static void +png_row_callback( png_structp png_read_ptr, + png_bytep new_row, + png_uint_32 row_num, + int pass_num ) +{ + IDirectFBImageProvider_PNG_data *data; + + data = png_get_progressive_ptr( png_read_ptr ); + + /* error stage? */ + if (data->stage < 0) + return; + + /* set image decoding stage */ + data->stage = STAGE_IMAGE; + + /* check image data pointer */ + if (!data->image) { + // FIXME: allocates four additional bytes because the scaling functions + // in src/misc/gfx_util.c have an off-by-one bug which causes + // segfaults on darwin/osx (not on linux) + int size = data->pitch * data->height + 4; + + /* allocate image data */ + data->image = D_CALLOC( 1, size ); + if (!data->image) { + D_ERROR("DirectFB/ImageProvider_PNG: Could not " + "allocate %d bytes of system memory!\n", size); + + /* set error stage */ + data->stage = STAGE_ERROR; + + return; + } + } + + /* write to image data */ + png_progressive_combine_row( data->png_ptr, (png_bytep) (data->image + + row_num * data->pitch), new_row ); + + /* increase row counter, FIXME: interlaced? */ + data->rows++; + + if (data->render_callback) { + DIRenderCallbackResult r; + DFBRectangle rect = { 0, row_num, data->width, 1 }; + + r = data->render_callback( &rect, data->render_callback_context ); + if (r != DIRCR_OK) + data->stage = STAGE_ABORT; + } +} + +/* Called after reading the entire image */ +static void +png_end_callback (png_structp png_read_ptr, + png_infop png_info_ptr) +{ + IDirectFBImageProvider_PNG_data *data; + + data = png_get_progressive_ptr( png_read_ptr ); + + /* error stage? */ + if (data->stage < 0) + return; + + /* set end stage */ + data->stage = STAGE_END; +} + +/* Pipes data into libpng until stage is different from the one specified. */ +static DFBResult +push_data_until_stage (IDirectFBImageProvider_PNG_data *data, + int stage, + int buffer_size) +{ + DFBResult ret; + IDirectFBDataBuffer *buffer = data->buffer; + + while (data->stage < stage) { + unsigned int len; + unsigned char buf[buffer_size]; + + if (data->stage < 0) + return DFB_FAILURE; + + while (buffer->HasData( buffer ) == DFB_OK) { + D_DEBUG( "ImageProvider/PNG: Retrieving data (up to %d bytes)...\n", buffer_size ); + + ret = buffer->GetData( buffer, buffer_size, buf, &len ); + if (ret) + return ret; + + D_DEBUG( "ImageProvider/PNG: Got %d bytes...\n", len ); + + png_process_data( data->png_ptr, data->info_ptr, buf, len ); + + D_DEBUG( "ImageProvider/PNG: ...processed %d bytes.\n", len ); + + /* are we there yet? */ + if (data->stage < 0 || data->stage >= stage) { + switch (data->stage) { + case STAGE_ABORT: return DFB_INTERRUPTED; + case STAGE_ERROR: return DFB_FAILURE; + default: return DFB_OK; + } + } + } + + D_DEBUG( "ImageProvider/PNG: Waiting for data...\n" ); + + if (buffer->WaitForData( buffer, 1 ) == DFB_EOF) + return DFB_FAILURE; + } + + return DFB_OK; +} diff -Naur DirectFB-1.2.10/tools/directfb-csource.c DirectFB-1.2.10-magellan/tools/directfb-csource.c --- DirectFB-1.2.10/tools/directfb-csource.c 2009-08-27 21:54:18.000000000 +0200 +++ DirectFB-1.2.10-magellan/tools/directfb-csource.c 2011-03-12 00:17:16.000000000 +0100 @@ -300,7 +300,7 @@ if (!png_ptr) goto cleanup; - if (setjmp (png_ptr->jmpbuf)) { + if (setjmp (png_jmpbuf (png_ptr))) { if (desc->preallocated[0].data) { free (desc->preallocated[0].data); desc->preallocated[0].data = NULL; @@ -367,17 +367,22 @@ } switch (src_format) { - case DSPF_LUT8: - if (info_ptr->num_palette) { + case DSPF_LUT8: { + png_colorp png_palette; + int num_palette; + + png_get_PLTE( png_ptr, info_ptr, &png_palette, &num_palette ); + + if (num_palette) { png_byte *alpha; int i, num; - *palette_size = MIN (info_ptr->num_palette, 256); + *palette_size = MIN (num_palette, 256); for (i = 0; i < *palette_size; i++) { palette[i].a = 0xFF; - palette[i].r = info_ptr->palette[i].red; - palette[i].g = info_ptr->palette[i].green; - palette[i].b = info_ptr->palette[i].blue; + palette[i].r = png_palette[i].red; + palette[i].g = png_palette[i].green; + palette[i].b = png_palette[i].blue; } if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS (png_ptr, info_ptr, &alpha, &num, NULL); @@ -386,6 +391,7 @@ } } break; + } case DSPF_RGB32: png_set_filler (png_ptr, 0xFF, #ifdef WORDS_BIGENDIAN diff -Naur DirectFB-1.2.10/tools/directfb-csource.c~ DirectFB-1.2.10-magellan/tools/directfb-csource.c~ --- DirectFB-1.2.10/tools/directfb-csource.c~ 1970-01-01 01:00:00.000000000 +0100 +++ DirectFB-1.2.10-magellan/tools/directfb-csource.c~ 2011-03-12 00:17:16.000000000 +0100 @@ -0,0 +1,856 @@ +/* + (c) Copyright 2001-2008 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + directfb-csource is based on gdk-pixbuf-csource, a GdkPixbuf + based image CSource generator Copyright (C) 1999, 2001 Tim Janik + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include + + +static struct { + DFBSurfacePixelFormat format; + const char *name; +} pixelformats[] = { + { DSPF_ARGB, "ARGB" }, + { DSPF_ARGB1555, "ARGB1555" }, + { DSPF_ARGB2554, "ARGB2554" }, + { DSPF_ARGB4444, "ARGB4444" }, + { DSPF_RGB32, "RGB32" }, + { DSPF_RGB24, "RGB24" }, + { DSPF_RGB16, "RGB16" }, + { DSPF_RGB332, "RGB332" }, + { DSPF_A8, "A8" }, + { DSPF_LUT8, "LUT8" } +}; +static int n_pixelformats = D_ARRAY_SIZE( pixelformats ); + + +static void print_usage (const char *prg_name); +static DFBResult load_image (const char *filename, + DFBSurfaceDescription *desc, + DFBColor *palette, + int *palette_size, + DFBSurfacePixelFormat rgbformat); +static DFBResult merge_images (DFBSurfaceDescription *images, + int num_images, + DFBSurfaceDescription *dest, + DFBRectangle *rectangles); +static DFBResult dump_raw_data (const char *name, + const unsigned char *data, + unsigned int len); +static DFBResult dump_image (const char *name, + DFBSurfaceDescription *desc, + DFBColor *palette, + int palette_size); +static DFBResult dump_rectangles (const char *name, + DFBRectangle *rectangles, + const char **names, + int num_rects); +static char * variable_name (const char *name); +static char * base_name (const char *name); + + +int main (int argc, + const char *argv[]) +{ + DFBSurfaceDescription desc = { flags: 0 }; + DFBSurfacePixelFormat format = DSPF_UNKNOWN; + DFBSurfacePixelFormat rgbformat = DSPF_UNKNOWN; + DFBColor palette[256]; + + const char *filename[argc]; + const char *name = NULL; + int palette_size = 0; + int num_images = 0; + int i, n; + int rawmode = 0; + + /* parse command line */ + + for (n = 1; n < argc; n++) { + if (strncmp (argv[n], "--", 2) == 0) { + + const char *arg = argv[n] + 2; + + if (strcmp (arg, "help") == 0) { + print_usage (argv[0]); + return EXIT_SUCCESS; + } + if (strcmp (arg, "version") == 0) { + fprintf (stderr, "directfb-csource version %s\n", + DIRECTFB_VERSION); + return EXIT_SUCCESS; + } + if (strcmp (arg, "raw") == 0) { + rawmode = 1; + continue; + } + if (strncmp (arg, "format=", 7) == 0 && !format) { + for (i = 0; i < n_pixelformats && !format; i++) + if (!strcasecmp (pixelformats[i].name, arg + 7)) + format = pixelformats[i].format; + if (format) + continue; + } + if (strncmp (arg, "rgbformat=", 10) == 0 && !rgbformat) { + for (i = 0; i < n_pixelformats && !rgbformat; i++) + if (!strcasecmp (pixelformats[i].name, arg + 10)) + rgbformat = pixelformats[i].format; + if (rgbformat) + continue; + } + if (strncmp (arg, "name=", 5) == 0 && !name) { + name = arg + 5; + if (*name) + continue; + } + + print_usage (argv[0]); + return EXIT_FAILURE; + } + + filename[num_images++] = argv[n]; + } + + /* check parameters */ + + if (! num_images) { + print_usage (argv[0]); + return EXIT_FAILURE; + } + + if (num_images > 1 && rawmode) { + fprintf (stderr, + "Multiple input files not allowed in raw mode.\n"); + return EXIT_FAILURE; + } + + if (num_images > 1 && !name) { + fprintf (stderr, + "You must specify a variable name when using multiple images.\n"); + return EXIT_FAILURE; + } + + /* load the first image */ + + if (rawmode) { + + struct stat statbuf; + if (0 == stat(filename[0], &statbuf)) + { + FILE *f; + unsigned char *data = alloca(statbuf.st_size); + memset(data, 0, statbuf.st_size); + + f = fopen(filename[0], "r"); + if (f) + { + fread(data, statbuf.st_size, 1, f); + fclose(f); + } + + return dump_raw_data(name ? : strrchr (filename[0], '/') ? : filename[0], + data, statbuf.st_size); + } + + } + else { + if (format) { + desc.flags = DSDESC_PIXELFORMAT; + desc.pixelformat = format; + } + + if (load_image (filename[0], &desc, palette, &palette_size, rgbformat) != DFB_OK) + return EXIT_FAILURE; + + /* dump it and quit if this is the only image on the command line */ + + if (num_images == 1) + return dump_image (name ? : strrchr (filename[0], '/') ? : filename[0], + &desc, palette, palette_size); + } + + /* merge multiple images into one surface */ + { + DFBSurfaceDescription image[num_images]; + DFBRectangle rect[num_images]; + DFBColor foo[256]; + int foo_size; + + image[0] = desc; + + for (i = 1; i < num_images; i++) { + image[i].flags = DSDESC_PIXELFORMAT; + image[i].pixelformat = desc.pixelformat; + + if (load_image (filename[i], + image + i, foo, &foo_size, rgbformat) != DFB_OK) + return EXIT_FAILURE; + } + + if (merge_images (image, num_images, &desc, rect) != DFB_OK) + return EXIT_FAILURE; + + /* dump the rectangles, then the surface */ + + if (dump_rectangles (name, rect, filename, num_images) != DFB_OK) + return EXIT_FAILURE; + + return dump_image (name, &desc, palette, palette_size); + } +} + +static void print_usage (const char *prg_name) +{ + fprintf (stderr, "directfb-csource version %s\n\n", DIRECTFB_VERSION); + fprintf (stderr, "Usage: %s [options] \n", prg_name); + fprintf (stderr, " --name= specifies variable name\n"); + fprintf (stderr, " --format= specifies surface format\n"); + fprintf (stderr, " --rgbformat= specifies format for non-alpha images\n"); + fprintf (stderr, " --multi multiple images\n"); + fprintf (stderr, " --raw dump a single file directly to header\n"); + fprintf (stderr, " --help show this help message\n"); + fprintf (stderr, " --version print version information\n"); + fprintf (stderr, "\n"); + fprintf (stderr, "See the directfb-csource(1) man-page for more information.\n"); + fprintf (stderr, "\n"); +} + +static DFBResult load_image (const char *filename, + DFBSurfaceDescription *desc, + DFBColor *palette, + int *palette_size, + DFBSurfacePixelFormat rgbformat) +{ + DFBSurfacePixelFormat dest_format; + DFBSurfacePixelFormat src_format; + FILE *fp; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + unsigned char *data = NULL; + int type; + char header[8]; + int bytes, pitch; + + dest_format = + (desc->flags & DSDESC_PIXELFORMAT) ? desc->pixelformat : DSPF_UNKNOWN; + + desc->flags = 0; + desc->preallocated[0].data = NULL; + + if (!(fp = fopen (filename, "rb"))) { + fprintf (stderr, "Failed to open file '%s': %s.\n", + filename, strerror (errno)); + goto cleanup; + } + + bytes = fread (header, 1, sizeof(header), fp); + if (png_sig_cmp ((unsigned char*) header, 0, bytes)) { + fprintf (stderr, "File '%s' doesn't seem to be a PNG image file.\n", + filename); + goto cleanup; + } + + png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (!png_ptr) + goto cleanup; + + if (setjmp (png_jmpbuf (png_ptr))) { + if (desc->preallocated[0].data) { + free (desc->preallocated[0].data); + desc->preallocated[0].data = NULL; + } + + /* data might have been clobbered, + set it to NULL and leak instead of crashing */ + data = NULL; + + goto cleanup; + } + + info_ptr = png_create_info_struct (png_ptr); + if (!info_ptr) + goto cleanup; + + png_init_io (png_ptr, fp); + png_set_sig_bytes (png_ptr, bytes); + + png_read_info (png_ptr, info_ptr); + + png_get_IHDR (png_ptr, info_ptr, + &width, &height, &bytes, &type, NULL, NULL, NULL); + + if (bytes == 16) + png_set_strip_16 (png_ptr); + +#ifdef WORDS_BIGENDIAN + png_set_swap_alpha (png_ptr); +#else + png_set_bgr (png_ptr); +#endif + + src_format = (type & PNG_COLOR_MASK_ALPHA) ? DSPF_ARGB : DSPF_RGB32; + switch (type) { + case PNG_COLOR_TYPE_GRAY: + if (dest_format == DSPF_A8) { + src_format = DSPF_A8; + break; + } + /* fallthru */ + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_set_gray_to_rgb (png_ptr); + if (rgbformat) + dest_format = rgbformat; + break; + + case PNG_COLOR_TYPE_PALETTE: + if (dest_format == DSPF_LUT8) { + src_format = DSPF_LUT8; + break; + } + png_set_palette_to_rgb (png_ptr); + /* fallthru */ + case PNG_COLOR_TYPE_RGB: + if (rgbformat) + dest_format = rgbformat; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (dest_format == DSPF_RGB24) { + png_set_strip_alpha (png_ptr); + src_format = DSPF_RGB24; + } + break; + } + + switch (src_format) { + case DSPF_LUT8: { + png_colorp png_palette; + int num_palette; + + png_get_PLTE( png_ptr, info_ptr, &png_palette, &num_palette ); + + if (num_palette) { + png_byte *alpha; + int i, num; + + *palette_size = MIN (num_palette, 256); + for (i = 0; i < *palette_size; i++) { + palette[i].a = 0xFF; + palette[i].r = png_palette[i].red; + palette[i].g = png_palette[i].green; + palette[i].b = png_palette[i].blue; + } + if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { + png_get_tRNS (png_ptr, info_ptr, &alpha, &num, NULL); + for (i = 0; i < MIN (num, *palette_size); i++) + palette[i].a = alpha[i]; + } + } + break; + case DSPF_RGB32: + png_set_filler (png_ptr, 0xFF, +#ifdef WORDS_BIGENDIAN + PNG_FILLER_BEFORE +#else + PNG_FILLER_AFTER +#endif + ); + break; + case DSPF_ARGB: + case DSPF_A8: + if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha (png_ptr); + break; + default: + break; + } + + pitch = width * DFB_BYTES_PER_PIXEL (src_format); + if (pitch & 3) + pitch += 4 - (pitch & 3); + + data = malloc (height * pitch); + if (!data) { + fprintf (stderr, "Failed to allocate %ld bytes.\n", height * pitch); + goto cleanup; + } + + { + unsigned int i; + png_bytep bptrs[height]; + + for (i = 0; i < height; i++) + bptrs[i] = data + i * pitch; + + png_read_image (png_ptr, bptrs); + } + + if (!dest_format) + dest_format = src_format; + + if (DFB_BYTES_PER_PIXEL(src_format) != DFB_BYTES_PER_PIXEL(dest_format)) { + unsigned char *s, *d, *dest; + int d_pitch, h; + + assert (DFB_BYTES_PER_PIXEL (src_format) == 4); + + d_pitch = width * DFB_BYTES_PER_PIXEL (dest_format); + if (d_pitch & 3) + d_pitch += 4 - (d_pitch & 3); + + dest = malloc (height * d_pitch); + if (!dest) { + fprintf (stderr, "Failed to allocate %ld bytes.\n", + height * d_pitch); + goto cleanup; + } + + h = height; + switch (dest_format) { + case DSPF_RGB16: + for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) + dfb_argb_to_rgb16 ((u32 *) s, (u16 *) d, width); + break; + case DSPF_ARGB1555: + for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) + dfb_argb_to_argb1555 ((u32 *) s, (u16 *) d, width); + break; + case DSPF_ARGB2554: + for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) + dfb_argb_to_argb2554 ((u32 *) s, (u16 *) d, width); + break; + case DSPF_ARGB4444: + for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) + dfb_argb_to_argb4444 ((u32 *) s, (u16 *) d, width); + break; + case DSPF_RGB332: + for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) + dfb_argb_to_rgb332 ((u32 *) s, (u8 *) d, width); + break; + case DSPF_A8: + for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) + dfb_argb_to_a8 ((u32 *) s, (u8 *) d, width); + break; + default: + fprintf (stderr, + "Sorry, unsupported format conversion.\n"); + goto cleanup; + } + + free (data); + data = dest; + pitch = d_pitch; + } + + desc->flags = (DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | + DSDESC_PREALLOCATED); + desc->width = width; + desc->height = height; + desc->pixelformat = dest_format; + desc->preallocated[0].pitch = pitch; + desc->preallocated[0].data = data; + + data = NULL; + + cleanup: + if (fp) + fclose (fp); + + if (png_ptr) + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + + if (data) + free (data); + + return ((desc->flags) ? DFB_OK : DFB_FAILURE); +} + +static DFBResult merge_images (DFBSurfaceDescription *images, + int num_images, + DFBSurfaceDescription *dest, + DFBRectangle *rectangles) +{ + DFBSurfaceDescription *image = images; + DFBRectangle *rect = rectangles; + unsigned char *data; + int bpp; + int pitch, i; + + rect->x = 0; + rect->y = 0; + rect->w = image->width; + rect->h = image->height; + + dest->flags = (DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | + DSDESC_PREALLOCATED); + dest->pixelformat = image->pixelformat; + + bpp = DFB_BYTES_PER_PIXEL (dest->pixelformat); + + if (bpp == 1) + dest->width = (rect->w + 3) & ~3; + else + dest->width = rect->w; + + dest->height = rect->h; + + for (i = 1; i < num_images; i++) { + image++; + rect++; + + if (image->pixelformat != dest->pixelformat) + return DFB_INVARG; + + rect->x = dest->width; + rect->y = 0; + rect->w = image->width; + rect->h = image->height; + + if (bpp == 1) + dest->width += (rect->w + 3) & ~3; + else + dest->width += rect->w; + + if (dest->height < rect->h) + dest->height = rect->h; + } + + pitch = (dest->width * bpp + 3) &~ 3; + data = malloc (dest->height * pitch); + if (!data) { + fprintf (stderr, "Failed to allocate %ld bytes.\n", + (long) dest->height * pitch); + return DFB_FAILURE; + } + + + for (i = 0, image = images, rect = rectangles; + i < num_images; + i++, image++, rect++) { + + unsigned char *dest = data + rect->x * bpp; + unsigned char *src = image->preallocated[0].data; + int height = rect->h; + + do { + memcpy (dest, src, rect->w * bpp); + src += image->preallocated[0].pitch; + dest += pitch; + } + while (--height); + } + + dest->preallocated[0].pitch = pitch; + dest->preallocated[0].data = data; + + return DFB_OK; +} + + +typedef struct { + FILE *fp; + int pos; + bool pad; +} CSourceData; + +static inline void save_uchar (CSourceData *csource, + unsigned char d) +{ + if (csource->pos > 70) { + fprintf (csource->fp, "\"\n \""); + + csource->pos = 3; + csource->pad = false; + } + if (d < 33 || d > 126) { + fprintf (csource->fp, "\\%o", d); + csource->pos += 1 + 1 + (d > 7) + (d > 63); + csource->pad = d < 64; + return; + } + if (d == '\\') { + fprintf (csource->fp, "\\\\"); + csource->pos += 2; + } + else if (d == '"') { + fprintf (csource->fp, "\\\""); + csource->pos += 2; + } + else if (csource->pad && d >= '0' && d <= '9') { + fprintf (csource->fp, "\"\"%c", d); + csource->pos += 3; + } + else { + fputc (d, csource->fp); + csource->pos += 1; + } + csource->pad = false; + + return; +} + +static void dump_data(CSourceData *csource, + const char *name, + const unsigned char *data, + unsigned int len) +{ + fprintf (csource->fp, + "static const unsigned char %s_data[] =\n", name); + fprintf (csource->fp, " \""); + + csource->pos = 3; + do + save_uchar (csource, *data++); + while (--len); + + fprintf (csource->fp, "\";\n\n"); +} + +static DFBResult dump_raw_data(const char *name, + const unsigned char *data, + unsigned int len) +{ + CSourceData csource = { stdout, 0, 0 }; + char *vname = variable_name (name); + + if (!data || !len) + return DFB_INVARG; + + fprintf (csource.fp, + "/* DirectFB raw data dump created by directfb-csource %s */\n\n", + DIRECTFB_VERSION); + + dump_data(&csource, vname, data, len); + + free (vname); + + return DFB_OK; +} + + +static DFBResult dump_image (const char *name, + DFBSurfaceDescription *desc, + DFBColor *palette, + int palette_size) +{ + CSourceData csource = { stdout, 0, 0 }; + const char *format = NULL; + char *vname = variable_name (name); + unsigned char *data; + unsigned long len; + int i; + + if (desc && + desc->flags != (DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | + DSDESC_PREALLOCATED)) + return DFB_INVARG; + + for (i = 0; i < n_pixelformats && !format; i++) + if (pixelformats[i].format == desc->pixelformat) + format = pixelformats[i].name; + + if (!format) + return DFB_INVARG; + + data = (unsigned char *) desc->preallocated[0].data; + len = desc->height * desc->preallocated[0].pitch; + + if (!len) + return DFB_INVARG; + + /* dump comment */ + fprintf (csource.fp, + "/* DirectFB surface dump created by directfb-csource %s */\n\n", + DIRECTFB_VERSION); + + /* dump data */ + dump_data(&csource, vname, data, len); + + /* dump palette */ + if (palette_size > 0) { + fprintf (csource.fp, + "static const DFBColor %s_palette[%d] = {\n", vname, palette_size); + for (i = 0; i < palette_size; i++) + fprintf (csource.fp, + " { 0x%02x, 0x%02x, 0x%02x, 0x%02x }%c\n", + palette[i].a, palette[i].r, palette[i].g, palette[i].b, + i+1 < palette_size ? ',' : ' '); + fprintf (csource.fp, "};\n\n"); + } + + /* dump description */ + fprintf (csource.fp, + "static const DFBSurfaceDescription %s_desc = {\n", vname); + fprintf (csource.fp, + " flags : DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT |\n" + " DSDESC_PREALLOCATED"); + if (palette_size > 0) + fprintf (csource.fp, " | DSDESC_PALETTE"); + fprintf (csource.fp, ",\n"); + fprintf (csource.fp, + " width : %d,\n", desc->width); + fprintf (csource.fp, + " height : %d,\n", desc->height); + fprintf (csource.fp, + " pixelformat : DSPF_%s,\n", format); + fprintf (csource.fp, + " preallocated : {{ data : (void *) %s_data,\n", vname); + fprintf (csource.fp, + " pitch : %d }}", desc->preallocated[0].pitch); + if (palette_size > 0) { + fprintf (csource.fp, ",\n"); + fprintf (csource.fp, + " palette : { entries : %s_palette,\n", vname); + fprintf (csource.fp, + " size : %d }", palette_size); + } + fprintf (csource.fp, "\n};\n\n"); + + free (vname); + + return DFB_OK; +} + +static DFBResult dump_rectangles (const char *name, + DFBRectangle *rectangles, + const char **names, + int num_rects) +{ + DFBRectangle *rect; + const char *blanks = " "; + char *vname = variable_name (name); + FILE *fp = stdout; + int len, i; + + if (num_rects < 1) + return DFB_INVARG; + + fprintf (fp, + "/* DirectFB multi-surface dump created by directfb-csource %s */\n\n", + DIRECTFB_VERSION); + + fprintf (fp, + "static const struct {\n" + " const char *name;\n" + " DFBRectangle rect;\n" + "} %s[] = {\n", vname); + + for (i = 0, len = 0; i < num_rects; i++) + len = MAX (len, strlen (names[i])); + + len = len + 4 - strlen (blanks); + + for (i = 0, rect = rectangles; i < num_rects; i++, rect++) { + + char *v = base_name (names[i]); + + if (i) + fprintf (fp, ",\n"); + + if (len < 0) { + int l = fprintf (fp, " { \"%s\", ", v); + + fprintf (fp, blanks - len + l); + fprintf (fp, "{ x : %4d, y : %4d, w : %4d, h : %4d } }", + rect->x, rect->y, rect->w, rect->h); + } + else { + fprintf (fp, + " { \"%s\",\n" + " { x : %4d, y : %4d, w : %4d, h : %4d } }", + v, rect->x, rect->y, rect->w, rect->h); + } + + free (v); + } + fprintf (fp, "\n};\n\n"); + + free (vname); + + return DFB_OK; +} + +static char * +variable_name (const char *name) +{ + char *vname = strdup (name); + char *v = vname; + + while (DFB_TRUE) { + switch (*v) { + case 0: + return vname; + case 'a'...'z': + case 'A'...'Z': + case '0'...'9': + case '_': + break; + default: + *v = '_'; + } + v++; + } +} + +static char * +base_name (const char *name) +{ + char *vname = strdup (name); + char *v = vname; + + while (DFB_TRUE) { + switch (*v) { + case '.': + *v = 0; + case 0: + return vname; + default: + break; + } + v++; + } +} diff -Naur DirectFB-1.2.10/tools/mkdfiff.c DirectFB-1.2.10-magellan/tools/mkdfiff.c --- DirectFB-1.2.10/tools/mkdfiff.c 2009-08-27 21:54:18.000000000 +0200 +++ DirectFB-1.2.10-magellan/tools/mkdfiff.c 2011-03-12 00:17:49.000000000 +0100 @@ -97,7 +97,7 @@ if (!png_ptr) goto cleanup; - if (setjmp (png_ptr->jmpbuf)) { + if (setjmp (png_jmpbuf (png_ptr))) { if (desc->preallocated[0].data) { free (desc->preallocated[0].data); desc->preallocated[0].data = NULL;