Files
directfb/tools/directfb-csource.c
2013-07-05 16:51:54 +02:00

949 lines
30 KiB
C

/*
(c) Copyright 2012-2013 DirectFB integrated media GmbH
(c) Copyright 2001-2013 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 <dok@directfb.org>,
Andreas Shimokawa <andi@directfb.org>,
Marek Pikarski <mass@directfb.org>,
Sven Neumann <neo@directfb.org>,
Ville Syrjälä <syrjala@sci.fi> and
Claudio Ciccani <klan@users.sf.net>.
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 <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <png.h>
#include <directfb.h>
#include <direct/types.h>
#include <direct/util.h>
#include <gfx/convert.h>
#define DFB_DITHER565 DFB_DITHER_ADVANCED
#include <misc/dither565.h>
static struct {
DFBSurfacePixelFormat format;
const char *name;
} pixelformats[] = {
{ DSPF_ARGB, "ARGB" },
{ DSPF_ARGB1555, "ARGB1555" },
{ DSPF_RGBA5551, "RGBA5551" },
{ DSPF_ARGB2554, "ARGB2554" },
{ DSPF_ARGB4444, "ARGB4444" },
{ DSPF_ARGB8565, "ARGB8565" },
{ 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,
const DFBColor *transparent,
DFBSurfacePixelFormat rgbformat,
bool dither565);
static void dither_rgb16 (const u32 *src,
u16 *dest,
int y,
int width);
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;
bool rawmode = 0;
bool dither565 = 0;
DFBColor *transparent = NULL;
int res;
/* 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 (strcmp (arg, "dither-rgb16") == 0) {
dither565 = 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;
}
if (strncmp (arg, "transparent=", 12) == 0 && !transparent) {
char *error;
u32 argb = strtoul (arg + 12, &error, 16);
if (! error) {
transparent = alloca(sizeof (DFBColor));
transparent->b = argb & 0xFF;
argb >>= 8;
transparent->g = argb & 0xFF;
argb >>= 8;
transparent->r = argb & 0xFF;
argb >>= 8;
transparent->a = argb & 0xFF;
}
if (transparent)
continue;
}
}
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)
{
res = fread(data, statbuf.st_size, 1, f);
(void)res;
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, transparent,
rgbformat, dither565) != 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, transparent,
rgbformat, dither565) != 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] <imagefile>\n", prg_name);
fprintf (stderr, " --name=<identifer> specifies variable name\n");
fprintf (stderr, " --format=<identifer> specifies surface format\n");
fprintf (stderr, " --rgbformat=<identifer> 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, " --dither-rgb16 dither images rendered to RGB16 surfaces\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,
const DFBColor *transparent,
DFBSurfacePixelFormat rgbformat,
bool dither565)
{
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 info_palette;
int num_palette;
png_get_PLTE(png_ptr,info_ptr,&info_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 = info_palette[i].red;
palette[i].g = info_palette[i].green;
palette[i].b = info_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 %lu bytes.\n", (unsigned long)(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;
/* replace color in completely transparent pixels */
if (transparent && DFB_PIXELFORMAT_HAS_ALPHA(src_format)) {
unsigned char *row;
int h;
for (row = data, h = height; h; h--, row += pitch) {
u32 *pixel;
int w;
for (pixel = (u32 *) row, w = width; w; w--, pixel++) {
if ((*pixel & 0xff000000) == 0x0)
*pixel = dfb_color_to_argb (transparent);
}
}
}
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 %lu bytes.\n", (unsigned long)(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)
if (dither565)
dither_rgb16 ((u32 *) s, (u16 *) d, height - h, width);
else
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_RGBA5551:
for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
dfb_argb_to_rgba5551 ((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_ARGB8565:
for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
dfb_argb_to_argb8565 ((u32 *) s, (u8 *) 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;
}
static void
dither_rgb16 (const u32 *src, u16 *dest, int y, int width)
{
const u32 *dm = DM_565 + ((y & (DM_565_HEIGHT - 1)) << DM_565_WIDTH_SHIFT);
int x;
for (x = 0; x < width; x++) {
u32 rgb = ((src[x] & 0xFF) |
(src[x] & 0xFF00) << 2 |
(src[x] & 0xFF0000) << 4);
rgb += dm[x & (DM_565_WIDTH - 1)];
rgb += (0x10040100
- ((rgb & 0x1e0001e0) >> 5)
- ((rgb & 0x00070000) >> 6));
dest[x] = (((rgb & 0x0f800000) >> 12) |
((rgb & 0x0003f000) >> 7) |
((rgb & 0x000000f8) >> 3));
}
}
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, "%s", 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++;
}
}