mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-14 15:42:28 -05:00
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
This commit is contained in:
parent
01c6dcf6c7
commit
a855d62025
994 changed files with 336924 additions and 15 deletions
824
apps/plugins/sdl/SDL_image/IMG_xcf.c
Normal file
824
apps/plugins/sdl/SDL_image/IMG_xcf.c
Normal file
|
|
@ -0,0 +1,824 @@
|
|||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a XCF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XCF
|
||||
|
||||
#if DEBUG
|
||||
static char prop_names [][30] = {
|
||||
"end",
|
||||
"colormap",
|
||||
"active_layer",
|
||||
"active_channel",
|
||||
"selection",
|
||||
"floating_selection",
|
||||
"opacity",
|
||||
"mode",
|
||||
"visible",
|
||||
"linked",
|
||||
"preserve_transparency",
|
||||
"apply_mask",
|
||||
"edit_mask",
|
||||
"show_mask",
|
||||
"show_masked",
|
||||
"offsets",
|
||||
"color",
|
||||
"compression",
|
||||
"guides",
|
||||
"resolution",
|
||||
"tattoo",
|
||||
"parasites",
|
||||
"unit",
|
||||
"paths",
|
||||
"user_unit"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROP_END = 0,
|
||||
PROP_COLORMAP = 1,
|
||||
PROP_ACTIVE_LAYER = 2,
|
||||
PROP_ACTIVE_CHANNEL = 3,
|
||||
PROP_SELECTION = 4,
|
||||
PROP_FLOATING_SELECTION = 5,
|
||||
PROP_OPACITY = 6,
|
||||
PROP_MODE = 7,
|
||||
PROP_VISIBLE = 8,
|
||||
PROP_LINKED = 9,
|
||||
PROP_PRESERVE_TRANSPARENCY = 10,
|
||||
PROP_APPLY_MASK = 11,
|
||||
PROP_EDIT_MASK = 12,
|
||||
PROP_SHOW_MASK = 13,
|
||||
PROP_SHOW_MASKED = 14,
|
||||
PROP_OFFSETS = 15,
|
||||
PROP_COLOR = 16,
|
||||
PROP_COMPRESSION = 17,
|
||||
PROP_GUIDES = 18,
|
||||
PROP_RESOLUTION = 19,
|
||||
PROP_TATTOO = 20,
|
||||
PROP_PARASITES = 21,
|
||||
PROP_UNIT = 22,
|
||||
PROP_PATHS = 23,
|
||||
PROP_USER_UNIT = 24
|
||||
} xcf_prop_type;
|
||||
|
||||
typedef enum {
|
||||
COMPR_NONE = 0,
|
||||
COMPR_RLE = 1,
|
||||
COMPR_ZLIB = 2,
|
||||
COMPR_FRACTAL = 3
|
||||
} xcf_compr_type;
|
||||
|
||||
typedef enum {
|
||||
IMAGE_RGB = 0,
|
||||
IMAGE_GREYSCALE = 1,
|
||||
IMAGE_INDEXED = 2
|
||||
} xcf_image_type;
|
||||
|
||||
typedef struct {
|
||||
Uint32 id;
|
||||
Uint32 length;
|
||||
union {
|
||||
struct {
|
||||
Uint32 num;
|
||||
char * cmap;
|
||||
} colormap; // 1
|
||||
struct {
|
||||
Uint32 drawable_offset;
|
||||
} floating_selection; // 5
|
||||
Sint32 opacity;
|
||||
Sint32 mode;
|
||||
int visible;
|
||||
int linked;
|
||||
int preserve_transparency;
|
||||
int apply_mask;
|
||||
int show_mask;
|
||||
struct {
|
||||
Sint32 x;
|
||||
Sint32 y;
|
||||
} offset;
|
||||
unsigned char color [3];
|
||||
Uint8 compression;
|
||||
struct {
|
||||
Sint32 x;
|
||||
Sint32 y;
|
||||
} resolution;
|
||||
struct {
|
||||
char * name;
|
||||
Uint32 flags;
|
||||
Uint32 size;
|
||||
char * data;
|
||||
} parasite;
|
||||
} data;
|
||||
} xcf_prop;
|
||||
|
||||
typedef struct {
|
||||
char sign [14];
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Sint32 image_type;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 * layer_file_offsets;
|
||||
Uint32 * channel_file_offsets;
|
||||
|
||||
xcf_compr_type compr;
|
||||
Uint32 cm_num;
|
||||
unsigned char * cm_map;
|
||||
} xcf_header;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Sint32 layer_type;
|
||||
char * name;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 hierarchy_file_offset;
|
||||
Uint32 layer_mask_offset;
|
||||
|
||||
Uint32 offset_x;
|
||||
Uint32 offset_y;
|
||||
int visible;
|
||||
} xcf_layer;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
char * name;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 hierarchy_file_offset;
|
||||
|
||||
Uint32 color;
|
||||
Uint32 opacity;
|
||||
int selection;
|
||||
int visible;
|
||||
} xcf_channel;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Uint32 bpp;
|
||||
|
||||
Uint32 * level_file_offsets;
|
||||
} xcf_hierarchy;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
|
||||
Uint32 * tile_file_offsets;
|
||||
} xcf_level;
|
||||
|
||||
typedef unsigned char * xcf_tile;
|
||||
|
||||
typedef unsigned char * (* load_tile_type) (SDL_RWops *, Uint32, int, int, int);
|
||||
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXCF(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_XCF;
|
||||
char magic[14];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XCF = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if (strncmp(magic, "gimp xcf ", 9) == 0) {
|
||||
is_XCF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XCF);
|
||||
}
|
||||
|
||||
static char * read_string (SDL_RWops * src) {
|
||||
Uint32 tmp;
|
||||
char * data;
|
||||
|
||||
tmp = SDL_ReadBE32 (src);
|
||||
if (tmp > 0) {
|
||||
data = (char *) malloc (sizeof (char) * tmp);
|
||||
SDL_RWread (src, data, tmp, 1);
|
||||
}
|
||||
else {
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static Uint32 Swap32 (Uint32 v) {
|
||||
return
|
||||
((v & 0x000000FF) << 16)
|
||||
| ((v & 0x0000FF00))
|
||||
| ((v & 0x00FF0000) >> 16)
|
||||
| ((v & 0xFF000000));
|
||||
}
|
||||
|
||||
static void xcf_read_property (SDL_RWops * src, xcf_prop * prop) {
|
||||
prop->id = SDL_ReadBE32 (src);
|
||||
prop->length = SDL_ReadBE32 (src);
|
||||
|
||||
#if DEBUG
|
||||
printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length);
|
||||
#endif
|
||||
|
||||
switch (prop->id) {
|
||||
case PROP_COLORMAP:
|
||||
prop->data.colormap.num = SDL_ReadBE32 (src);
|
||||
prop->data.colormap.cmap = (char *) malloc (sizeof (char) * prop->data.colormap.num * 3);
|
||||
SDL_RWread (src, prop->data.colormap.cmap, prop->data.colormap.num*3, 1);
|
||||
break;
|
||||
|
||||
case PROP_OFFSETS:
|
||||
prop->data.offset.x = SDL_ReadBE32 (src);
|
||||
prop->data.offset.y = SDL_ReadBE32 (src);
|
||||
break;
|
||||
case PROP_OPACITY:
|
||||
prop->data.opacity = SDL_ReadBE32 (src);
|
||||
break;
|
||||
case PROP_COMPRESSION:
|
||||
case PROP_COLOR:
|
||||
SDL_RWread (src, &prop->data, prop->length, 1);
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
prop->data.visible = SDL_ReadBE32 (src);
|
||||
break;
|
||||
default:
|
||||
// SDL_RWread (src, &prop->data, prop->length, 1);
|
||||
SDL_RWseek (src, prop->length, RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_xcf_header (xcf_header * h) {
|
||||
if (h->cm_num)
|
||||
free (h->cm_map);
|
||||
|
||||
free (h);
|
||||
}
|
||||
|
||||
static xcf_header * read_xcf_header (SDL_RWops * src) {
|
||||
xcf_header * h;
|
||||
xcf_prop prop;
|
||||
|
||||
h = (xcf_header *) malloc (sizeof (xcf_header));
|
||||
SDL_RWread (src, h->sign, 14, 1);
|
||||
h->width = SDL_ReadBE32 (src);
|
||||
h->height = SDL_ReadBE32 (src);
|
||||
h->image_type = SDL_ReadBE32 (src);
|
||||
|
||||
h->properties = NULL;
|
||||
h->compr = COMPR_NONE;
|
||||
h->cm_num = 0;
|
||||
h->cm_map = NULL;
|
||||
|
||||
// Just read, don't save
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
if (prop.id == PROP_COMPRESSION)
|
||||
h->compr = prop.data.compression;
|
||||
else if (prop.id == PROP_COLORMAP) {
|
||||
// unused var: int i;
|
||||
|
||||
h->cm_num = prop.data.colormap.num;
|
||||
h->cm_map = (unsigned char *) malloc (sizeof (unsigned char) * 3 * h->cm_num);
|
||||
memcpy (h->cm_map, prop.data.colormap.cmap, 3*sizeof (char)*h->cm_num);
|
||||
free (prop.data.colormap.cmap);
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void free_xcf_layer (xcf_layer * l) {
|
||||
free (l->name);
|
||||
free (l);
|
||||
}
|
||||
|
||||
static xcf_layer * read_xcf_layer (SDL_RWops * src) {
|
||||
xcf_layer * l;
|
||||
xcf_prop prop;
|
||||
|
||||
l = (xcf_layer *) malloc (sizeof (xcf_layer));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
l->layer_type = SDL_ReadBE32 (src);
|
||||
|
||||
l->name = read_string (src);
|
||||
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
if (prop.id == PROP_OFFSETS) {
|
||||
l->offset_x = prop.data.offset.x;
|
||||
l->offset_y = prop.data.offset.y;
|
||||
} else if (prop.id == PROP_VISIBLE) {
|
||||
l->visible = prop.data.visible ? 1 : 0;
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
l->hierarchy_file_offset = SDL_ReadBE32 (src);
|
||||
l->layer_mask_offset = SDL_ReadBE32 (src);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_channel (xcf_channel * c) {
|
||||
free (c->name);
|
||||
free (c);
|
||||
}
|
||||
|
||||
static xcf_channel * read_xcf_channel (SDL_RWops * src) {
|
||||
xcf_channel * l;
|
||||
xcf_prop prop;
|
||||
|
||||
l = (xcf_channel *) malloc (sizeof (xcf_channel));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
|
||||
l->name = read_string (src);
|
||||
|
||||
l->selection = 0;
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
switch (prop.id) {
|
||||
case PROP_OPACITY:
|
||||
l->opacity = prop.data.opacity << 24;
|
||||
break;
|
||||
case PROP_COLOR:
|
||||
l->color = ((Uint32) prop.data.color[0] << 16)
|
||||
| ((Uint32) prop.data.color[1] << 8)
|
||||
| ((Uint32) prop.data.color[2]);
|
||||
break;
|
||||
case PROP_SELECTION:
|
||||
l->selection = 1;
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
l->visible = prop.data.visible ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
l->hierarchy_file_offset = SDL_ReadBE32 (src);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_hierarchy (xcf_hierarchy * h) {
|
||||
free (h->level_file_offsets);
|
||||
free (h);
|
||||
}
|
||||
|
||||
static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) {
|
||||
xcf_hierarchy * h;
|
||||
int i;
|
||||
|
||||
h = (xcf_hierarchy *) malloc (sizeof (xcf_hierarchy));
|
||||
h->width = SDL_ReadBE32 (src);
|
||||
h->height = SDL_ReadBE32 (src);
|
||||
h->bpp = SDL_ReadBE32 (src);
|
||||
|
||||
h->level_file_offsets = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
h->level_file_offsets = (Uint32 *) realloc (h->level_file_offsets, sizeof (Uint32) * (i+1));
|
||||
h->level_file_offsets [i] = SDL_ReadBE32 (src);
|
||||
} while (h->level_file_offsets [i++]);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void free_xcf_level (xcf_level * l) {
|
||||
free (l->tile_file_offsets);
|
||||
free (l);
|
||||
}
|
||||
|
||||
static xcf_level * read_xcf_level (SDL_RWops * src) {
|
||||
xcf_level * l;
|
||||
int i;
|
||||
|
||||
l = (xcf_level *) malloc (sizeof (xcf_level));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
|
||||
l->tile_file_offsets = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
l->tile_file_offsets = (Uint32 *) realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1));
|
||||
l->tile_file_offsets [i] = SDL_ReadBE32 (src);
|
||||
} while (l->tile_file_offsets [i++]);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_tile (unsigned char * t) {
|
||||
free (t);
|
||||
}
|
||||
|
||||
static unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
|
||||
unsigned char * load;
|
||||
|
||||
load = (unsigned char *) malloc (len); // expect this is okay
|
||||
SDL_RWread (src, load, len, 1);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
|
||||
unsigned char * load, * t, * data, * d;
|
||||
Uint32 reallen;
|
||||
int i, size, count, j, length;
|
||||
unsigned char val;
|
||||
|
||||
t = load = (unsigned char *) malloc (len);
|
||||
reallen = SDL_RWread (src, t, 1, len);
|
||||
|
||||
data = (unsigned char *) malloc (x*y*bpp);
|
||||
for (i = 0; i < bpp; i++) {
|
||||
d = data + i;
|
||||
size = x*y;
|
||||
count = 0;
|
||||
|
||||
while (size > 0) {
|
||||
val = *t++;
|
||||
|
||||
length = val;
|
||||
if (length >= 128) {
|
||||
length = 255 - (length - 1);
|
||||
if (length == 128) {
|
||||
length = (*t << 8) + t[1];
|
||||
t += 2;
|
||||
}
|
||||
|
||||
count += length;
|
||||
size -= length;
|
||||
|
||||
while (length-- > 0) {
|
||||
*d = *t++;
|
||||
d += bpp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
length += 1;
|
||||
if (length == 128) {
|
||||
length = (*t << 8) + t[1];
|
||||
t += 2;
|
||||
}
|
||||
|
||||
count += length;
|
||||
size -= length;
|
||||
|
||||
val = *t++;
|
||||
|
||||
for (j = 0; j < length; j++) {
|
||||
*d = val;
|
||||
d += bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (load);
|
||||
return (data);
|
||||
}
|
||||
|
||||
static Uint32 rgb2grey (Uint32 a) {
|
||||
Uint8 l;
|
||||
l = 0.2990 * ((a && 0x00FF0000) >> 16)
|
||||
+ 0.5870 * ((a && 0x0000FF00) >> 8)
|
||||
+ 0.1140 * ((a && 0x000000FF));
|
||||
|
||||
return (l << 16) | (l << 8) | l;
|
||||
}
|
||||
|
||||
static void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) {
|
||||
Uint32 c = 0;
|
||||
|
||||
switch (itype) {
|
||||
case IMAGE_RGB:
|
||||
case IMAGE_INDEXED:
|
||||
c = opacity | color;
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
c = opacity | rgb2grey (color);
|
||||
break;
|
||||
}
|
||||
SDL_FillRect (surf, NULL, c);
|
||||
}
|
||||
|
||||
static int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) {
|
||||
xcf_hierarchy * hierarchy;
|
||||
xcf_level * level;
|
||||
unsigned char * tile;
|
||||
Uint8 * p8;
|
||||
Uint16 * p16;
|
||||
Uint32 * p;
|
||||
int x, y, tx, ty, ox, oy, i, j;
|
||||
Uint32 *row;
|
||||
|
||||
SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET);
|
||||
hierarchy = read_xcf_hierarchy (src);
|
||||
|
||||
level = NULL;
|
||||
for (i = 0; hierarchy->level_file_offsets [i]; i++) {
|
||||
SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET);
|
||||
level = read_xcf_level (src);
|
||||
|
||||
ty = tx = 0;
|
||||
for (j = 0; level->tile_file_offsets [j]; j++) {
|
||||
SDL_RWseek (src, level->tile_file_offsets [j], RW_SEEK_SET);
|
||||
ox = tx+64 > level->width ? level->width % 64 : 64;
|
||||
oy = ty+64 > level->height ? level->height % 64 : 64;
|
||||
|
||||
if (level->tile_file_offsets [j+1]) {
|
||||
tile = load_tile
|
||||
(src,
|
||||
level->tile_file_offsets [j+1] - level->tile_file_offsets [j],
|
||||
hierarchy->bpp,
|
||||
ox, oy);
|
||||
}
|
||||
else {
|
||||
tile = load_tile
|
||||
(src,
|
||||
ox*oy*6,
|
||||
hierarchy->bpp,
|
||||
ox, oy);
|
||||
}
|
||||
|
||||
p8 = tile;
|
||||
p16 = (Uint16 *) p8;
|
||||
p = (Uint32 *) p8;
|
||||
for (y=ty; y < ty+oy; y++) {
|
||||
row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4);
|
||||
switch (hierarchy->bpp) {
|
||||
case 4:
|
||||
for (x=tx; x < tx+ox; x++)
|
||||
*row++ = Swap32 (*p++);
|
||||
break;
|
||||
case 3:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = 0xFF000000;
|
||||
*row |= ((Uint32) *(p8++) << 16);
|
||||
*row |= ((Uint32) *(p8++) << 8);
|
||||
*row |= ((Uint32) *(p8++) << 0);
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
case 2: // Indexed/Greyscale + Alpha
|
||||
switch (head->image_type) {
|
||||
case IMAGE_INDEXED:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = ((Uint32) (head->cm_map [*p8*3]) << 16);
|
||||
*row |= ((Uint32) (head->cm_map [*p8*3+1]) << 8);
|
||||
*row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0);
|
||||
*row |= ((Uint32) *p8++ << 24);;
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = ((Uint32) *p8 << 16);
|
||||
*row |= ((Uint32) *p8 << 8);
|
||||
*row |= ((Uint32) *p8++ << 0);
|
||||
*row |= ((Uint32) *p8++ << 24);;
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 1: // Indexed/Greyscale
|
||||
switch (head->image_type) {
|
||||
case IMAGE_INDEXED:
|
||||
for (x = tx; x < tx+ox; x++) {
|
||||
*row++ = 0xFF000000
|
||||
| ((Uint32) (head->cm_map [*p8*3]) << 16)
|
||||
| ((Uint32) (head->cm_map [*p8*3+1]) << 8)
|
||||
| ((Uint32) (head->cm_map [*p8*3+2]) << 0);
|
||||
p8++;
|
||||
}
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row++ = 0xFF000000
|
||||
| (((Uint32) (*p8)) << 16)
|
||||
| (((Uint32) (*p8)) << 8)
|
||||
| (((Uint32) (*p8)) << 0);
|
||||
++p8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
tx += 64;
|
||||
if (tx >= level->width) {
|
||||
tx = 0;
|
||||
ty += 64;
|
||||
}
|
||||
if (ty >= level->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
free_xcf_tile (tile);
|
||||
}
|
||||
free_xcf_level (level);
|
||||
}
|
||||
|
||||
free_xcf_hierarchy (hierarchy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface, *lays;
|
||||
xcf_header * head;
|
||||
xcf_layer * layer;
|
||||
xcf_channel ** channel;
|
||||
int chnls, i, offsets;
|
||||
Uint32 offset, fp;
|
||||
|
||||
unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int);
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Initialize the data we will clean up when we're done */
|
||||
surface = NULL;
|
||||
|
||||
head = read_xcf_header (src);
|
||||
|
||||
switch (head->compr) {
|
||||
case COMPR_NONE:
|
||||
load_tile = load_xcf_tile_none;
|
||||
break;
|
||||
case COMPR_RLE:
|
||||
load_tile = load_xcf_tile_rle;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unsupported Compression.\n");
|
||||
free_xcf_header (head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the surface of the appropriate type */
|
||||
surface = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if ( surface == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
head->layer_file_offsets = NULL;
|
||||
offsets = 0;
|
||||
|
||||
while ((offset = SDL_ReadBE32 (src))) {
|
||||
head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
|
||||
head->layer_file_offsets [offsets] = offset;
|
||||
offsets++;
|
||||
}
|
||||
fp = SDL_RWtell (src);
|
||||
|
||||
lays = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if ( lays == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Blit layers backwards, because Gimp saves them highest first
|
||||
for (i = offsets; i > 0; i--) {
|
||||
SDL_Rect rs, rd;
|
||||
SDL_RWseek (src, head->layer_file_offsets [i-1], RW_SEEK_SET);
|
||||
|
||||
layer = read_xcf_layer (src);
|
||||
do_layer_surface (lays, src, head, layer, load_tile);
|
||||
rs.x = 0;
|
||||
rs.y = 0;
|
||||
rs.w = layer->width;
|
||||
rs.h = layer->height;
|
||||
rd.x = layer->offset_x;
|
||||
rd.y = layer->offset_y;
|
||||
rd.w = layer->width;
|
||||
rd.h = layer->height;
|
||||
|
||||
if (layer->visible)
|
||||
SDL_BlitSurface (lays, &rs, surface, &rd);
|
||||
free_xcf_layer (layer);
|
||||
}
|
||||
|
||||
SDL_FreeSurface (lays);
|
||||
|
||||
SDL_RWseek (src, fp, RW_SEEK_SET);
|
||||
|
||||
// read channels
|
||||
channel = NULL;
|
||||
chnls = 0;
|
||||
while ((offset = SDL_ReadBE32 (src))) {
|
||||
channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1));
|
||||
fp = SDL_RWtell (src);
|
||||
SDL_RWseek (src, offset, RW_SEEK_SET);
|
||||
channel [chnls++] = (read_xcf_channel (src));
|
||||
SDL_RWseek (src, fp, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
if (chnls) {
|
||||
SDL_Surface * chs;
|
||||
|
||||
chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if (chs == NULL) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < chnls; i++) {
|
||||
// printf ("CNLBLT %i\n", i);
|
||||
if (!channel [i]->selection && channel [i]->visible) {
|
||||
create_channel_surface (chs, head->image_type, channel [i]->color, channel [i]->opacity);
|
||||
SDL_BlitSurface (chs, NULL, surface, NULL);
|
||||
}
|
||||
free_xcf_channel (channel [i]);
|
||||
}
|
||||
|
||||
SDL_FreeSurface (chs);
|
||||
}
|
||||
|
||||
done:
|
||||
free_xcf_header (head);
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXCF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XCF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XCF */
|
||||
Loading…
Add table
Add a link
Reference in a new issue