Пример #1
0
static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf, short tile)
{
	int destx = region->destx;
	int desty = region->desty;
	int srcx = region->srcx;
	int srcy = region->srcy;
	int width = region->width;
	int height = region->height;
	int origw, origh, w, h, tot = 0;

	/* convert destination and source coordinates to be within image */
	if (tile & PAINT_TILE_X) {
		destx = destx % dbuf->x;
		if (destx < 0) destx += dbuf->x;
		srcx = srcx % sbuf->x;
		if (srcx < 0) srcx += sbuf->x;
	}
	if (tile & PAINT_TILE_Y) {
		desty = desty % dbuf->y;
		if (desty < 0) desty += dbuf->y;
		srcy = srcy % sbuf->y;
		if (srcy < 0) srcy += sbuf->y;
	}
	/* clip width of blending area to destination imbuf, to avoid writing the
	 * same pixel twice */
	origw = w = (width > dbuf->x) ? dbuf->x : width;
	origh = h = (height > dbuf->y) ? dbuf->y : height;

	/* clip within image */
	IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
	paint_2d_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);

	/* do 3 other rects if needed */
	if ((tile & PAINT_TILE_X) && w < origw)
		paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
	if ((tile & PAINT_TILE_Y) && h < origh)
		paint_2d_set_region(&region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
	if ((tile & PAINT_TILE_X) && (tile & PAINT_TILE_Y) && (w < origw) && (h < origh))
		paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h);

	return tot;
}
Пример #2
0
static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
{
    ImagePaintRegion region[4];
    int a, tot;

    paint_2d_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
    tot = paint_2d_torus_split_region(region, ibufb, ibuf);

    for (a = 0; a < tot; a++)
        IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, 0, region[a].destx, region[a].desty,
                      region[a].destx, region[a].desty,
                      region[a].srcx, region[a].srcy,
                      region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
}
Пример #3
0
static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const float lastpos[2], const float pos[2])
{
    ImagePaintState *s = ((ImagePaintState *)state);
    ImBuf *clonebuf = NULL, *frombuf, *tmpbuf = NULL;
    ImagePaintRegion region[4];
    short torus = s->brush->flag & BRUSH_TORUS;
    short blend = s->blend;
    float *offset = s->brush->clone.offset;
    float liftpos[2];
    float brush_alpha = BKE_brush_alpha_get(s->scene, s->brush);
    unsigned short mask_max = (unsigned short)(brush_alpha * 65535.0f);
    int bpos[2], blastpos[2], bliftpos[2];
    int a, tot;

    paint_2d_convert_brushco(ibufb, pos, bpos);

    /* lift from canvas */
    if (s->tool == PAINT_TOOL_SOFTEN) {
        paint_2d_lift_soften(s->canvas, ibufb, bpos, torus);
    }
    else if (s->tool == PAINT_TOOL_SMEAR) {
        if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
            return 0;

        paint_2d_convert_brushco(ibufb, lastpos, blastpos);
        paint_2d_lift_smear(s->canvas, ibufb, blastpos);
    }
    else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
        liftpos[0] = pos[0] - offset[0] * s->canvas->x;
        liftpos[1] = pos[1] - offset[1] * s->canvas->y;

        paint_2d_convert_brushco(ibufb, liftpos, bliftpos);
        clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos);
    }

    frombuf = (clonebuf) ? clonebuf : ibufb;

    if (torus) {
        paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
        tot = paint_2d_torus_split_region(region, s->canvas, frombuf);
    }
    else {
        paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
        tot = 1;
    }

    if (s->do_masking)
        tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);

    /* blend into canvas */
    for (a = 0; a < tot; a++) {
        ED_imapaint_dirty_region(s->image, s->canvas,
                                 region[a].destx, region[a].desty,
                                 region[a].width, region[a].height);

        if (s->do_masking) {
            /* masking, find original pixels tiles from undo buffer to composite over */
            int tilex, tiley, tilew, tileh, tx, ty;

            imapaint_region_tiles(s->canvas, region[a].destx, region[a].desty,
                                  region[a].width, region[a].height,
                                  &tilex, &tiley, &tilew, &tileh);

            for (ty = tiley; ty <= tileh; ty++) {
                for (tx = tilex; tx <= tilew; tx++) {
                    /* retrieve original pixels + mask from undo buffer */
                    unsigned short *mask;
                    int origx = region[a].destx - tx * IMAPAINT_TILE_SIZE;
                    int origy = region[a].desty - ty * IMAPAINT_TILE_SIZE;

                    if (s->canvas->rect_float)
                        tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask);
                    else
                        tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask);

                    IMB_rectblend(s->canvas, tmpbuf, frombuf, mask,
                                  maskb, mask_max,
                                  region[a].destx, region[a].desty,
                                  origx, origy,
                                  region[a].srcx, region[a].srcy,
                                  region[a].width, region[a].height, blend);
                }
            }
        }
        else {
            /* no masking, composite brush directly onto canvas */
            IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, NULL, 0,
                          region[a].destx, region[a].desty,
                          region[a].destx, region[a].desty,
                          region[a].srcx, region[a].srcy,
                          region[a].width, region[a].height, blend);
        }
    }

    if (clonebuf) IMB_freeImBuf(clonebuf);
    if (tmpbuf) IMB_freeImBuf(tmpbuf);

    return 1;
}