2 * $Id: brush.c 10455 2007-04-04 13:18:41Z campbellbarton $
4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
35 #include "MEM_guardedalloc.h"
37 #include "DNA_brush_types.h"
38 #include "DNA_image_types.h"
39 #include "DNA_texture_types.h"
40 #include "DNA_scene_types.h"
42 #include "BLI_arithb.h"
43 #include "BLI_blenlib.h"
45 #include "BKE_brush.h"
46 #include "BKE_global.h"
47 #include "BKE_library.h"
49 #include "BKE_texture.h"
50 #include "BKE_utildefines.h"
52 #include "IMB_imbuf.h"
53 #include "IMB_imbuf_types.h"
55 #include "RE_render_ext.h" /* externtex */
57 /* Datablock add/copy/free/make_local */
59 Brush
*add_brush(char *name
)
63 brush
= alloc_libblock(&G
.main
->brush
, ID_BR
, name
);
70 brush
->spacing
= 10.0f
;
72 brush
->innerradius
= 0.5f
;
73 brush
->clone
.alpha
= 0.5;
75 /* enable fake user by default */
76 brush
->id
.flag
|= LIB_FAKEUSER
;
77 brush_toggled_fake_user(brush
);
82 Brush
*copy_brush(Brush
*brush
)
88 brushn
= copy_libblock(brush
);
90 for(a
=0; a
<MAX_MTEX
; a
++) {
93 brushn
->mtex
[a
]= MEM_dupallocN(mtex
);
94 if(mtex
->tex
) id_us_plus((ID
*)mtex
->tex
);
98 /* enable fake user by default */
99 if (!(brushn
->id
.flag
& LIB_FAKEUSER
)) {
100 brushn
->id
.flag
|= LIB_FAKEUSER
;
101 brush_toggled_fake_user(brushn
);
107 /* not brush itself */
108 void free_brush(Brush
*brush
)
113 for(a
=0; a
<MAX_MTEX
; a
++) {
114 mtex
= brush
->mtex
[a
];
116 if(mtex
->tex
) mtex
->tex
->id
.us
--;
122 void make_local_brush(Brush
*brush
)
124 /* - only lib users: do nothing
125 * - only local users: set flag
131 int local
= 0, lib
= 0;
133 if(brush
->id
.lib
==0) return;
135 if(brush
->clone
.image
) {
136 /* special case: ima always local immediately */
137 brush
->clone
.image
->id
.lib
= 0;
138 brush
->clone
.image
->id
.flag
= LIB_LOCAL
;
139 new_id(0, (ID
*)brush
->clone
.image
, 0);
142 for(scene
= G
.main
->scene
.first
; scene
; scene
=scene
->id
.next
)
143 if(scene
->toolsettings
->imapaint
.brush
==brush
) {
144 if(scene
->id
.lib
) lib
= 1;
148 if(local
&& lib
==0) {
150 brush
->id
.flag
= LIB_LOCAL
;
151 new_id(0, (ID
*)brush
, 0);
153 /* enable fake user by default */
154 if (!(brush
->id
.flag
& LIB_FAKEUSER
)) {
155 brush
->id
.flag
|= LIB_FAKEUSER
;
156 brush_toggled_fake_user(brush
);
159 else if(local
&& lib
) {
160 brushn
= copy_brush(brush
);
161 brushn
->id
.us
= 1; /* only keep fake user */
162 brushn
->id
.flag
|= LIB_FAKEUSER
;
164 for(scene
= G
.main
->scene
.first
; scene
; scene
=scene
->id
.next
)
165 if(scene
->toolsettings
->imapaint
.brush
==brush
)
166 if(scene
->id
.lib
==0) {
167 scene
->toolsettings
->imapaint
.brush
= brushn
;
174 /* Library Operations */
176 int brush_set_nr(Brush
**current_brush
, int nr
)
180 id
= (ID
*)(*current_brush
);
181 idtest
= (ID
*)BLI_findlink(&G
.main
->brush
, nr
-1);
183 if(idtest
==0) { /* new brush */
184 if(id
) idtest
= (ID
*)copy_brush((Brush
*)id
);
185 else idtest
= (ID
*)add_brush("Brush");
189 brush_delete(current_brush
);
190 *current_brush
= (Brush
*)idtest
;
199 int brush_delete(Brush
**current_brush
)
201 if (*current_brush
) {
202 (*current_brush
)->id
.us
--;
203 *current_brush
= NULL
;
211 void brush_toggled_fake_user(Brush
*brush
)
215 if(id
->flag
& LIB_FAKEUSER
) {
223 int brush_texture_set_nr(Brush
*brush
, int nr
)
225 ID
*idtest
, *id
=NULL
;
227 if(brush
->mtex
[brush
->texact
])
228 id
= (ID
*)brush
->mtex
[brush
->texact
]->tex
;
230 idtest
= (ID
*)BLI_findlink(&G
.main
->tex
, nr
-1);
231 if(idtest
==0) { /* new tex */
232 if(id
) idtest
= (ID
*)copy_texture((Tex
*)id
);
233 else idtest
= (ID
*)add_texture("Tex");
237 brush_texture_delete(brush
);
239 if(brush
->mtex
[brush
->texact
]==NULL
) {
240 brush
->mtex
[brush
->texact
]= add_mtex();
241 brush
->mtex
[brush
->texact
]->r
= 1.0f
;
242 brush
->mtex
[brush
->texact
]->g
= 1.0f
;
243 brush
->mtex
[brush
->texact
]->b
= 1.0f
;
245 brush
->mtex
[brush
->texact
]->tex
= (Tex
*)idtest
;
254 int brush_texture_delete(Brush
*brush
)
256 if(brush
->mtex
[brush
->texact
]) {
257 if(brush
->mtex
[brush
->texact
]->tex
)
258 brush
->mtex
[brush
->texact
]->tex
->id
.us
--;
259 MEM_freeN(brush
->mtex
[brush
->texact
]);
260 brush
->mtex
[brush
->texact
]= NULL
;
268 int brush_clone_image_set_nr(Brush
*brush
, int nr
)
270 if(brush
&& nr
> 0) {
271 Image
*ima
= (Image
*)BLI_findlink(&G
.main
->image
, nr
-1);
274 brush_clone_image_delete(brush
);
275 brush
->clone
.image
= ima
;
276 id_us_plus(&ima
->id
);
277 brush
->clone
.offset
[0]= brush
->clone
.offset
[1]= 0.0f
;
286 int brush_clone_image_delete(Brush
*brush
)
288 if (brush
&& brush
->clone
.image
) {
289 brush
->clone
.image
->id
.us
--;
290 brush
->clone
.image
= NULL
;
297 void brush_check_exists(Brush
**brush
)
300 brush_set_nr(brush
, 1);
305 /*static float taylor_approx_cos(float f)
308 f = 1.0f - f/2.0f + f*f/24.0f;
312 float brush_sample_falloff(Brush
*brush
, float dist
)
314 float a
, outer
, inner
;
316 outer
= brush
->size
>> 1;
317 inner
= outer
*brush
->innerradius
;
322 else if ((dist
< outer
) && (inner
< outer
)) {
323 a
= sqrt((dist
- inner
)/(outer
- inner
));
324 return (1 - a
)*brush
->alpha
;
326 /* formula used by sculpt, with taylor approx
327 a = 0.5f*(taylor_approx_cos(3.0f*(dist - inner)/(outer - inner)) + 1.0f);
328 return a*brush->alpha; */
334 void brush_sample_tex(Brush
*brush
, float *xy
, float *rgba
)
336 MTex
*mtex
= brush
->mtex
[brush
->texact
];
338 if (mtex
&& mtex
->tex
) {
339 float co
[3], tin
, tr
, tg
, tb
, ta
;
342 co
[0]= xy
[0]/(brush
->size
>> 1);
343 co
[1]= xy
[1]/(brush
->size
>> 1);
346 hasrgb
= externtex(mtex
, co
, &tin
, &tr
, &tg
, &tb
, &ta
);
362 rgba
[0]= rgba
[1]= rgba
[2]= rgba
[3]= 1.0f
;
365 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
367 void brush_imbuf_new(Brush
*brush
, short flt
, short texfall
, int size
, ImBuf
**outbuf
)
370 float xy
[2], dist
, rgba
[4], *dstf
;
371 int x
, y
, rowbytes
, xoff
, yoff
, imbflag
;
374 imbflag
= (flt
)? IB_rectfloat
: IB_rect
;
375 xoff
= -size
/2.0f
+ 0.5f
;
376 yoff
= -size
/2.0f
+ 0.5f
;
382 ibuf
= IMB_allocImBuf(size
, size
, 32, imbflag
, 0);
385 for (y
=0; y
< ibuf
->y
; y
++) {
386 dstf
= ibuf
->rect_float
+ y
*rowbytes
;
388 for (x
=0; x
< ibuf
->x
; x
++, dstf
+=4) {
393 dist
= sqrt(xy
[0]*xy
[0] + xy
[1]*xy
[1]);
395 VECCOPY(dstf
, brush
->rgb
);
396 dstf
[3]= brush_sample_falloff(brush
, dist
);
398 else if (texfall
== 1) {
399 brush_sample_tex(brush
, xy
, dstf
);
402 dist
= sqrt(xy
[0]*xy
[0] + xy
[1]*xy
[1]);
404 brush_sample_tex(brush
, xy
, rgba
);
406 dstf
[0] = rgba
[0]*brush
->rgb
[0];
407 dstf
[1] = rgba
[1]*brush
->rgb
[1];
408 dstf
[2] = rgba
[2]*brush
->rgb
[2];
409 dstf
[3] = rgba
[3]*brush_sample_falloff(brush
, dist
);
415 crgb
[0]= FTOCHAR(brush
->rgb
[0]);
416 crgb
[1]= FTOCHAR(brush
->rgb
[1]);
417 crgb
[2]= FTOCHAR(brush
->rgb
[2]);
419 for (y
=0; y
< ibuf
->y
; y
++) {
420 dst
= (char*)ibuf
->rect
+ y
*rowbytes
;
422 for (x
=0; x
< ibuf
->x
; x
++, dst
+=4) {
427 dist
= sqrt(xy
[0]*xy
[0] + xy
[1]*xy
[1]);
432 dst
[3]= FTOCHAR(brush_sample_falloff(brush
, dist
));
434 else if (texfall
== 1) {
435 brush_sample_tex(brush
, xy
, rgba
);
436 dst
[0]= FTOCHAR(rgba
[0]);
437 dst
[1]= FTOCHAR(rgba
[1]);
438 dst
[2]= FTOCHAR(rgba
[2]);
439 dst
[3]= FTOCHAR(rgba
[3]);
442 dist
= sqrt(xy
[0]*xy
[0] + xy
[1]*xy
[1]);
444 brush_sample_tex(brush
, xy
, rgba
);
445 dst
[0] = FTOCHAR(rgba
[0]*brush
->rgb
[0]);
446 dst
[1] = FTOCHAR(rgba
[1]*brush
->rgb
[1]);
447 dst
[2] = FTOCHAR(rgba
[2]*brush
->rgb
[2]);
448 dst
[3] = FTOCHAR(rgba
[3]*brush_sample_falloff(brush
, dist
));
459 typedef struct BrushPainterCache
{
462 int size
; /* size override, if 0 uses brush->size */
463 short flt
; /* need float imbuf? */
464 short texonly
; /* no alpha, color or fallof, only texture in imbuf */
468 float lastinnerradius
;
475 struct BrushPainter
{
478 float lastmousepos
[2]; /* mouse position of last paint call */
480 float accumdistance
; /* accumulated distance of brush since last paint op */
481 float lastpaintpos
[2]; /* position of last paint op */
482 float startpaintpos
[2]; /* position of first paint */
484 double accumtime
; /* accumulated time since last paint op (airbrush) */
485 double lasttime
; /* time of last update */
489 short firsttouch
; /* first paint op */
493 float startinnerradius
;
496 BrushPainterCache cache
;
499 BrushPainter
*brush_painter_new(Brush
*brush
)
501 BrushPainter
*painter
= MEM_callocN(sizeof(BrushPainter
), "BrushPainter");
503 painter
->brush
= brush
;
504 painter
->firsttouch
= 1;
505 painter
->cache
.lastsize
= -1; /* force ibuf create in refresh */
507 painter
->startsize
= brush
->size
;
508 painter
->startalpha
= brush
->alpha
;
509 painter
->startinnerradius
= brush
->innerradius
;
510 painter
->startspacing
= brush
->spacing
;
515 void brush_painter_require_imbuf(BrushPainter
*painter
, short flt
, short texonly
, int size
)
517 if ((painter
->cache
.flt
!= flt
) || (painter
->cache
.size
!= size
) ||
518 ((painter
->cache
.texonly
!= texonly
) && texonly
)) {
519 if (painter
->cache
.ibuf
) IMB_freeImBuf(painter
->cache
.ibuf
);
520 if (painter
->cache
.maskibuf
) IMB_freeImBuf(painter
->cache
.maskibuf
);
521 painter
->cache
.ibuf
= painter
->cache
.maskibuf
= NULL
;
522 painter
->cache
.lastsize
= -1; /* force ibuf create in refresh */
525 if (painter
->cache
.flt
!= flt
) {
526 if (painter
->cache
.texibuf
) IMB_freeImBuf(painter
->cache
.texibuf
);
527 painter
->cache
.texibuf
= NULL
;
528 painter
->cache
.lastsize
= -1; /* force ibuf create in refresh */
531 painter
->cache
.size
= size
;
532 painter
->cache
.flt
= flt
;
533 painter
->cache
.texonly
= texonly
;
534 painter
->cache
.enabled
= 1;
537 void brush_painter_free(BrushPainter
*painter
)
539 Brush
*brush
= painter
->brush
;
541 brush
->size
= painter
->startsize
;
542 brush
->alpha
= painter
->startalpha
;
543 brush
->innerradius
= painter
->startinnerradius
;
544 brush
->spacing
= painter
->startspacing
;
546 if (painter
->cache
.ibuf
) IMB_freeImBuf(painter
->cache
.ibuf
);
547 if (painter
->cache
.texibuf
) IMB_freeImBuf(painter
->cache
.texibuf
);
548 if (painter
->cache
.maskibuf
) IMB_freeImBuf(painter
->cache
.maskibuf
);
552 static void brush_painter_do_partial(BrushPainter
*painter
, ImBuf
*oldtexibuf
, int x
, int y
, int w
, int h
, int xt
, int yt
, float *pos
)
554 Brush
*brush
= painter
->brush
;
555 ImBuf
*ibuf
, *maskibuf
, *texibuf
;
556 float *bf
, *mf
, *tf
, *otf
=NULL
, xoff
, yoff
, xy
[2], rgba
[4];
557 char *b
, *m
, *t
, *ot
= NULL
;
558 int dotexold
, origx
= x
, origy
= y
;
560 xoff
= -brush
->size
/2.0f
+ 0.5f
;
561 yoff
= -brush
->size
/2.0f
+ 0.5f
;
562 xoff
+= (int)pos
[0] - (int)painter
->startpaintpos
[0];
563 yoff
+= (int)pos
[1] - (int)painter
->startpaintpos
[1];
565 ibuf
= painter
->cache
.ibuf
;
566 texibuf
= painter
->cache
.texibuf
;
567 maskibuf
= painter
->cache
.maskibuf
;
569 dotexold
= (oldtexibuf
!= NULL
);
571 if (painter
->cache
.flt
) {
573 bf
= ibuf
->rect_float
+ (y
*ibuf
->x
+ origx
)*4;
574 tf
= texibuf
->rect_float
+ (y
*texibuf
->x
+ origx
)*4;
575 mf
= maskibuf
->rect_float
+ (y
*maskibuf
->x
+ origx
)*4;
578 otf
= oldtexibuf
->rect_float
+ ((y
- origy
+ yt
)*oldtexibuf
->x
+ xt
)*4;
580 for (x
=origx
; x
< w
; x
++, bf
+=4, mf
+=4, tf
+=4) {
590 brush_sample_tex(brush
, xy
, tf
);
602 b
= (char*)ibuf
->rect
+ (y
*ibuf
->x
+ origx
)*4;
603 t
= (char*)texibuf
->rect
+ (y
*texibuf
->x
+ origx
)*4;
604 m
= (char*)maskibuf
->rect
+ (y
*maskibuf
->x
+ origx
)*4;
607 ot
= (char*)oldtexibuf
->rect
+ ((y
- origy
+ yt
)*oldtexibuf
->x
+ xt
)*4;
609 for (x
=origx
; x
< w
; x
++, b
+=4, m
+=4, t
+=4) {
621 brush_sample_tex(brush
, xy
, rgba
);
622 t
[0]= FTOCHAR(rgba
[0]);
623 t
[1]= FTOCHAR(rgba
[1]);
624 t
[2]= FTOCHAR(rgba
[2]);
625 t
[3]= FTOCHAR(rgba
[3]);
628 b
[0] = t
[0]*m
[0]/255;
629 b
[1] = t
[1]*m
[1]/255;
630 b
[2] = t
[2]*m
[2]/255;
631 b
[3] = t
[3]*m
[3]/255;
637 void brush_painter_fixed_tex_partial_update(BrushPainter
*painter
, float *pos
)
639 Brush
*brush
= painter
->brush
;
640 BrushPainterCache
*cache
= &painter
->cache
;
641 ImBuf
*oldtexibuf
, *ibuf
;
642 int imbflag
, destx
, desty
, srcx
, srcy
, w
, h
, x1
, y1
, x2
, y2
;
644 imbflag
= (cache
->flt
)? IB_rectfloat
: IB_rect
;
646 cache
->ibuf
= IMB_allocImBuf(brush
->size
, brush
->size
, 32, imbflag
, 0);
649 oldtexibuf
= cache
->texibuf
;
650 cache
->texibuf
= IMB_allocImBuf(brush
->size
, brush
->size
, 32, imbflag
, 0);
654 destx
= (int)painter
->lastpaintpos
[0] - (int)pos
[0];
655 desty
= (int)painter
->lastpaintpos
[1] - (int)pos
[1];
659 IMB_rectclip(cache
->texibuf
, oldtexibuf
, &destx
, &desty
, &srcx
, &srcy
, &w
, &h
);
672 /* blend existing texture in new position */
673 if ((x1
< x2
) && (y1
< y2
))
674 brush_painter_do_partial(painter
, oldtexibuf
, x1
, y1
, x2
, y2
, srcx
, srcy
, pos
);
677 IMB_freeImBuf(oldtexibuf
);
679 /* sample texture in new areas */
680 if ((0 < x1
) && (0 < ibuf
->y
))
681 brush_painter_do_partial(painter
, NULL
, 0, 0, x1
, ibuf
->y
, 0, 0, pos
);
682 if ((x2
< ibuf
->x
) && (0 < ibuf
->y
))
683 brush_painter_do_partial(painter
, NULL
, x2
, 0, ibuf
->x
, ibuf
->y
, 0, 0, pos
);
684 if ((x1
< x2
) && (0 < y1
))
685 brush_painter_do_partial(painter
, NULL
, x1
, 0, x2
, y1
, 0, 0, pos
);
686 if ((x1
< x2
) && (y2
< ibuf
->y
))
687 brush_painter_do_partial(painter
, NULL
, x1
, y2
, x2
, ibuf
->y
, 0, 0, pos
);
690 static void brush_painter_refresh_cache(BrushPainter
*painter
, float *pos
)
692 Brush
*brush
= painter
->brush
;
693 BrushPainterCache
*cache
= &painter
->cache
;
694 MTex
*mtex
= brush
->mtex
[brush
->texact
];
698 if ((brush
->size
!= cache
->lastsize
) || (brush
->alpha
!= cache
->lastalpha
)
699 || (brush
->innerradius
!= cache
->lastinnerradius
)) {
701 IMB_freeImBuf(cache
->ibuf
);
704 if (cache
->maskibuf
) {
705 IMB_freeImBuf(cache
->maskibuf
);
706 cache
->maskibuf
= NULL
;
710 size
= (cache
->size
)? cache
->size
: brush
->size
;
712 if (!(mtex
&& mtex
->tex
) || (mtex
->tex
->type
==0)) {
713 brush_imbuf_new(brush
, flt
, 0, size
, &cache
->ibuf
);
715 else if (brush
->flag
& BRUSH_FIXED_TEX
) {
716 brush_imbuf_new(brush
, flt
, 0, size
, &cache
->maskibuf
);
717 brush_painter_fixed_tex_partial_update(painter
, pos
);
720 brush_imbuf_new(brush
, flt
, 2, size
, &cache
->ibuf
);
722 cache
->lastsize
= brush
->size
;
723 cache
->lastalpha
= brush
->alpha
;
724 cache
->lastinnerradius
= brush
->innerradius
;
726 else if ((brush
->flag
& BRUSH_FIXED_TEX
) && mtex
&& mtex
->tex
) {
727 int dx
= (int)painter
->lastpaintpos
[0] - (int)pos
[0];
728 int dy
= (int)painter
->lastpaintpos
[1] - (int)pos
[1];
730 if ((dx
!= 0) || (dy
!= 0))
731 brush_painter_fixed_tex_partial_update(painter
, pos
);
735 void brush_painter_break_stroke(BrushPainter
*painter
)
737 painter
->firsttouch
= 1;
740 static void brush_apply_pressure(BrushPainter
*painter
, Brush
*brush
, float pressure
)
742 if (brush
->flag
& BRUSH_ALPHA_PRESSURE
)
743 brush
->alpha
= MAX2(0.0, painter
->startalpha
*pressure
);
744 if (brush
->flag
& BRUSH_SIZE_PRESSURE
)
745 brush
->size
= MAX2(1.0, painter
->startsize
*pressure
);
746 if (brush
->flag
& BRUSH_RAD_PRESSURE
)
747 brush
->innerradius
= MAX2(0.0, painter
->startinnerradius
*pressure
);
748 if (brush
->flag
& BRUSH_SPACING_PRESSURE
)
749 brush
->spacing
= MAX2(1.0, painter
->startspacing
*(1.5f
-pressure
));
752 int brush_painter_paint(BrushPainter
*painter
, BrushFunc func
, float *pos
, double time
, float pressure
, void *user
)
754 Brush
*brush
= painter
->brush
;
757 if (pressure
== 0.0f
)
758 pressure
= 1.0f
; /* zero pressure == not using tablet */
760 if (painter
->firsttouch
) {
761 /* paint exactly once on first touch */
762 painter
->startpaintpos
[0]= pos
[0];
763 painter
->startpaintpos
[1]= pos
[1];
765 brush_apply_pressure(painter
, brush
, pressure
);
766 if (painter
->cache
.enabled
)
767 brush_painter_refresh_cache(painter
, pos
);
768 totpaintops
+= func(user
, painter
->cache
.ibuf
, pos
, pos
);
770 painter
->lasttime
= time
;
771 painter
->firsttouch
= 0;
772 painter
->lastpaintpos
[0]= pos
[0];
773 painter
->lastpaintpos
[1]= pos
[1];
776 else if (painter
->brush
->flag
& BRUSH_AIRBRUSH
) {
777 float spacing
, step
, paintpos
[2], dmousepos
[2], len
;
778 double starttime
, curtime
= time
;
780 /* compute brush spacing adapted to brush size */
781 spacing
= brush
->rate
; //brush->size*brush->spacing*0.01f;
783 /* setup starting time, direction vector and accumulated time */
784 starttime
= painter
->accumtime
;
785 Vec2Subf(dmousepos
, pos
, painter
->lastmousepos
);
786 len
= Normalize2(dmousepos
);
787 painter
->accumtime
+= curtime
- painter
->lasttime
;
789 /* do paint op over unpainted time distance */
790 while (painter
->accumtime
>= spacing
) {
791 step
= (spacing
- starttime
)*len
;
792 paintpos
[0]= painter
->lastmousepos
[0] + dmousepos
[0]*step
;
793 paintpos
[1]= painter
->lastmousepos
[1] + dmousepos
[1]*step
;
795 if (painter
->cache
.enabled
)
796 brush_painter_refresh_cache(painter
);
797 totpaintops
+= func(user
, painter
->cache
.ibuf
,
798 painter
->lastpaintpos
, paintpos
);
800 painter
->lastpaintpos
[0]= paintpos
[0];
801 painter
->lastpaintpos
[1]= paintpos
[1];
802 painter
->accumtime
-= spacing
;
803 starttime
-= spacing
;
806 painter
->lasttime
= curtime
;
810 float startdistance
, spacing
, step
, paintpos
[2], dmousepos
[2];
813 /* compute brush spacing adapted to brush size, spacing may depend
814 on pressure, so update it */
815 brush_apply_pressure(painter
, brush
, painter
->lastpressure
);
816 spacing
= MAX2(1.0f
, brush
->size
)*brush
->spacing
*0.01f
;
818 /* setup starting distance, direction vector and accumulated distance */
819 startdistance
= painter
->accumdistance
;
820 Vec2Subf(dmousepos
, pos
, painter
->lastmousepos
);
821 len
= Normalize2(dmousepos
);
822 painter
->accumdistance
+= len
;
824 /* do paint op over unpainted distance */
825 while ((len
> 0.0f
) && (painter
->accumdistance
>= spacing
)) {
826 step
= spacing
- startdistance
;
827 paintpos
[0]= painter
->lastmousepos
[0] + dmousepos
[0]*step
;
828 paintpos
[1]= painter
->lastmousepos
[1] + dmousepos
[1]*step
;
831 press
= (1.0f
-t
)*painter
->lastpressure
+ t
*pressure
;
832 brush_apply_pressure(painter
, brush
, press
);
833 spacing
= MAX2(1.0f
, brush
->size
)*brush
->spacing
*0.01f
;
835 if (painter
->cache
.enabled
)
836 brush_painter_refresh_cache(painter
, paintpos
);
839 func(user
, painter
->cache
.ibuf
, painter
->lastpaintpos
, paintpos
);
841 painter
->lastpaintpos
[0]= paintpos
[0];
842 painter
->lastpaintpos
[1]= paintpos
[1];
843 painter
->accumdistance
-= spacing
;
844 startdistance
-= spacing
;
847 /* do airbrush paint ops, based on the number of paint ops left over
848 from regular painting. this is a temporary solution until we have
849 accurate time stamps for mouse move events */
850 if (brush
->flag
& BRUSH_AIRBRUSH
) {
851 double curtime
= time
;
852 double painttime
= brush
->rate
*totpaintops
;
854 painter
->accumtime
+= curtime
- painter
->lasttime
;
855 if (painter
->accumtime
<= painttime
)
856 painter
->accumtime
= 0.0;
858 painter
->accumtime
-= painttime
;
860 while (painter
->accumtime
>= brush
->rate
) {
861 brush_apply_pressure(painter
, brush
, pressure
);
862 if (painter
->cache
.enabled
)
863 brush_painter_refresh_cache(painter
, paintpos
);
865 func(user
, painter
->cache
.ibuf
, painter
->lastmousepos
, pos
);
866 painter
->accumtime
-= brush
->rate
;
869 painter
->lasttime
= curtime
;
873 painter
->lastmousepos
[0]= pos
[0];
874 painter
->lastmousepos
[1]= pos
[1];
875 painter
->lastpressure
= pressure
;
877 brush
->alpha
= painter
->startalpha
;
878 brush
->size
= painter
->startsize
;
879 brush
->innerradius
= painter
->startinnerradius
;
880 brush
->spacing
= painter
->startspacing
;