0.39 Released: Nov 2 2001.
+0.40 pre1
+ - anti-aliased polygon fill
+ - add general fill to polygon fill
+
=================================================================
For latest versions check the Imager-devel pages:
i_bezier_multi
i_poly_aa
+ i_poly_aa_cfill
i_copyto
i_rubthru
$self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
}
- i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'color'});
+ if ($opts{'fill'}) {
+ unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
+ # assume it's a hash ref
+ require 'Imager/Fill.pm';
+ unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
+ $self->{ERRSTR} = $Imager::ERRSTR;
+ return undef;
+ }
+ }
+ i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
+ $opts{'fill'}{'fill'});
+ }
+ else {
+ i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'color'});
+ }
+
return $self;
}
myfree(x);
myfree(y);
+void
+i_poly_aa_cfill(im,xc,yc,fill)
+ Imager::ImgRaw im
+ Imager::FillHandle fill
+ PREINIT:
+ double *x,*y;
+ int len;
+ AV *av1;
+ AV *av2;
+ SV *sv1;
+ SV *sv2;
+ int i;
+ PPCODE:
+ if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+ if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+ if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+ if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
+ av1=(AV*)SvRV(ST(1));
+ av2=(AV*)SvRV(ST(2));
+ if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
+ len=av_len(av1)+1;
+ x=mymalloc( len*sizeof(double) );
+ y=mymalloc( len*sizeof(double) );
+ for(i=0;i<len;i++) {
+ sv1=(*(av_fetch(av1,i,0)));
+ sv2=(*(av_fetch(av2,i,0)));
+ x[i]=(double)SvNV(sv1);
+ y[i]=(double)SvNV(sv2);
+ }
+ i_poly_aa_cfill(im,len,x,y,fill);
+ myfree(x);
+ myfree(y);
+
void
x = ar->data[y].min;
w = ar->data[y].max-ar->data[y].min;
- if (fill->combine)
+ if (fill->combine) {
i_glin(im, x, x+w, y, line);
-
- (fill->fill_with_color)(fill, x, y, w, im->channels, line, work);
+ (fill->fill_with_color)(fill, x, y, w, im->channels, work);
+ (fill->combine)(line, work, im->channels, w);
+ }
+ else {
+ (fill->fill_with_color)(fill, x, y, w, im->channels, line);
+ }
i_plin(im, x, x+w, y, line);
}
}
x = ar->data[y].min;
w = ar->data[y].max-ar->data[y].min;
- if (fill->combinef)
+ if (fill->combinef) {
i_glinf(im, x, x+w, y, line);
-
- (fill->fill_with_fcolor)(fill, x, y, w, im->channels, line, work);
+ (fill->fill_with_fcolor)(fill, x, y, w, im->channels, work);
+ (fill->combinef)(line, work, im->channels, w);
+ }
+ else {
+ (fill->fill_with_fcolor)(fill, x, y, w, im->channels, line);
+ }
i_plinf(im, x, x+w, y, line);
}
}
if (fill->combine)
work = mymalloc(sizeof(i_color) * (x2-x1));
while (y1 <= y2) {
- if (fill->combine)
+ if (fill->combine) {
i_glin(im, x1, x2, y1, line);
-
- (fill->fill_with_color)(fill, x1, y1, x2-x1, im->channels, line, work);
+ (fill->fill_with_color)(fill, x1, y1, x2-x1, im->channels, work);
+ (fill->combine)(line, work, im->channels, x2-x1);
+ }
+ else {
+ (fill->fill_with_color)(fill, x1, y1, x2-x1, im->channels, line);
+ }
i_plin(im, x1, x2, y1, line);
++y1;
}
work = mymalloc(sizeof(i_fcolor) * (x2 - x1));
while (y1 <= y2) {
- if (fill->combinef)
+ if (fill->combine) {
i_glinf(im, x1, x2, y1, line);
-
- (fill->fill_with_fcolor)(fill, x1, y1, x2-x1, im->channels, line, work);
+ (fill->fill_with_fcolor)(fill, x1, y1, x2-x1, im->channels, work);
+ (fill->combinef)(line, work, im->channels, x2-x1);
+ }
+ else {
+ (fill->fill_with_fcolor)(fill, x1, y1, x2-x1, im->channels, line);
+ }
i_plinf(im, x1, x2, y1, line);
- ++y1;
}
myfree(line);
if (work)
while (x < bxmax && btm_test(btm, x, y)) {
++x;
}
- if (fill->combine)
+ if (fill->combine) {
i_glin(im, start, x, y, line);
- (fill->fill_with_color)(fill, start, y, x-start, im->channels,
- line, work);
+ (fill->fill_with_color)(fill, start, y, x-start, im->channels,
+ work);
+ (fill->combine)(line, work, im->channels, x-start);
+ }
+ else {
+ (fill->fill_with_color)(fill, start, y, x-start, im->channels,
+ line);
+ }
i_plin(im, start, x, y, line);
}
}
while (x < bxmax && btm_test(btm, x, y)) {
++x;
}
- if (fill->combinef)
+ if (fill->combinef) {
i_glinf(im, start, x, y, line);
- (fill->fill_with_fcolor)(fill, start, y, x-start, im->channels,
- line, work);
+ (fill->fill_with_fcolor)(fill, start, y, x-start, im->channels,
+ work);
+ (fill->combinef)(line, work, im->channels, x-start);
+ }
+ else {
+ (fill->fill_with_fcolor)(fill, start, y, x-start, im->channels,
+ line);
+ }
i_plinf(im, start, x, y, line);
}
}
} i_fill_solid_t;
static void fill_solid(i_fill_t *, int x, int y, int width, int channels,
- i_color *, i_color *);
+ i_color *);
static void fill_solidf(i_fill_t *, int x, int y, int width, int channels,
- i_fcolor *, i_fcolor *);
+ i_fcolor *);
static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels,
- i_color *, i_color *);
+ i_color *);
static void fill_solidf_comb(i_fill_t *, int x, int y, int width,
- int channels, i_fcolor *, i_fcolor *);
+ int channels, i_fcolor *);
static i_fill_solid_t base_solid_fill =
{
} i_fill_hatch_t;
static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work);
+ i_color *data);
static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work);
+ i_fcolor *data);
static
i_fill_t *
i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
}
static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work);
+ i_color *data);
static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work);
+ i_fcolor *data);
struct i_fill_image_t {
i_fill_t base;
i_img *src;
*/
static void
fill_solid(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work) {
+ i_color *data) {
while (width-- > 0) {
*data++ = T_SOLID_FILL(fill)->c;
}
*/
static void
fill_solidf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work) {
+ i_fcolor *data) {
while (width-- > 0) {
*data++ = T_SOLID_FILL(fill)->fc;
}
*/
static void
fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work) {
+ i_color *data) {
i_color c = T_SOLID_FILL(fill)->c;
- int count = width;
- i_color *wstart = work;
while (width-- > 0) {
- *work++ = c;
+ *data++ = c;
}
- (fill->combine)(data, wstart, channels, count);
}
/*
*/
static void
fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work) {
+ i_fcolor *data) {
i_fcolor c = T_SOLID_FILL(fill)->fc;
- int count = width;
- i_fcolor *wstart = work;
while (width-- > 0) {
- *work++ = c;
+ *data++ = c;
}
- (fill->combinef)(data, wstart, channels, count);
}
/*
=cut
*/
static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work) {
+ i_color *data) {
i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
int byte = f->hatch[(y + f->dy) & 7];
int xpos = (x + f->dx) & 7;
int mask = 128 >> xpos;
- if (fill->combine) {
- int count = width;
- i_color *wstart = work;
-
- while (count-- > 0) {
- *work++ = (byte & mask) ? f->fg : f->bg;
-
- if ((mask >>= 1) == 0)
- mask = 128;
- }
- (fill->combine)(data, wstart, channels, width);
- }
- else {
- while (width-- > 0) {
- *data++ = (byte & mask) ? f->fg : f->bg;
-
- if ((mask >>= 1) == 0)
- mask = 128;
- }
+ while (width-- > 0) {
+ *data++ = (byte & mask) ? f->fg : f->bg;
+
+ if ((mask >>= 1) == 0)
+ mask = 128;
}
}
=back
*/
static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work) {
+ i_fcolor *data) {
i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
int byte = f->hatch[(y + f->dy) & 7];
int xpos = (x + f->dx) & 7;
int mask = 128 >> xpos;
- if (fill->combinef) {
- int count = width;
- i_fcolor *wstart = work;
-
- while (count-- > 0) {
- *work++ = (byte & mask) ? f->ffg : f->fbg;
-
- if ((mask >>= 1) == 0)
- mask = 128;
- }
- (fill->combinef)(data, wstart, channels, width);
- }
- else {
- while (width-- > 0) {
- *data++ = (byte & mask) ? f->ffg : f->fbg;
-
- if ((mask >>= 1) == 0)
- mask = 128;
- }
+ while (width-- > 0) {
+ *data++ = (byte & mask) ? f->ffg : f->fbg;
+
+ if ((mask >>= 1) == 0)
+ mask = 128;
}
}
=cut
*/
static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work) {
+ i_color *data) {
struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
- i_color *out = fill->combine ? work : data;
int i = 0;
i_color c;
}
c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
}
- *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
+ *data++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
++i;
}
}
}
rx -= ix * f->src->xsize;
ry -= iy * f->src->ysize;
- i_gpix(f->src, rx, ry, out);
- ++out;
+ i_gpix(f->src, rx, ry, data);
+ ++data;
++i;
}
}
-
- if (fill->combine) {
- (fill->combine)(data, work, channels, width);
- }
}
/*
=cut
*/
static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work) {
+ i_fcolor *data) {
struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
- i_fcolor *out = fill->combine ? work : data;
int i = 0;
i_fcolor c;
}
c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
}
- *out++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
+ *data++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
++i;
}
}
}
rx -= ix * f->src->xsize;
ry -= iy * f->src->ysize;
- i_gpixf(f->src, rx, ry, out);
- ++out;
+ i_gpixf(f->src, rx, ry, data);
+ ++data;
++i;
}
}
-
- if (fill->combinef) {
- (fill->combinef)(data, work, channels, width);
- }
}
static void combine_replace(i_color *, i_color *, int, int);
static void
fill_fountf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work);
+ i_fcolor *data);
static void
fount_fill_destroy(i_fill_t *fill);
*/
static void
fill_fountf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work) {
+ i_fcolor *data) {
i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
- if (fill->combinef) {
- i_fcolor *wstart = work;
- int count = width;
-
- while (width--) {
- i_fcolor c;
- int got_one;
-
- if (f->state.ssfunc)
- got_one = f->state.ssfunc(&c, x, y, &f->state);
- else
- got_one = fount_getat(&c, x, y, &f->state);
-
- *work++ = c;
-
- ++x;
- }
- (fill->combinef)(data, wstart, channels, count);
- }
- else {
- while (width--) {
- i_fcolor c;
- int got_one;
-
- if (f->state.ssfunc)
- got_one = f->state.ssfunc(&c, x, y, &f->state);
- else
- got_one = fount_getat(&c, x, y, &f->state);
-
- *data++ = c;
-
- ++x;
- }
+ while (width--) {
+ i_fcolor c;
+ int got_one;
+
+ if (f->state.ssfunc)
+ got_one = f->state.ssfunc(&c, x, y, &f->state);
+ else
+ got_one = fount_getat(&c, x, y, &f->state);
+
+ *data++ = c;
+
+ ++x;
}
}
typedef void (*i_fill_with_color_f)
(struct i_fill_tag *fill, int x, int y, int width, int channels,
- i_color *data, i_color *work);
+ i_color *data);
typedef void (*i_fill_with_fcolor_f)
(struct i_fill_tag *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work);
+ i_fcolor *data);
typedef void (*i_fill_destroy_f)(struct i_fill_tag *fill);
typedef void (*i_fill_combine_f)(i_color *out, i_color *in, int channels,
int count);
void i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val);
void i_poly_aa (i_img *im,int l,double *x,double *y,i_color *val);
+void i_poly_aa_cfill(i_img *im,int l,double *x,double *y,i_fill_t *fill);
void i_flood_fill (i_img *im,int seedx,int seedy,i_color *dcol);
while (y < im->ysize && rc >= 0) {
i_gsamp(im, 0, im->xsize, y, data, rgb_chan, 3);
rc = ig->writecb(ig, data, im->xsize * 3);
+ ++y;
}
myfree(data);
}
while (y < im->ysize && rc >= 0) {
i_gsamp(im, 0, im->xsize, y, data, &chan, 1);
rc = ig->writecb(ig, data, im->xsize);
+ ++y;
}
myfree(data);
}
return 0;
}
+typedef void (*scanline_flusher)(i_img *im, ss_scanline *ss, int y, void *ctx);
/* This function must be modified later to do proper blending */
void
-scanline_flush(i_img *im, ss_scanline *ss, int y, i_color *val) {
+scanline_flush(i_img *im, ss_scanline *ss, int y, void *ctx) {
int x, ch, tv;
i_color t;
+ i_color *val = (i_color *)ctx;
for(x=0; x<im->xsize; x++) {
tv = saturate(ss->line[x]);
i_gpix(im, x, y, &t);
void
-i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
+i_poly_aa_low(i_img *im, int l, double *x, double *y, void *ctx, scanline_flusher flusher) {
int i ,k; /* Index variables */
int clc; /* Lines inside current interval */
pcord miny ,maxy; /* Min and max values of the current slice in the subcord system */
p_line *lset; /* List of lines in polygon */
p_slice *tllist; /* List of slices */
- mm_log((1, "i_poly_aa(im %p, l %d, x %p, y %p, val %p)\n", im, l, x, y, val));
+ mm_log((1, "i_poly_aa(im %p, l %d, x %p, y %p, ctx %p, flusher %p)\n", im, l, x, y, ctx, flusher));
for(i=0; i<l; i++) {
mm_log((2, "(%.2f, %.2f)\n", x[i], y[i]));
}
if (16*coarse(tempy) == tempy) {
POLY_DEB( printf("flushing scan line %d\n", cscl) );
- scanline_flush(im, &templine, cscl, val);
+ flusher(im, &templine, cscl, ctx);
ss_scanline_reset(&templine);
}
/*
}
} /* Intervals */
if (16*coarse(tempy) != tempy)
- scanline_flush(im, &templine, cscl-1, val);
+ flusher(im, &templine, cscl-1, ctx);
ss_scanline_exorcise(&templine);
myfree(pset);
myfree(tllist);
} /* Function */
+
+void
+i_poly_aa(i_img *im, int l, double *x, double *y, i_color *val) {
+ i_poly_aa_low(im, l, x, y, val, scanline_flush);
+}
+
+struct poly_cfill_state {
+ i_color *fillbuf;
+ i_color *linebuf;
+ int *cover;
+ i_fill_t *fill;
+};
+
+void
+scanline_flush_cfill(i_img *im, ss_scanline *ss, int y, void *ctx) {
+ int x, ch, tv;
+ i_color t;
+ int pos;
+ int left, right;
+ struct poly_cfill_state *state = (struct poly_cfill_state *)ctx;
+ i_color *fillbuf = state->fillbuf;
+ i_color *line = state->linebuf;
+
+ left = 0;
+ while (left < im->xsize && ss->line[left] <= 0)
+ ++left;
+ if (left < im->xsize) {
+ right = im->xsize;
+ /* since going from the left found something, moving from the
+ right should */
+ while (/* right > left && */ ss->line[right-1] <= 0)
+ --right;
+
+ (state->fill->fill_with_color)(state->fill, left, y, right-left,
+ im->channels, fillbuf);
+ i_glin(im, left, right, y, line);
+ pos = 0;
+ if (state->fill->combine) {
+ for (x = left; x < right; ++x) {
+ tv = saturate(ss->line[x]);
+ fillbuf[pos].channel[3] =
+ fillbuf[pos].channel[3] * tv / 255;
+ }
+ (state->fill->combine)(line, fillbuf, im->channels, right-left);
+ pos++;
+ }
+ else {
+ for (x = left; x < right; ++x) {
+ tv = saturate(ss->line[x]);
+ if (tv) {
+ if (tv == 255) {
+ line[pos] = fillbuf[pos];
+ }
+ else {
+ i_color *to = line + pos;
+ i_color *from = fillbuf + pos;
+ for (ch = 0; ch < im->channels; ++ch) {
+ to->channel[ch] = (tv * from->channel[ch] +
+ (255 - tv) * to->channel[ch]) / 255;
+ }
+ }
+ }
+ pos++;
+ }
+ }
+ i_plin(im, left, right, y, line);
+ }
+}
+
+struct poly_cfill_state_f {
+ i_fcolor *fillbuf;
+ i_fcolor *linebuf;
+ int *cover;
+ i_fill_t *fill;
+};
+
+void
+scanline_flush_cfill_f(i_img *im, ss_scanline *ss, int y, void *ctx) {
+ int x, ch, tv;
+ int pos;
+ int left, right;
+ struct poly_cfill_state_f *state = (struct poly_cfill_state_f *)ctx;
+ i_fcolor *fillbuf = state->fillbuf;
+ i_fcolor *line = state->linebuf;
+
+ left = 0;
+ while (left < im->xsize && ss->line[left] <= 0)
+ ++left;
+ if (left < im->xsize) {
+ right = im->xsize;
+ /* since going from the left found something, moving from the
+ right should */
+ while (/* right > left && */ ss->line[right-1] <= 0)
+ --right;
+
+ (state->fill->fill_with_fcolor)(state->fill, left, y, right-left,
+ im->channels, fillbuf);
+ i_glinf(im, left, right, y, line);
+ pos = 0;
+ if (state->fill->combinef) {
+ for (x = left; x < right; ++x) {
+ tv = saturate(ss->line[x]);
+ fillbuf[pos].channel[3] =
+ fillbuf[pos].channel[3] * tv / 255;
+ }
+ (state->fill->combinef)(line, fillbuf, im->channels, right-left);
+ pos++;
+ }
+ else {
+ for (x = left; x < right; ++x) {
+ tv = saturate(ss->line[x]);
+ if (tv) {
+ if (tv == 255) {
+ line[pos] = fillbuf[pos];
+ }
+ else {
+ i_fcolor *to = line + pos;
+ i_fcolor *from = fillbuf + pos;
+ for (ch = 0; ch < im->channels; ++ch) {
+ to->channel[ch] = (tv * from->channel[ch] +
+ (255 - tv) * to->channel[ch]) / 255;
+ }
+ }
+ }
+ pos++;
+ }
+ }
+ i_plinf(im, left, right, y, line);
+ }
+}
+
+void
+i_poly_aa_cfill(i_img *im, int l, double *x, double *y, i_fill_t *fill) {
+ if (im->bits == i_8_bits && fill->fill_with_color) {
+ struct poly_cfill_state ctx;
+ ctx.fillbuf = mymalloc(sizeof(i_color) * im->xsize * 2);
+ ctx.linebuf = ctx.fillbuf + im->xsize;
+ ctx.cover = mymalloc(sizeof(int) * im->xsize);
+ ctx.fill = fill;
+ i_poly_aa_low(im, l, x, y, &ctx, scanline_flush_cfill);
+ myfree(ctx.fillbuf);
+ myfree(ctx.cover);
+ }
+ else {
+ struct poly_cfill_state_f ctx;
+ ctx.fillbuf = mymalloc(sizeof(i_fcolor) * im->xsize * 2);
+ ctx.linebuf = ctx.fillbuf + im->xsize;
+ ctx.cover = mymalloc(sizeof(int) * im->xsize);
+ ctx.fill = fill;
+ i_poly_aa_low(im, l, x, y, &ctx, scanline_flush_cfill_f);
+ myfree(ctx.fillbuf);
+ myfree(ctx.cover);
+ }
+}
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
-BEGIN { $| = 1; print "1..7\n"; }
+BEGIN { $| = 1; print "1..9\n"; }
END {print "not ok 1\n" unless $loaded;}
use Imager qw(:all);
print "ok 7\n";
-malloc_state();
-
-
-
-
-
-
-
-
-
-
+$img = Imager->new(xsize=>300, ysize=>300);
+$img->polygon(fill=>{ hatch=>'cross1', fg=>'00FF00', bg=>'0000FF', dx=>3 },
+ points => [
+ translate(150,150,
+ scale(70,70,
+ get_polygon('wavycircle', 32*8, sub { 1+1*cos(4*$_) })))
+ ],
+ ) or die $img->errstr();
+$img->write(file=>"testout/t75wave_fill.ppm") or die $img->errstr;
+
+print "ok 8\n";
+
+$img = Imager->new(xsize=>300, ysize=>300, bits=>16);
+$img->polygon(fill=>{ hatch=>'cross1', fg=>'00FF00', bg=>'0000FF' },
+ points => [
+ translate(150,150,
+ scale(70,70,
+ get_polygon('wavycircle', 32*8, sub { 1+1*cos(5*$_) })))
+ ],
+ ) or die $img->errstr();
+$img->write(file=>"testout/t75wave_fill16.ppm") or die $img->errstr;
+
+print "ok 9\n";
+malloc_state();