e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
bc73c61999-04-11Per Hedbor #include "global.h"
d9db231999-05-30Mirar (Pontus Hagland) #include "image_machine.h"
bc73c61999-04-11Per Hedbor  #include "pike_macros.h" #include "object.h" #include "module_support.h" #include "interpret.h" #include "svalue.h" #include "threads.h" #include "mapping.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
bc73c61999-04-11Per Hedbor #include "stralloc.h" #include "builtin_functions.h"
c9804a2000-10-08Per Hedbor #include "bignum.h"
68ec3f2014-08-18Martin Nilsson #include "pike_types.h"
9d1f542017-01-25Henrik Grubbström (Grubba) #include "sprintf.h"
bc73c61999-04-11Per Hedbor  #include "image.h" #include "colortable.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
531c172002-05-11Martin Nilsson #define sp Pike_sp #define fp Pike_fp
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
bc73c61999-04-11Per Hedbor extern struct program *image_colortable_program; extern struct program *image_program; /* **! module Image **! submodule XCF **! */
6e6c451999-04-12Per Hedbor #define TILE_WIDTH 64 #define TILE_HEIGHT 64
01a9572000-02-03Henrik Grubbström (Grubba) #define STRING(X) static struct pike_string *s_##X
bc73c61999-04-11Per Hedbor #include "xcf_constant_strings.h" #undef STRING struct buffer {
c9804a2000-10-08Per Hedbor  struct pike_string *s;
bc73c61999-04-11Per Hedbor  unsigned char *str;
279ca52008-01-22Henrik Grubbström (Grubba)  size_t len;
bc73c61999-04-11Per Hedbor };
c9804a2000-10-08Per Hedbor struct substring { struct pike_string *s;
58dcfe2000-10-19Henrik Grubbström (Grubba)  ptrdiff_t offset; ptrdiff_t len;
c9804a2000-10-08Per Hedbor }; static struct program *substring_program;
7c72e02017-12-12Martin Nilsson #undef SS
c9804a2000-10-08Per Hedbor #define SS(X) ((struct substring*)X->storage) static void f_substring_cast( INT32 args ) {
68ec3f2014-08-18Martin Nilsson  struct pike_string *type = sp[-args].u.string; pop_n_elems(args); /* type have at least one more reference. */ if( type == literal_string_string ) { struct substring *s = SS(fp->current_object); push_string( make_shared_binary_string( (((char *)s->s->str)+s->offset), s->len ) ); } else push_undefined();
c9804a2000-10-08Per Hedbor } static void f_substring_index( INT32 args ) {
986b522001-03-17Henrik Grubbström (Grubba)  ptrdiff_t i = sp[-1].u.integer;
c9804a2000-10-08Per Hedbor  struct substring *s = SS(fp->current_object); pop_n_elems( args ); if( i < 0 ) i = s->len + i;
ac9fc22000-10-20Henrik Grubbström (Grubba)  if( i >= s->len ) {
cc7cf42015-10-14Martin Nilsson  Pike_error("Index out of bounds, %ld > %ld\n", i, (long)s->len-1 );
ac9fc22000-10-20Henrik Grubbström (Grubba)  }
c9804a2000-10-08Per Hedbor  push_int( ((unsigned char *)s->s->str)[s->offset+i] ); } static void f_substring__sprintf( INT32 args ) { int x; struct substring *s = SS(fp->current_object); if (args != 2 )
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("_sprintf",2);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-2]) != T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("_sprintf",0,"int");
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-1]) != T_MAPPING)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("_sprintf",1,"mapping");
c9804a2000-10-08Per Hedbor  x = sp[-2].u.integer; pop_n_elems( args ); switch( x ) { case 't':
5e9fc02015-08-18Per Hedbor  push_static_text("SubString");
c9804a2000-10-08Per Hedbor  return; case 'O':
5e9fc02015-08-18Per Hedbor  push_static_text("SubString( %O /* [+%d .. %d] */ )" );
6a932b2014-08-18Martin Nilsson  ref_push_string(literal_string_string); f_substring_cast( 1 );
c9804a2000-10-08Per Hedbor 
986b522001-03-17Henrik Grubbström (Grubba)  push_int64( s->len ); push_int64( s->offset );
c9804a2000-10-08Per Hedbor  f_sprintf( 4 ); return;
13670c2015-05-25Martin Nilsson  default:
c9804a2000-10-08Per Hedbor  push_int(0); return; } }
74dfe82012-12-30Jonas Walldén static void f_substring_get_int( INT32 UNUSED(args) )
c9804a2000-10-08Per Hedbor { struct substring *s = SS(fp->current_object); int res; unsigned char *p; int x = sp[-1].u.integer; if( x > s->len>>2 )
6de0852004-01-23Martin Nilsson  Pike_error("Index %d out of range.\n", x );
c9804a2000-10-08Per Hedbor 
dc82262002-08-13Henrik Grubbström (Grubba)  p = ((unsigned char *)s->s->str) + s->offset + x*4;
c9804a2000-10-08Per Hedbor  res = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; push_int( res ); }
74dfe82012-12-30Jonas Walldén static void f_substring_get_uint( INT32 UNUSED(args) )
c9804a2000-10-08Per Hedbor { struct substring *s = SS(fp->current_object); unsigned int res; unsigned char *p; int x = sp[-1].u.integer; if( x > s->len>>2 )
6de0852004-01-23Martin Nilsson  Pike_error("Index %d out of range.\n", x );
c9804a2000-10-08Per Hedbor 
dc82262002-08-13Henrik Grubbström (Grubba)  p = ((unsigned char *)s->s->str) + s->offset + x*4;
c9804a2000-10-08Per Hedbor  res = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; push_int64( res ); }
74dfe82012-12-30Jonas Walldén static void f_substring_get_ushort( INT32 UNUSED(args) )
c9804a2000-10-08Per Hedbor { struct substring *s = SS(fp->current_object); unsigned short res; unsigned char *p; int x = sp[-1].u.integer; if( x > s->len>>1 )
6de0852004-01-23Martin Nilsson  Pike_error("Index %d out of range.\n", x );
c9804a2000-10-08Per Hedbor 
dc82262002-08-13Henrik Grubbström (Grubba)  p = ((unsigned char *)s->s->str) + s->offset + x*2;
c9804a2000-10-08Per Hedbor  res = (p[2]<<8) | p[3]; push_int( res ); }
74dfe82012-12-30Jonas Walldén static void f_substring_get_short( INT32 UNUSED(args) )
c9804a2000-10-08Per Hedbor { struct substring *s = SS(fp->current_object); short res; unsigned char *p; int x = sp[-1].u.integer; if( x > s->len>>1 )
6de0852004-01-23Martin Nilsson  Pike_error("Index %d out of range.\n", x );
c9804a2000-10-08Per Hedbor 
dc82262002-08-13Henrik Grubbström (Grubba)  p = ((unsigned char *)s->s->str) + s->offset + x*2;
c9804a2000-10-08Per Hedbor  res = (p[2]<<8) | p[3]; push_int( res ); }
13670c2015-05-25Martin Nilsson static void push_substring( struct pike_string *s,
ae0ca82000-10-10Henrik Grubbström (Grubba)  ptrdiff_t offset, ptrdiff_t len )
c9804a2000-10-08Per Hedbor { struct object *o = clone_object( substring_program, 0 ); struct substring *ss = SS(o); ss->s = s; s->refs++; ss->offset = offset; ss->len = len; push_object( o ); }
74dfe82012-12-30Jonas Walldén static void free_substring(struct object *UNUSED(o))
c9804a2000-10-08Per Hedbor { if( SS(fp->current_object)->s ) free_string( SS(fp->current_object)->s ); }
bc73c61999-04-11Per Hedbor  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 } property_type; typedef enum { RGB = 0, GRAY = 1, INDEXED = 2, } image_type; typedef enum { Red, Green, Blue, Gray, Indexed, Auxillary } channel_type; typedef enum { RGB_GIMAGE, RGBA_GIMAGE, GRAY_GIMAGE, GRAYA_GIMAGE, INDEXED_GIMAGE, INDEXEDA_GIMAGE } layer_type;
0e02e91999-04-11Per Hedbor  typedef enum { /*< chop=_MODE >*/ NORMAL_MODE, DISSOLVE_MODE, BEHIND_MODE, MULTIPLY_MODE, /*< nick=MULTIPLY/BURN >*/ SCREEN_MODE, OVERLAY_MODE, DIFFERENCE_MODE, ADDITION_MODE, SUBTRACT_MODE, DARKEN_ONLY_MODE, /*< nick=DARKEN-ONLY >*/ LIGHTEN_ONLY_MODE, /*< nick=LIGHTEN-ONLY >*/ HUE_MODE, SATURATION_MODE, COLOR_MODE, VALUE_MODE, DIVIDE_MODE, /*< nick=DIVIDE/DODGE >*/ ERASE_MODE, REPLACE_MODE, } LayerModeEffects;
bc73c61999-04-11Per Hedbor typedef enum { COMPRESS_NONE = 0, COMPRESS_RLE = 1, COMPRESS_ZLIB = 2, COMPRESS_FRACTAL = 3, } compression_type; struct property { int type; struct buffer data; struct property *next; }; static unsigned int read_uint( struct buffer *from ) { unsigned int res; if(from->len < 4)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Not enough space for 4 bytes (uint32)\n");
c9804a2000-10-08Per Hedbor  res = (from->str[0]<<24)|(from->str[1]<<16)|(from->str[2]<<8)|from->str[3];
bc73c61999-04-11Per Hedbor  from->str += 4; from->len -= 4; return res; }
6dc2772000-07-28Fredrik Hübinette (Hubbe) static int xcf_read_int( struct buffer *from )
bc73c61999-04-11Per Hedbor { return (int)read_uint( from ); }
c9804a2000-10-08Per Hedbor static char *read_data( struct buffer *from, size_t len )
bc73c61999-04-11Per Hedbor { char *res; if( from->len < len )
cc7cf42015-10-14Martin Nilsson  Pike_error("Not enough space for %lu bytes\n", (unsigned long)len);
01a9572000-02-03Henrik Grubbström (Grubba)  res = (char *)from->str;
bc73c61999-04-11Per Hedbor  from->str += len; from->len -= len; return res; } static struct buffer read_string( struct buffer *data ) {
c9804a2000-10-08Per Hedbor  struct buffer res = *data;
6dc2772000-07-28Fredrik Hübinette (Hubbe)  res.len = xcf_read_int( data );
01a9572000-02-03Henrik Grubbström (Grubba)  res.str = (unsigned char *)read_data( data, res.len );
97fa562000-10-17Per Hedbor  if(res.len > 0) res.len--; /* len includes ending \0 */
bc73c61999-04-11Per Hedbor  if(!res.str)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("String read failed\n");
bc73c61999-04-11Per Hedbor  return res; } static struct property read_property( struct buffer * data ) { struct property res; res.type = read_uint( data ); if(res.type == PROP_COLORMAP) { unsigned int foo; read_uint(data); /* bogus 'len'... */ foo = read_uint( data ); res.data.len = foo*3;
01a9572000-02-03Henrik Grubbström (Grubba)  res.data.str = (unsigned char *)read_data( data,foo*3 );
c9804a2000-10-08Per Hedbor  res.data.s = data->s;
bc73c61999-04-11Per Hedbor  } else { res.data.len = read_uint( data );
01a9572000-02-03Henrik Grubbström (Grubba)  res.data.str = (unsigned char *)read_data( data,res.data.len );
c9804a2000-10-08Per Hedbor  res.data.s = data->s;
bc73c61999-04-11Per Hedbor  } res.next = NULL; return res; } struct tile { struct tile *next; struct buffer data; }; struct level { unsigned int width; unsigned int height;
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  struct tile *first_tile; }; struct hierarchy { unsigned int width; unsigned int height; unsigned int bpp; struct level level; }; struct channel { struct channel *next; unsigned int width; unsigned int height; struct buffer name; struct hierarchy image_data; struct property *first_property; }; struct layer_mask { unsigned int width; unsigned int height; struct buffer name; struct hierarchy image_data; struct property *first_property; }; struct layer { struct layer *next; unsigned int width; unsigned int height; int type; struct buffer name; struct hierarchy image_data; struct property *first_property; struct layer_mask *mask; }; struct gimp_image { unsigned int width; unsigned int height; int type; struct property *first_property; struct layer *first_layer; /* OBS: In reverse order! */ struct channel *first_channel; /* OBS: In reverse order! */ }; static void free_level( struct level *l ) { struct tile *t; while( (t = l->first_tile) ) {
00bee62000-04-10Henrik Grubbström (Grubba)  l->first_tile = t->next;
bc73c61999-04-11Per Hedbor  free(t); } } static void free_layer_mask( struct layer_mask *l ) { struct property *p; while( (p = l->first_property) ) {
00bee62000-04-10Henrik Grubbström (Grubba)  l->first_property = p->next;
bc73c61999-04-11Per Hedbor  free(p); } free_level( &l->image_data.level ); } static void free_layer( struct layer *l ) { struct property *p; while( (p = l->first_property) ) {
00bee62000-04-10Henrik Grubbström (Grubba)  l->first_property = p->next;
bc73c61999-04-11Per Hedbor  free(p); } if(l->mask) { free_layer_mask( l->mask ); free( l->mask ); } free_level( &l->image_data.level ); } static void free_channel( struct channel *l ) { struct property *p; while( (p = l->first_property) ) {
00bee62000-04-10Henrik Grubbström (Grubba)  l->first_property = p->next;
bc73c61999-04-11Per Hedbor  free(p); } free_level( &l->image_data.level ); } static void free_image( struct gimp_image *i ) { struct property *p; struct layer *l;
00bee62000-04-10Henrik Grubbström (Grubba)  struct channel *c;
bc73c61999-04-11Per Hedbor  while( (p = i->first_property) ) {
00bee62000-04-10Henrik Grubbström (Grubba)  i->first_property = p->next;
bc73c61999-04-11Per Hedbor  free(p); } while( (l = i->first_layer) ) {
00bee62000-04-10Henrik Grubbström (Grubba)  i->first_layer = l->next;
bc73c61999-04-11Per Hedbor  free_layer( l ); free( l );
00bee62000-04-10Henrik Grubbström (Grubba)  } while( (c = i->first_channel) ) { i->first_channel = c->next; free_channel(c); free(c);
bc73c61999-04-11Per Hedbor  } } static struct level read_level( struct buffer *buff, struct buffer *initial ) { struct level res; ONERROR err; int offset; struct tile *last_tile = NULL;
c9804a2000-10-08Per Hedbor /* int all_tiles_eq = 0; */
21b12a2014-09-03Martin Nilsson  memset(&res, 0, sizeof(res));
bc73c61999-04-11Per Hedbor  res.width = read_uint( buff ); res.height = read_uint( buff ); SET_ONERROR( err, free_level, &res ); offset = read_uint( buff ); while(offset) { struct buffer ob = *initial; int offset2 = read_uint( buff );
2d21052018-01-19Martin Nilsson  struct tile *tile = ALLOC_STRUCT(tile);
bc73c61999-04-11Per Hedbor  read_data( &ob, offset ); if(last_tile) last_tile->next = tile; last_tile = tile; if(!res.first_tile) res.first_tile = tile; tile->data = ob; tile->next = NULL; offset = offset2; } UNSET_ONERROR( err ); return res; } static struct hierarchy read_hierarchy( struct buffer *buff, struct buffer *initial ) { struct hierarchy res; unsigned int offset; struct buffer ob;
21b12a2014-09-03Martin Nilsson  memset(&res, 0, sizeof(res));
bc73c61999-04-11Per Hedbor  res.width = read_uint( buff ); res.height = read_uint( buff ); res.bpp = read_uint( buff ); offset = read_uint( buff ); ob = *initial; read_data( &ob, offset ); res.level = read_level( &ob, initial ); return res; }
0bda162000-02-08Per Hedbor static struct layer_mask read_layer_mask( struct buffer *buff,
bc73c61999-04-11Per Hedbor  struct buffer *initial ) { struct layer_mask res; ONERROR err; int offset; struct property tmp;
21b12a2014-09-03Martin Nilsson  memset(&res, 0, sizeof(res));
bc73c61999-04-11Per Hedbor  res.width = read_uint( buff ); res.height = read_uint( buff ); res.name = read_string( buff );
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  SET_ONERROR( err, free_layer_mask, &res ); do { tmp = read_property( buff ); if(tmp.type) {
2d21052018-01-19Martin Nilsson  struct property *s = ALLOC_STRUCT(property);
bc73c61999-04-11Per Hedbor  *s = tmp; s->next = res.first_property; res.first_property = s; } } while(tmp.type); offset = read_uint( buff );
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  if(offset) { struct buffer ob = *initial; read_data( &ob, offset ); res.image_data = read_hierarchy( &ob, initial ); } UNSET_ONERROR( err ); return res; }
0bda162000-02-08Per Hedbor static struct channel read_channel( struct buffer *buff,
bc73c61999-04-11Per Hedbor  struct buffer *initial ) { struct channel res; ONERROR err; int offset; struct property tmp;
21b12a2014-09-03Martin Nilsson  memset(&res, 0, sizeof(res));
bc73c61999-04-11Per Hedbor  res.width = read_uint( buff ); res.height = read_uint( buff ); res.name = read_string( buff );
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  SET_ONERROR( err, free_channel, &res ); do { tmp = read_property( buff ); if(tmp.type) {
2d21052018-01-19Martin Nilsson  struct property *s = ALLOC_STRUCT(property);
bc73c61999-04-11Per Hedbor  *s = tmp; s->next = res.first_property; res.first_property = s; } } while( tmp.type ); offset = read_uint( buff );
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  if(offset) { struct buffer ob = *initial; read_data( &ob, offset ); res.image_data = read_hierarchy( &ob, initial ); } UNSET_ONERROR( err ); return res; } static struct layer read_layer( struct buffer *buff, struct buffer *initial ) { struct layer res; struct property tmp; int lm_offset; int h_offset; ONERROR err;
21b12a2014-09-03Martin Nilsson  memset(&res, 0, sizeof(res));
bc73c61999-04-11Per Hedbor  SET_ONERROR( err, free_layer, &res ); res.width = read_uint( buff ); res.height = read_uint( buff );
6dc2772000-07-28Fredrik Hübinette (Hubbe)  res.type = xcf_read_int( buff );
bc73c61999-04-11Per Hedbor  res.name = read_string( buff );
262cd82003-10-25Martin Nilsson 
bc73c61999-04-11Per Hedbor  do { tmp = read_property( buff ); if(tmp.type) {
2d21052018-01-19Martin Nilsson  struct property *s=ALLOC_STRUCT(property);
bc73c61999-04-11Per Hedbor  *s = tmp; s->next = res.first_property; res.first_property = s; } } while( tmp.type );
6dc2772000-07-28Fredrik Hübinette (Hubbe)  h_offset = xcf_read_int( buff ); lm_offset = xcf_read_int( buff );
262cd82003-10-25Martin Nilsson 
bc73c61999-04-11Per Hedbor  if(lm_offset) { struct buffer loffset = *initial;
2d21052018-01-19Martin Nilsson  struct layer_mask *m=ALLOC_STRUCT(layer_mask);
bc73c61999-04-11Per Hedbor  res.mask = m; read_data( &loffset, lm_offset );
21b12a2014-09-03Martin Nilsson  memset(m, 0, sizeof( struct layer_mask ));
bc73c61999-04-11Per Hedbor  *m = read_layer_mask( &loffset, initial ); }
262cd82003-10-25Martin Nilsson 
bc73c61999-04-11Per Hedbor  if(h_offset) { struct buffer loffset = *initial; read_data( &loffset, h_offset ); res.image_data = read_hierarchy( &loffset, initial ); } UNSET_ONERROR( err ); return res; } static struct gimp_image read_image( struct buffer * data ) { struct gimp_image res; struct property tmp; struct buffer initial; unsigned int offset; ONERROR err;
21b12a2014-09-03Martin Nilsson  memset(&res, 0, sizeof(res));
bc73c61999-04-11Per Hedbor  initial = *data; if(data->len < 34)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("This is not an xcf file (to little data)\n");
bc73c61999-04-11Per Hedbor  if(!(data->str[0] == 'g' && data->str[1] == 'i' && data->str[2] == 'm' && data->str[3] == 'p' && data->str[4] == ' ')) {
01a9572000-02-03Henrik Grubbström (Grubba)  if(strlen((char *)data->str) == 13)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("This is not an xcf file (%s)\n", data->str);
bc73c61999-04-11Per Hedbor  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("This is not an xcf file\n");
bc73c61999-04-11Per Hedbor  } data->str+=14; data->len-=14; res.width = read_uint( data ); res.height = read_uint( data );
6dc2772000-07-28Fredrik Hübinette (Hubbe)  res.type = xcf_read_int( data );
bc73c61999-04-11Per Hedbor  SET_ONERROR( err, free_image, &res ); do { tmp = read_property( data ); if(tmp.type) {
2d21052018-01-19Martin Nilsson  struct property *s=ALLOC_STRUCT(property);
bc73c61999-04-11Per Hedbor  *s = tmp; s->next = res.first_property; res.first_property = s; } } while( tmp.type );
262cd82003-10-25Martin Nilsson 
bc73c61999-04-11Per Hedbor  while( (offset = read_uint( data )) ) { struct buffer layer_data = initial; struct layer tmp; read_data( &layer_data, offset ); tmp = read_layer( &layer_data, &initial ); if( tmp.width && tmp.height ) {
2d21052018-01-19Martin Nilsson  struct layer *s = ALLOC_STRUCT(layer);
bc73c61999-04-11Per Hedbor  *s = tmp; s->next = res.first_layer; res.first_layer = s; } } while( (offset = read_uint( data )) ) { struct buffer channel_data = initial; struct channel tmp; read_data( &channel_data, offset ); tmp = read_channel( &channel_data, &initial ); if( tmp.width && tmp.height ) {
2d21052018-01-19Martin Nilsson  struct channel *s = ALLOC_STRUCT(channel);
bc73c61999-04-11Per Hedbor  *s = tmp; s->next = res.first_channel; res.first_channel = s; } } UNSET_ONERROR( err ); return res; } static void push_buffer( struct buffer *b ) {
279ca52008-01-22Henrik Grubbström (Grubba)  push_substring( b->s, b->str - (unsigned char *)b->s->str, b->len );
c9804a2000-10-08Per Hedbor /* push_string( make_shared_binary_string( (char *)b->str, b->len ) );*/
bc73c61999-04-11Per Hedbor } static void push_properties( struct property *p ) { struct svalue *osp = sp; while(p) { ref_push_string( s_type ); push_int( p->type ); ref_push_string( s_data ); push_buffer( &p->data ); f_aggregate_mapping( 4 ); p = p->next; }
cc7cf42015-10-14Martin Nilsson  f_aggregate((INT32)(sp - osp));
bc73c61999-04-11Per Hedbor } static void push_tile( struct tile *t ) { push_buffer( &t->data ); } static void push_hierarchy( struct hierarchy * h ) { struct tile *t = h->level.first_tile; struct svalue *osp = sp, *tsp; if(h->level.width != h->width || h->level.height != h->height)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Illegal hierarchy level sizes!\n");
bc73c61999-04-11Per Hedbor  ref_push_string( s_width ); push_int( h->width ); ref_push_string( s_height ); push_int( h->height ); ref_push_string( s_bpp ); push_int( h->bpp );
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  ref_push_string( s_tiles ); tsp = sp; while(t) { push_tile( t ); t=t->next; }
cc7cf42015-10-14Martin Nilsson  f_aggregate((INT32)(sp - tsp)); f_aggregate_mapping((INT32)(sp - osp));
bc73c61999-04-11Per Hedbor } static void push_layer_mask(struct layer_mask *i) { struct svalue *osp = sp; ref_push_string( s_width ); push_int( i->width ); ref_push_string( s_height ); push_int( i->height ); ref_push_string( s_properties ); push_properties( i->first_property ); ref_push_string( s_name ); push_buffer( &i->name ); ref_push_string( s_image_data ); push_hierarchy( &i->image_data );
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping((INT32)(sp-osp));
bc73c61999-04-11Per Hedbor } static void push_channel(struct channel *i) { struct svalue *osp = sp; ref_push_string( s_width ); push_int( i->width ); ref_push_string( s_height ); push_int( i->height ); ref_push_string( s_properties ); push_properties( i->first_property ); ref_push_string( s_name ); push_buffer( &i->name ); ref_push_string( s_image_data ); push_hierarchy( &i->image_data );
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping((INT32)(sp-osp));
bc73c61999-04-11Per Hedbor } static void push_layer(struct layer *i) { struct svalue *osp = sp; ref_push_string( s_width ); push_int( i->width ); ref_push_string( s_height ); push_int( i->height ); ref_push_string( s_type ); push_int( i->type ); ref_push_string( s_properties ); push_properties( i->first_property ); ref_push_string( s_name ); push_buffer( &i->name ); ref_push_string( s_image_data ); push_hierarchy( &i->image_data ); if( i->mask ) { ref_push_string( s_mask ); push_layer_mask( i->mask ); }
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping((INT32)(sp - osp));
bc73c61999-04-11Per Hedbor } static void push_image( struct gimp_image *i ) { struct layer *l; struct channel *c; int nitems = 0; struct svalue *osp = sp; ref_push_string( s_width ); push_int( i->width ); ref_push_string( s_height ); push_int( i->height ); ref_push_string( s_type ); push_int( i->type ); ref_push_string( s_properties ); push_properties( i->first_property ); ref_push_string( s_layers ); l = i->first_layer; while(l) { nitems++; push_layer( l ); l = l->next; } f_aggregate( nitems ); ref_push_string( s_channels ); nitems=0; c = i->first_channel; while(c) { nitems++; push_channel( c ); c = c->next; } f_aggregate( nitems );
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping((INT32)(sp-osp));
bc73c61999-04-11Per Hedbor } static void image_xcf____decode( INT32 args ) { struct pike_string *s; struct buffer b; struct gimp_image res; ONERROR err;
391ac52018-08-05Martin Nilsson  get_all_args( NULL, args, "%S", &s );
bc73c61999-04-11Per Hedbor  if(args > 1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too many arguments to Image.XCF.___decode()\n");
bc73c61999-04-11Per Hedbor 
c9804a2000-10-08Per Hedbor  b.s = s; b.len = s->len; b.str = (unsigned char *)s->str;
bc73c61999-04-11Per Hedbor  res = read_image( &b ); SET_ONERROR( err, free_image, &res ); push_image( &res ); UNSET_ONERROR( err ); free_image( &res ); stack_swap(); pop_stack(); }
c9804a2000-10-08Per Hedbor static unsigned char read_char( struct buffer *from )
bc73c61999-04-11Per Hedbor { unsigned char res = 0; if(from->len) { res = from->str[0]; from->str++; from->len--; } return res; }
0bda162000-02-08Per Hedbor /* **! method array(object) decode_layers( string data )
4a9f4d2001-04-15Mirar (Pontus Hagland) **! method array(object) decode_layers( string data, mapping options )
0bda162000-02-08Per Hedbor **! Decodes a XCF image to an array of Image.Layer objects **! **! The layer object have the following extra variables (to be queried **! using get_misc_value): **! **! image_xres, image_yres, image_colormap, image_guides, image_parasites, **! name, parasites, visible, active
4a9f4d2001-04-15Mirar (Pontus Hagland) **! **! Takes the same argument mapping as <ref>_decode</ref>, **! note especially "draw_all_layers":1.
0bda162000-02-08Per Hedbor */
bc73c61999-04-11Per Hedbor  /* **! method object decode(string data)
0bda162000-02-08Per Hedbor **! Decodes a XCF image to a single image object.
bc73c61999-04-11Per Hedbor **! **! note
a4a1722000-12-05Per Hedbor **! Throws upon error in data, you will loose quite a lot of
bc73c61999-04-11Per Hedbor **! information by doing this. See Image.XCF._decode and Image.XCF.__decode */ /*
6e6c451999-04-12Per Hedbor **! method mapping _decode(string|object data,mapping|void options)
0bda162000-02-08Per Hedbor **! Decodes a XCF image to a mapping, with at least an **! 'image' and possibly an 'alpha' object. Data is either a XCF image, or
bc73c61999-04-11Per Hedbor **! a XCF.GimpImage object structure (as received from __decode) **!
6e6c451999-04-12Per Hedbor **! <pre> Supported options **! ([
448c201999-04-13Mirar (Pontus Hagland) **! "background":({r,g,b})||Image.Color object
6e6c451999-04-12Per Hedbor **! "draw_all_layers":1, **! Draw invisible layers as well **! **! "draw_guides":1, **! Draw the guides **! **! "draw_selection":1, **! Mark the selection using an overlay **! **! "ignore_unknown_layer_modes":1 **! Do not asume 'Normal' for unknown layer modes. **! **! "mark_layers":1, **! Draw an outline around all (drawn) layers **!
448c201999-04-13Mirar (Pontus Hagland) **! "mark_layer_names":Image.Font object,
6e6c451999-04-12Per Hedbor **! Write the name of all layers using the font object, **! **! "mark_active_layer":1, **! Draw an outline around the active layer **! ])</pre> **!
bc73c61999-04-11Per Hedbor **! note
a4a1722000-12-05Per Hedbor **! Throws upon error in data. For more information, see Image.XCF.__decode
bc73c61999-04-11Per Hedbor */ /*
6e6c451999-04-12Per Hedbor **! method object __decode(string|mapping data, mapping|void options)
bc73c61999-04-11Per Hedbor **! Decodes a XCF image to a Image.XCF.GimpImage object. **!
0bda162000-02-08Per Hedbor **! <pre>Returned structure reference **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class GimpImage
bc73c61999-04-11Per Hedbor **! { **! int width; **! int height; **! int compression; **! int type; **! int tattoo_state; **! float xres = 72.0; **! float yres = 72.0; **! int res_unit;
448c201999-04-13Mirar (Pontus Hagland) **! Image.Colortable colormap; **! Image.Colortable meta_colormap;
bc73c61999-04-11Per Hedbor **! array(Layer) layers = ({}); **! array(Channel) channels = ({}); **! array(Guide) guides = ({}); **! array(Parasite) parasites = ({}); **! array(Path) paths = ({});
6e6c451999-04-12Per Hedbor **!
bc73c61999-04-11Per Hedbor **! Layer active_layer; **! Channel active_channel; **! Channel selection; **! }
0bda162000-02-08Per Hedbor **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class Layer
bc73c61999-04-11Per Hedbor **! { **! string name; **! int opacity; **! int type; **! int mode; **! int tattoo; **! mapping flags = ([]); **! int width, height; **! int xoffset, yoffset; **! array (Parasite) parasites; **! LayerMask mask; **! Hierarchy image; **! }
0bda162000-02-08Per Hedbor **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class Channel
bc73c61999-04-11Per Hedbor **! { **! string name; **! int width; **! int height; **! int opacity; **! int r, g, b; **! int tattoo; **! Hierarchy image_data; **! object parent; **! mapping flags = ([]); **! array (Parasite) parasites; **! }
0bda162000-02-08Per Hedbor **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class Hierarchy
bc73c61999-04-11Per Hedbor **! {
448c201999-04-13Mirar (Pontus Hagland) **! Image.Image img; **! Image.Image alpha;
bc73c61999-04-11Per Hedbor **! int width; **! int height; **! int bpp; **! }
0bda162000-02-08Per Hedbor **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class Parasite
bc73c61999-04-11Per Hedbor **! { **! string name; **! int flags; **! string data; **! }
0bda162000-02-08Per Hedbor **! **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class Guide
bc73c61999-04-11Per Hedbor **! { **! int pos; **! int vertical; **! }
0bda162000-02-08Per Hedbor **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class Path
bc73c61999-04-11Per Hedbor **! { **! string name; **! int ptype; **! int tattoo; **! int closed; **! int state; **! int locked; **! array (PathPoint) points = ({}); **! }
0bda162000-02-08Per Hedbor **!
65352b1999-04-12Mirar (Pontus Hagland) **! !class PathPoint
bc73c61999-04-11Per Hedbor **! { **! int type; **! float x; **! float y; **! } **! **! </pre> */ /* **! method object ___decode(string|mapping data) **! Decodes a XCF image to a mapping. **!
0bda162000-02-08Per Hedbor **! <pre>Structure reference **!
bc73c61999-04-11Per Hedbor **! ([ **! "width":int, **! "height":int, **! "type":int, **! "properties":({
0bda162000-02-08Per Hedbor **! ([
bc73c61999-04-11Per Hedbor **! "type":int, **! "data":string, **! ]), **! ... **! }), **! "layers":({ **! ([ **! "name":string, **! "width":int, **! "height":int, **! "type":type, **! "properties":({
0bda162000-02-08Per Hedbor **! ([
bc73c61999-04-11Per Hedbor **! "type":int, **! "data":string, **! ]), **! ... **! }), **! "mask":0 || ([ **! "name":string, **! "width":int, **! "height":int, **! "properties":({
0bda162000-02-08Per Hedbor **! ([
bc73c61999-04-11Per Hedbor **! "type":int, **! "data":string, **! ]), **! ... **! }), **! "image_data":([ **! "bpp":int, **! "width":int, **! "height":int, **! "tiles":({ **! string, **! ... **! }), **! ]), **! ]), **! "image_data":([ **! "bpp":int, **! "width":int, **! "height":int, **! "tiles":({ **! string, **! ... **! }), **! ]), **! ]), **! ... **! }), **! "channels":({ **! "name":string, **! "width":int, **! "height":int, **! "properties":({
0bda162000-02-08Per Hedbor **! ([
bc73c61999-04-11Per Hedbor **! "type":int, **! "data":string, **! ]), **! ... **! }), **! "image_data":([ **! "bpp":int, **! "width":int, **! "height":int, **! "tiles":({ **! string, **! ... **! }), **! ]), **! }), **! ]) **!</pre> */ void image_xcf_f__decode_tiles( INT32 args ) { struct object *io,*ao, *cmapo; struct array *tiles;
c9804a2000-10-08Per Hedbor  struct image *i=NULL, *a=NULL;
bc73c61999-04-11Per Hedbor  struct neo_colortable *cmap = NULL;
a92ad62003-10-13Henrik Grubbström (Grubba)  INT32 rxs, rys;
bc73c61999-04-11Per Hedbor  rgb_group *colortable=NULL;
b45ba42000-10-19Per Hedbor  rgb_group pix = {0,0,0};
da8e5a2000-10-25Henrik Grubbström (Grubba)  rgb_group apix= {255,255,255}; /* avoid may use uninitialized warnings */
b45ba42000-10-19Per Hedbor 
c9804a2000-10-08Per Hedbor  INT_TYPE rle, bpp, span, shrink;
bc73c61999-04-11Per Hedbor  unsigned int l, x=0, y=0, cx, cy;
7d60af2004-05-19Martin Nilsson  ONERROR err;
391ac52018-08-05Martin Nilsson  get_all_args( NULL, args, "%o%O%a%i%i%O%i%d%d",
c9804a2000-10-08Per Hedbor  &io, &ao, &tiles, &rle, &bpp, &cmapo, &shrink, &rxs, &rys);
13b5ed2014-05-26Per Hedbor  if( !(i = get_storage( io, image_program )))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong type object argument 1 (image)\n");
c9804a2000-10-08Per Hedbor 
13b5ed2014-05-26Per Hedbor  if(ao && !(a = get_storage( ao, image_program )))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong type object argument 2 (image)\n");
c9804a2000-10-08Per Hedbor 
0bda162000-02-08Per Hedbor  if( cmapo &&
76f7462014-05-26Martin Nilsson  !(cmap=get_storage(cmapo, image_colortable_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong type object argument 4 (colortable)\n");
c9804a2000-10-08Per Hedbor 
bc73c61999-04-11Per Hedbor  for(l=0; l<(unsigned int)tiles->size; l++)
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(tiles->item[l]) != T_OBJECT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong type array argument 3 (tiles)\n");
c9804a2000-10-08Per Hedbor  if(a && ((i->xsize != a->xsize) || (i->ysize != a->ysize)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image and alpha objects are not identically sized.\n");
bc73c61999-04-11Per Hedbor  if(cmap) {
20d0552009-04-22Martin Stjernholm  colortable = xalloc(sizeof(rgb_group)*image_colortable_size( cmap ) + RGB_VEC_PAD);
7d60af2004-05-19Martin Nilsson  SET_ONERROR(err, free, colortable);
bc73c61999-04-11Per Hedbor  image_colortable_write_rgb( cmap, (unsigned char *)colortable ); } x=y=0;
c9804a2000-10-08Per Hedbor  THREADS_ALLOW();
bc73c61999-04-11Per Hedbor  for(l=0; l<(unsigned)tiles->size; l++) {
c9804a2000-10-08Per Hedbor  struct object *to = tiles->item[l].u.object; struct substring *tile_ss = SS(to); struct buffer tile; char *df = 0;
bc73c61999-04-11Per Hedbor  unsigned int eheight, ewidth; unsigned char *s;
c9804a2000-10-08Per Hedbor  if(!tile_ss) continue;
63261c2008-01-22Henrik Grubbström (Grubba)  tile.s = NULL;
dc82262002-08-13Henrik Grubbström (Grubba)  tile.str = (unsigned char *)(tile_ss->s->str + tile_ss->offset);
c9804a2000-10-08Per Hedbor  tile.len = tile_ss->len; ewidth = MINIMUM(TILE_WIDTH, (rxs-x)); eheight = MINIMUM(TILE_HEIGHT, (rys-y));
bc73c61999-04-11Per Hedbor 
294d792004-08-11Per Hedbor  if( (double)ewidth * eheight * bpp > INT_MAX ) Pike_error("Insanely large tiles not supported\n");
bc73c61999-04-11Per Hedbor  if(rle) {
c9804a2000-10-08Per Hedbor  struct buffer s = tile, od, d; int i;
63261c2008-01-22Henrik Grubbström (Grubba)  od.s = NULL;
c9804a2000-10-08Per Hedbor  od.len = eheight*ewidth*bpp; /* Max and only size, really */
dc8d022014-04-27Martin Nilsson  df = (char *)(od.str = xalloc( eheight*ewidth*bpp+1 ));
c9804a2000-10-08Per Hedbor  d = od; for(i=0; i<bpp; i++) { int nelems = ewidth*eheight; int length; while(nelems) { unsigned char val = read_char( &s ); if(!s.len) { break; /* Hm. This is actually rather fatal */ } length = val; if( length >= 128 ) { length = 255-(length-1); if (length == 128) length = (read_char( &s )<<8) + read_char( &s ); nelems -= length; while(length--) { if(d.len < 1) break; d.str[0] = read_char( &s ); d.str++; d.len--; } } else { length++; if(length == 128) length = (read_char( &s )<<8) + read_char( &s ); nelems -= length; val = read_char( &s ); while(length--) { if(d.len < 1) break; d.str[0] = val; d.str++; d.len--; } } } } tile = od;
bc73c61999-04-11Per Hedbor  }
c9804a2000-10-08Per Hedbor  if( (size_t)(tile.len) < (size_t)(eheight * ewidth * bpp )) {
9b5c4e2017-08-11Chris Angelico  if( df ) {free( df ); df=0;}
c9804a2000-10-08Per Hedbor  continue; } s = (unsigned char *)tile.str; #define LOOP_INIT() {\ int ix, iy=y/shrink; \ for(cy=0; cy<eheight; cy+=shrink,iy=((cy+y)/shrink)) \ { \
ac9fc22000-10-20Henrik Grubbström (Grubba)  rgb_group *ip, *ap = NULL; \
b45ba42000-10-19Per Hedbor  int ind=cy*ewidth; \
c9804a2000-10-08Per Hedbor  int ds = 0; \ if(iy >= i->ysize) continue; \
b45ba42000-10-19Per Hedbor  ix = x/shrink; \ ip = i->img + (i->xsize*iy); \ if( a ) ap = a->img + (i->xsize*iy); \
c9804a2000-10-08Per Hedbor  for(cx=0; cx<ewidth; cx+=shrink,ind+=shrink,ix++) \ { \ if(ix >= i->xsize) continue #define LOOP_EXIT() \
b45ba42000-10-19Per Hedbor  ip[ix] = pix; \
c9804a2000-10-08Per Hedbor  } \ }}
0bda162000-02-08Per Hedbor 
c9804a2000-10-08Per Hedbor  if(rle) span = ewidth*eheight; else span = 1;
bc73c61999-04-11Per Hedbor 
65d3622000-10-19Henrik Grubbström (Grubba)  switch(bpp)
bc73c61999-04-11Per Hedbor  {
b45ba42000-10-19Per Hedbor  case 1: /* indexed or grey */ if(colortable) { LOOP_INIT(); pix = colortable[s[ind]]; LOOP_EXIT();
13670c2015-05-25Martin Nilsson  }
b45ba42000-10-19Per Hedbor  else { LOOP_INIT(); pix.r = pix.g = pix.b = s[ind]; LOOP_EXIT(); } break; case 2: /* indexed or grey with alpha */ if(colortable) { LOOP_INIT(); pix = colortable[ s[ ind ] ]; if( a ) { apix.r = apix.g = apix.b = s[ind+span]; ap[ix] = apix; } LOOP_EXIT(); } else { LOOP_INIT(); pix.r = pix.g = pix.b = s[ind]; if( a ) { apix.r = apix.g = apix.b = s[ind+span]; ap[ix] = apix; } LOOP_EXIT(); } break; case 3: /* rgb */ LOOP_INIT(); pix.r = s[ind]; pix.g = s[ind+span]; pix.b = s[ind+span*2]; LOOP_EXIT(); break; case 4: /* rgba */ LOOP_INIT(); pix.r = s[ind]; pix.g = s[ind+span]; pix.b = s[ind+span*2]; if(a) { apix.r = apix.b = apix.g = s[ind+span*3]; ap[ix] = apix; } LOOP_EXIT(); break;
c9804a2000-10-08Per Hedbor  } if( df )
13670c2015-05-25Martin Nilsson  { free(df); df=0;
bc73c61999-04-11Per Hedbor  } x += TILE_WIDTH;
c9804a2000-10-08Per Hedbor 
296ca22000-10-09Per Hedbor  if( (int)x >= (int)rxs )
bc73c61999-04-11Per Hedbor  { x = 0; y += TILE_HEIGHT; } }
c9804a2000-10-08Per Hedbor  THREADS_DISALLOW();
7d60af2004-05-19Martin Nilsson  if(colortable) { UNSET_ONERROR(err);
c9804a2000-10-08Per Hedbor  free( colortable );
7d60af2004-05-19Martin Nilsson  }
0bda162000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  pop_n_elems(args); push_int(0); } static struct program *image_encoding_xcf_program=NULL;
c9eefb2014-08-21Martin Nilsson void init_image_xcf(void)
bc73c61999-04-11Per Hedbor {
226ec82005-01-23Martin Nilsson  ADD_FUNCTION( "___decode", image_xcf____decode, tFunc(tStr,tMapping), 0);
bc73c61999-04-11Per Hedbor 
226ec82005-01-23Martin Nilsson  ADD_FUNCTION( "_decode_tiles", image_xcf_f__decode_tiles, tFunction, 0);
bc73c61999-04-11Per Hedbor  add_integer_constant( "PROP_END", PROP_END,0 ); add_integer_constant( "PROP_COLORMAP", PROP_COLORMAP, 0 ); add_integer_constant( "PROP_ACTIVE_LAYER", PROP_ACTIVE_LAYER, 0 ); add_integer_constant( "PROP_ACTIVE_CHANNEL", PROP_ACTIVE_CHANNEL, 0 ); add_integer_constant( "PROP_SELECTION", PROP_SELECTION, 0 ); add_integer_constant( "PROP_FLOATING_SELECTION", PROP_FLOATING_SELECTION, 0 ); add_integer_constant( "PROP_OPACITY", PROP_OPACITY, 0 ); add_integer_constant( "PROP_MODE", PROP_MODE, 0 ); add_integer_constant( "PROP_VISIBLE", PROP_VISIBLE, 0 ); add_integer_constant( "PROP_LINKED", PROP_LINKED, 0 ); add_integer_constant( "PROP_PRESERVE_TRANSPARENCY", PROP_PRESERVE_TRANSPARENCY, 0); add_integer_constant( "PROP_APPLY_MASK", PROP_APPLY_MASK, 0 ); add_integer_constant( "PROP_EDIT_MASK", PROP_EDIT_MASK, 0 ); add_integer_constant( "PROP_SHOW_MASK", PROP_SHOW_MASK, 0 ); add_integer_constant( "PROP_SHOW_MASKED", PROP_SHOW_MASKED, 0 ); add_integer_constant( "PROP_OFFSETS", PROP_OFFSETS, 0 ); add_integer_constant( "PROP_COLOR", PROP_COLOR, 0 ); add_integer_constant( "PROP_COMPRESSION", PROP_COMPRESSION, 0 ); add_integer_constant( "PROP_GUIDES", PROP_GUIDES, 0 ); add_integer_constant( "PROP_RESOLUTION", PROP_RESOLUTION, 0 ); add_integer_constant( "PROP_TATTOO", PROP_TATTOO, 0 ); add_integer_constant( "PROP_PARASITES", PROP_PARASITES, 0 ); add_integer_constant( "PROP_UNIT", PROP_UNIT, 0 ); add_integer_constant( "PROP_PATHS", PROP_PATHS, 0 ); add_integer_constant( "PROP_USER_UNIT", PROP_USER_UNIT, 0 ); add_integer_constant( "RGB", RGB, 0 ); add_integer_constant( "GRAY", GRAY, 0 ); add_integer_constant( "INDEXED", INDEXED, 0 ); add_integer_constant( "COMPRESS_NONE", COMPRESS_NONE, 0 ); add_integer_constant( "COMPRESS_RLE", COMPRESS_RLE, 0 ); add_integer_constant( "COMPRESS_ZLIB", COMPRESS_ZLIB, 0 ); add_integer_constant( "COMPRESS_FRACTAL", COMPRESS_FRACTAL, 0 );
0e02e91999-04-11Per Hedbor  add_integer_constant("NORMAL_MODE", NORMAL_MODE, 0); add_integer_constant("DISSOLVE_MODE", DISSOLVE_MODE, 0); add_integer_constant("BEHIND_MODE",BEHIND_MODE, 0); add_integer_constant("MULTIPLY_MODE",MULTIPLY_MODE, 0); add_integer_constant("SCREEN_MODE",SCREEN_MODE, 0); add_integer_constant("OVERLAY_MODE",OVERLAY_MODE, 0); add_integer_constant("DIFFERENCE_MODE",DIFFERENCE_MODE, 0); add_integer_constant("ADDITION_MODE",ADDITION_MODE, 0); add_integer_constant("SUBTRACT_MODE",SUBTRACT_MODE, 0); add_integer_constant("DARKEN_ONLY_MODE",DARKEN_ONLY_MODE, 0); add_integer_constant("LIGHTEN_ONLY_MODE",LIGHTEN_ONLY_MODE, 0); add_integer_constant("HUE_MODE",HUE_MODE, 0); add_integer_constant("SATURATION_MODE",SATURATION_MODE, 0); add_integer_constant("COLOR_MODE",COLOR_MODE, 0); add_integer_constant("VALUE_MODE",VALUE_MODE, 0); add_integer_constant("DIVIDE_MODE",DIVIDE_MODE, 0); add_integer_constant("ERASE_MODE",ERASE_MODE, 0); add_integer_constant("REPLACE_MODE",REPLACE_MODE, 0);
bc73c61999-04-11Per Hedbor  add_integer_constant( "Red", Red, 0 ); add_integer_constant( "Green", Green, 0 ); add_integer_constant( "Blue", Blue, 0 ); add_integer_constant( "Gray", Gray, 0 ); add_integer_constant( "Indexed", Indexed, 0 ); add_integer_constant( "Auxillary", Auxillary, 0 ); add_integer_constant( "RGB_GIMAGE", RGB_GIMAGE, 0 ); add_integer_constant( "RGBA_GIMAGE", RGBA_GIMAGE, 0 ); add_integer_constant( "GRAY_GIMAGE", GRAY_GIMAGE, 0 ); add_integer_constant( "GRAYA_GIMAGE", GRAYA_GIMAGE, 0 ); add_integer_constant( "INDEXED_GIMAGE", INDEXED_GIMAGE, 0 ); add_integer_constant( "INDEXEDA_GIMAGE", INDEXEDA_GIMAGE, 0 );
01a9572000-02-03Henrik Grubbström (Grubba) #define STRING(X) s_##X = make_shared_binary_string(#X,sizeof( #X )-sizeof(""))
bc73c61999-04-11Per Hedbor #include "xcf_constant_strings.h" #undef STRING
c9804a2000-10-08Per Hedbor  start_new_program(); ADD_STORAGE( struct substring );
7a74cc2014-08-26Per Hedbor  ADD_FUNCTION("cast", f_substring_cast, tFunc(tStr,tStr), ID_PRIVATE);
226ec82005-01-23Martin Nilsson  ADD_FUNCTION("`[]", f_substring_index, tFunc(tInt,tInt), 0); ADD_FUNCTION("get_short", f_substring_get_short, tFunc(tInt,tInt), 0 ); ADD_FUNCTION("get_ushort", f_substring_get_ushort, tFunc(tInt,tInt), 0 ); ADD_FUNCTION("get_int", f_substring_get_int, tFunc(tInt,tInt), 0 ); ADD_FUNCTION("get_uint", f_substring_get_uint, tFunc(tInt,tInt), 0 ); ADD_FUNCTION("_sprintf",f_substring__sprintf, tFunc(tInt tMapping,tMix), 0);
c9804a2000-10-08Per Hedbor  set_exit_callback(free_substring);
13670c2015-05-25Martin Nilsson  substring_program = end_program();
bc73c61999-04-11Per Hedbor }
c9eefb2014-08-21Martin Nilsson void exit_image_xcf(void)
bc73c61999-04-11Per Hedbor { #define STRING(X) free_string(s_##X) #include "xcf_constant_strings.h" #undef STRING
c9804a2000-10-08Per Hedbor  free_program( substring_program );
bc73c61999-04-11Per Hedbor }