Exemplo n.º 1
0
/* Brush Sampling */
void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread)
{
	MTex *mtex= &brush->mtex;

	if (mtex && mtex->tex) {
		float co[3], tin, tr, tg, tb, ta;
		int hasrgb;
		const int radius= brush_size(brush);

		co[0]= xy[0]/radius;
		co[1]= xy[1]/radius;
		co[2]= 0.0f;

		hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread);

		if (hasrgb) {
			rgba[0]= tr;
			rgba[1]= tg;
			rgba[2]= tb;
			rgba[3]= ta;
		}
		else {
			rgba[0]= tin;
			rgba[1]= tin;
			rgba[2]= tin;
			rgba[3]= 1.0f;
		}
	}
	else if (rgba)
		rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f;
}
Exemplo n.º 2
0
void brush_jitter_pos(Brush *brush, float pos[2], float jitterpos[2])
{
	int use_jitter= brush->jitter != 0;

	/* jitter-ed brush gives weird and unpredictable result for this
	   kinds of stroke, so manyally disable jitter usage (sergey) */
	use_jitter&= (brush->flag & (BRUSH_RESTORE_MESH|BRUSH_ANCHORED)) == 0;

	if(use_jitter){
		float rand_pos[2];
		const int radius= brush_size(brush);
		const int diameter= 2*radius;

		// find random position within a circle of diameter 1
		do {
			rand_pos[0] = BLI_frand()-0.5f;
			rand_pos[1] = BLI_frand()-0.5f;
		} while (len_v2(rand_pos) > 0.5f);

		jitterpos[0] = pos[0] + 2*rand_pos[0]*diameter*brush->jitter;
		jitterpos[1] = pos[1] + 2*rand_pos[1]*diameter*brush->jitter;
	}
	else {
		copy_v2_v2(jitterpos, pos);
	}
}
Exemplo n.º 3
0
static void draw_image_view_tool(Scene *scene)
{
	ToolSettings *settings= scene->toolsettings;
	Brush *brush= settings->imapaint.brush;
	int mval[2];
	float radius;
	int draw= 0;

	if(brush) {
		if(settings->imapaint.flag & IMAGEPAINT_DRAWING) {
			if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
				draw= 1;
		}
		else if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL)
			draw= 1;
		
		if(draw) {
			getmouseco_areawin(mval);

			radius= brush_size(brush)*G.sima->zoom;
			fdrawXORcirc(mval[0], mval[1], radius);

			if (brush->innerradius != 1.0) {
				radius *= brush->innerradius;
				fdrawXORcirc(mval[0], mval[1], radius);
			}
		}
	}
}
Exemplo n.º 4
0
static int load_tex(Sculpt *sd, Brush* br, ViewContext* vc)
{
	static GLuint overlay_texture = 0;
	static int init = 0;
	static int tex_changed_timestamp = -1;
	static int curve_changed_timestamp = -1;
	static Snapshot snap;
	static int old_size = -1;

	GLubyte* buffer = NULL;

	int size;
	int j;
	int refresh;

#ifndef _OPENMP
	(void)sd; /* quied unused warning */
#endif
	
	if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0;
	
	refresh = 
		!overlay_texture ||
		(br->mtex.tex && 
		    (!br->mtex.tex->preview ||
		      br->mtex.tex->preview->changed_timestamp[0] != tex_changed_timestamp)) ||
		!br->curve ||
		br->curve->changed_timestamp != curve_changed_timestamp ||
		!same_snap(&snap, br, vc);

	if (refresh) {
		if (br->mtex.tex && br->mtex.tex->preview)
			tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0];

		if (br->curve)
			curve_changed_timestamp = br->curve->changed_timestamp;

		make_snap(&snap, br, vc);

		if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) {
			int s = brush_size(br);
			int r = 1;

			for (s >>= 1; s > 0; s >>= 1)
				r++;

			size = (1<<r);

			if (size < 256)
				size = 256;

			if (size < old_size)
				size = old_size;
		}
		else
Exemplo n.º 5
0
static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos)
{
	Brush *brush= painter->brush;
	BrushPainterCache *cache= &painter->cache;
	ImBuf *oldtexibuf, *ibuf;
	int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
	const int diameter= 2*brush_size(brush);

	imbflag= (cache->flt)? IB_rectfloat: IB_rect;
	if (!cache->ibuf)
		cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);
	ibuf= cache->ibuf;

	oldtexibuf= cache->texibuf;
	cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag);

	if (oldtexibuf) {
		srcx= srcy= 0;
		destx= (int)painter->lastpaintpos[0] - (int)pos[0];
		desty= (int)painter->lastpaintpos[1] - (int)pos[1];
		w= oldtexibuf->x;
		h= oldtexibuf->y;

		IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
	}
	else {
		srcx= srcy= 0;
		destx= desty= 0;
		w= h= 0;
	}
	
	x1= destx;
	y1= desty;
	x2= destx+w;
	y2= desty+h;

	/* blend existing texture in new position */
	if ((x1 < x2) && (y1 < y2))
		brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);

	if (oldtexibuf)
		IMB_freeImBuf(oldtexibuf);

	/* sample texture in new areas */
	if ((0 < x1) && (0 < ibuf->y))
		brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
	if ((x2 < ibuf->x) && (0 < ibuf->y))
		brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
	if ((x1 < x2) && (0 < y1))
		brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
	if ((x1 < x2) && (y2 < ibuf->y))
		brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
}
Exemplo n.º 6
0
BrushPainter *brush_painter_new(Brush *brush)
{
	BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter");

	painter->brush= brush;
	painter->firsttouch= 1;
	painter->cache.lastsize= -1; /* force ibuf create in refresh */

	painter->startsize = brush_size(brush);
	painter->startalpha = brush_alpha(brush);
	painter->startjitter = brush->jitter;
	painter->startspacing = brush->spacing;

	return painter;
}
Exemplo n.º 7
0
static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int use_color_correction)
{
	Brush *brush= painter->brush;
	BrushPainterCache *cache= &painter->cache;
	MTex *mtex= &brush->mtex;
	int size;
	short flt;
	const int diameter= 2*brush_size(brush);
	const float alpha= brush_alpha(brush);

	if (diameter != cache->lastsize ||
		alpha != cache->lastalpha ||
		brush->jitter != cache->lastjitter)
	{
		if (cache->ibuf) {
			IMB_freeImBuf(cache->ibuf);
			cache->ibuf= NULL;
		}
		if (cache->maskibuf) {
			IMB_freeImBuf(cache->maskibuf);
			cache->maskibuf= NULL;
		}

		flt= cache->flt;
		size= (cache->size)? cache->size: diameter;

		if (brush->flag & BRUSH_FIXED_TEX) {
			brush_imbuf_new(brush, flt, 3, size, &cache->maskibuf, use_color_correction);
			brush_painter_fixed_tex_partial_update(painter, pos);
		}
		else
			brush_imbuf_new(brush, flt, 2, size, &cache->ibuf, use_color_correction);

		cache->lastsize= diameter;
		cache->lastalpha= alpha;
		cache->lastjitter= brush->jitter;
	}
	else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
		int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
		int dy = (int)painter->lastpaintpos[1] - (int)pos[1];

		if ((dx != 0) || (dy != 0))
			brush_painter_fixed_tex_partial_update(painter, pos);
	}
}
Exemplo n.º 8
0
static int same_snap(Snapshot* snap, Brush* brush, ViewContext* vc)
{
	MTex* mtex = &brush->mtex;

	return 
		(mtex->tex &&
		    mtex->ofs[0] == snap->ofs[0] &&
		    mtex->ofs[1] == snap->ofs[1] &&
		    mtex->ofs[2] == snap->ofs[2] &&
		    mtex->size[0] == snap->size[0] &&
		    mtex->size[1] == snap->size[1] &&
		    mtex->size[2] == snap->size[2] &&
		    mtex->rot == snap->rot) &&
		((mtex->brush_map_mode == MTEX_MAP_MODE_FIXED && brush_size(brush) <= snap->brush_size) || (brush_size(brush) == snap->brush_size)) && // make brush smaller shouldn't cause a resample
		mtex->brush_map_mode == snap->brush_map_mode &&
		vc->ar->winx == snap->winx &&
		vc->ar->winy == snap->winy;
}
Exemplo n.º 9
0
static void make_snap(Snapshot* snap, Brush* brush, ViewContext* vc)
{
	if (brush->mtex.tex) {
		snap->brush_map_mode = brush->mtex.brush_map_mode;
		copy_v3_v3(snap->ofs, brush->mtex.ofs);
		copy_v3_v3(snap->size, brush->mtex.size);
		snap->rot = brush->mtex.rot;
	}
	else {
		snap->brush_map_mode = -1;
		snap->ofs[0]= snap->ofs[1]= snap->ofs[2]= -1;
		snap->size[0]= snap->size[1]= snap->size[2]= -1;
		snap->rot = -1;
	}

	snap->brush_size = brush_size(brush);
	snap->winx = vc->ar->winx;
	snap->winy = vc->ar->winy;
}
Exemplo n.º 10
0
static int brush_scale_size_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Paint  *paint=  paint_get_active(scene);
	struct Brush  *brush=  paint_brush(paint);
	// Object *ob=     CTX_data_active_object(C);
	float   scalar= RNA_float_get(op->ptr, "scalar");

	if (brush) {
		// pixel radius
		{
			const int old_size= brush_size(scene, brush);
			int size= (int)(scalar*old_size);

			if (old_size == size) {
				if (scalar > 1) {
					size++;
				}
				else if (scalar < 1) {
					size--;
				}
			}
			CLAMP(size, 1, 2000); // XXX magic number

			brush_set_size(scene, brush, size);
		}

		// unprojected radius
		{
			float unprojected_radius= scalar*brush_unprojected_radius(scene, brush);

			if (unprojected_radius < 0.001f) // XXX magic number
				unprojected_radius= 0.001f;

			brush_set_unprojected_radius(scene, brush, unprojected_radius);
		}
	}

	return OPERATOR_FINISHED;
}
Exemplo n.º 11
0
int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user, int use_color_correction)
{
	Brush *brush= painter->brush;
	int totpaintops= 0;

	if (pressure == 0.0f) {
		if(painter->lastpressure) // XXX - hack, operator misses
			pressure= painter->lastpressure;
		else
			pressure = 1.0f;	/* zero pressure == not using tablet */
	}
	if (painter->firsttouch) {
		/* paint exactly once on first touch */
		painter->startpaintpos[0]= pos[0];
		painter->startpaintpos[1]= pos[1];

		brush_apply_pressure(painter, brush, pressure);
		if (painter->cache.enabled)
			brush_painter_refresh_cache(painter, pos, use_color_correction);
		totpaintops += func(user, painter->cache.ibuf, pos, pos);
		
		painter->lasttime= time;
		painter->firsttouch= 0;
		painter->lastpaintpos[0]= pos[0];
		painter->lastpaintpos[1]= pos[1];
	}
#if 0
	else if (painter->brush->flag & BRUSH_AIRBRUSH) {
		float spacing, step, paintpos[2], dmousepos[2], len;
		double starttime, curtime= time;

		/* compute brush spacing adapted to brush size */
		spacing= brush->rate; //radius*brush->spacing*0.01f;

		/* setup starting time, direction vector and accumulated time */
		starttime= painter->accumtime;
		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
		len= normalize_v2(dmousepos);
		painter->accumtime += curtime - painter->lasttime;

		/* do paint op over unpainted time distance */
		while (painter->accumtime >= spacing) {
			step= (spacing - starttime)*len;
			paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
			paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;

			if (painter->cache.enabled)
				brush_painter_refresh_cache(painter);
			totpaintops += func(user, painter->cache.ibuf,
				painter->lastpaintpos, paintpos);

			painter->lastpaintpos[0]= paintpos[0];
			painter->lastpaintpos[1]= paintpos[1];
			painter->accumtime -= spacing;
			starttime -= spacing;
		}
		
		painter->lasttime= curtime;
	}
#endif
	else {
		float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
		float t, len, press;
		const int radius= brush_size(brush);

		/* compute brush spacing adapted to brush radius, spacing may depend
		   on pressure, so update it */
		brush_apply_pressure(painter, brush, painter->lastpressure);
		spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;

		/* setup starting distance, direction vector and accumulated distance */
		startdistance= painter->accumdistance;
		sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
		len= normalize_v2(dmousepos);
		painter->accumdistance += len;

		if (brush->flag & BRUSH_SPACE) {
			/* do paint op over unpainted distance */
			while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
				step= spacing - startdistance;
				paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
				paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;

				t = step/len;
				press= (1.0f-t)*painter->lastpressure + t*pressure;
				brush_apply_pressure(painter, brush, press);
				spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;

				brush_jitter_pos(brush, paintpos, finalpos);

				if (painter->cache.enabled)
					brush_painter_refresh_cache(painter, finalpos, use_color_correction);

				totpaintops +=
					func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);

				painter->lastpaintpos[0]= paintpos[0];
				painter->lastpaintpos[1]= paintpos[1];
				painter->accumdistance -= spacing;
				startdistance -= spacing;
			}
		} else {
			brush_jitter_pos(brush, pos, finalpos);

			if (painter->cache.enabled)
				brush_painter_refresh_cache(painter, finalpos, use_color_correction);

			totpaintops += func(user, painter->cache.ibuf, pos, finalpos);

			painter->lastpaintpos[0]= pos[0];
			painter->lastpaintpos[1]= pos[1];
			painter->accumdistance= 0;
		}

		/* do airbrush paint ops, based on the number of paint ops left over
		   from regular painting. this is a temporary solution until we have
		   accurate time stamps for mouse move events */
		if (brush->flag & BRUSH_AIRBRUSH) {
			double curtime= time;
			double painttime= brush->rate*totpaintops;

			painter->accumtime += curtime - painter->lasttime;
			if (painter->accumtime <= painttime)
				painter->accumtime= 0.0;
			else
				painter->accumtime -= painttime;

			while (painter->accumtime >= (double)brush->rate) {
				brush_apply_pressure(painter, brush, pressure);

				brush_jitter_pos(brush, pos, finalpos);

				if (painter->cache.enabled)
					brush_painter_refresh_cache(painter, finalpos, use_color_correction);

				totpaintops +=
					func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
				painter->accumtime -= (double)brush->rate;
			}

			painter->lasttime= curtime;
		}
	}

	painter->lastmousepos[0]= pos[0];
	painter->lastmousepos[1]= pos[1];
	painter->lastpressure= pressure;

	brush_set_alpha(brush, painter->startalpha);
	brush_set_size(brush, painter->startsize);
	brush->jitter = painter->startjitter;
	brush->spacing = painter->startspacing;

	return totpaintops;
}
Exemplo n.º 12
0
static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos)
{
	Brush *brush= painter->brush;
	ImBuf *ibuf, *maskibuf, *texibuf;
	float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
	char *b, *m, *t, *ot= NULL;
	int dotexold, origx= x, origy= y;
	const int radius= brush_size(brush);

	xoff = -radius + 0.5f;
	yoff = -radius + 0.5f;
	xoff += (int)pos[0] - (int)painter->startpaintpos[0];
	yoff += (int)pos[1] - (int)painter->startpaintpos[1];

	ibuf = painter->cache.ibuf;
	texibuf = painter->cache.texibuf;
	maskibuf = painter->cache.maskibuf;

	dotexold = (oldtexibuf != NULL);

	/* not sure if it's actually needed or it's a mistake in coords/sizes
	   calculation in brush_painter_fixed_tex_partial_update(), but without this
	   limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
	w = MIN2(w, ibuf->x);
	h = MIN2(h, ibuf->y);

	if (painter->cache.flt) {
		for (; y < h; y++) {
			bf = ibuf->rect_float + (y*ibuf->x + origx)*4;
			tf = texibuf->rect_float + (y*texibuf->x + origx)*4;
			mf = maskibuf->rect_float + (y*maskibuf->x + origx)*4;

			if (dotexold)
				otf = oldtexibuf->rect_float + ((y - origy + yt)*oldtexibuf->x + xt)*4;

			for (x=origx; x < w; x++, bf+=4, mf+=4, tf+=4) {
				if (dotexold) {
					copy_v3_v3(tf, otf);
					tf[3] = otf[3];
					otf += 4;
				}
				else {
					xy[0] = x + xoff;
					xy[1] = y + yoff;

					brush_sample_tex(brush, xy, tf, 0);
				}

				bf[0] = tf[0]*mf[0];
				bf[1] = tf[1]*mf[1];
				bf[2] = tf[2]*mf[2];
				bf[3] = tf[3]*mf[3];
			}
		}
	}
	else {
		for (; y < h; y++) {
			b = (char*)ibuf->rect + (y*ibuf->x + origx)*4;
			t = (char*)texibuf->rect + (y*texibuf->x + origx)*4;
			m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4;

			if (dotexold)
				ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4;

			for (x=origx; x < w; x++, b+=4, m+=4, t+=4) {
				if (dotexold) {
					t[0] = ot[0];
					t[1] = ot[1];
					t[2] = ot[2];
					t[3] = ot[3];
					ot += 4;
				}
				else {
					xy[0] = x + xoff;
					xy[1] = y + yoff;

					brush_sample_tex(brush, xy, rgba, 0);
					t[0]= FTOCHAR(rgba[0]);
					t[1]= FTOCHAR(rgba[1]);
					t[2]= FTOCHAR(rgba[2]);
					t[3]= FTOCHAR(rgba[3]);
				}

				b[0] = t[0]*m[0]/255;
				b[1] = t[1]*m[1]/255;
				b[2] = t[2]*m[2]/255;
				b[3] = t[3]*m[3]/255;
			}
		}
	}
}
Exemplo n.º 13
0
void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
	ImBuf *ibuf;
	float xy[2], dist, rgba[4], *dstf;
	int x, y, rowbytes, xoff, yoff, imbflag;
	const int radius= brush_size(brush);
	char *dst, crgb[3];
	const float alpha= brush_alpha(brush);
	float brush_rgb[3];
    
	imbflag= (flt)? IB_rectfloat: IB_rect;
	xoff = -bufsize/2.0f + 0.5f;
	yoff = -bufsize/2.0f + 0.5f;
	rowbytes= bufsize*4;

	if (*outbuf)
		ibuf= *outbuf;
	else
		ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag);

	if (flt) {
		copy_v3_v3(brush_rgb, brush->rgb);
		if(use_color_correction){
			srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
		}

		for (y=0; y < ibuf->y; y++) {
			dstf = ibuf->rect_float + y*rowbytes;

			for (x=0; x < ibuf->x; x++, dstf+=4) {
				xy[0] = x + xoff;
				xy[1] = y + yoff;

				if (texfall == 0) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					copy_v3_v3(dstf, brush_rgb);
					dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
				}
				else if (texfall == 1) {
					brush_sample_tex(brush, xy, dstf, 0);
				}
				else {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					mul_v3_v3v3(dstf, rgba, brush_rgb);
					dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius);
				}
			}
		}
	}
	else {
		crgb[0]= FTOCHAR(brush->rgb[0]);
		crgb[1]= FTOCHAR(brush->rgb[1]);
		crgb[2]= FTOCHAR(brush->rgb[2]);

		for (y=0; y < ibuf->y; y++) {
			dst = (char*)ibuf->rect + y*rowbytes;

			for (x=0; x < ibuf->x; x++, dst+=4) {
				xy[0] = x + xoff;
				xy[1] = y + yoff;

				if (texfall == 0) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					dst[0]= crgb[0];
					dst[1]= crgb[1];
					dst[2]= crgb[2];
					dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
				}
				else if (texfall == 1) {
					brush_sample_tex(brush, xy, rgba, 0);
					dst[0]= FTOCHAR(rgba[0]);
					dst[1]= FTOCHAR(rgba[1]);
					dst[2]= FTOCHAR(rgba[2]);
					dst[3]= FTOCHAR(rgba[3]);
				}
				else if (texfall == 2) {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
					dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
					dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
					dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
				} else {
					dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);

					brush_sample_tex(brush, xy, rgba, 0);
					dst[0]= crgb[0];
					dst[1]= crgb[1];
					dst[2]= crgb[2];
					dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
				}
			}
		}
	}

	*outbuf= ibuf;
}