mirror of https://github.com/GNOME/gimp.git
Correct scaling of brush pipes and pixmap brushes.
--Sven
This commit is contained in:
parent
d21d00be23
commit
831b75e301
|
@ -1,3 +1,12 @@
|
|||
Thu Sep 9 21:02:46 MEST 1999 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/airbrush.c
|
||||
* app/gimpbrushpipe.[ch]
|
||||
* app/paint_core.[ch]
|
||||
* app/paintbrush.c
|
||||
* app/pencil.c: scaling of brush pipes should now work correctly.
|
||||
Needs a little bit of optimization though...
|
||||
|
||||
Thu Sep 9 19:16:25 MEST 1999 Simon Budig <Simon.Budig@unix-ag.org>
|
||||
(checked in by Sven Neumann <sven@gimp.org>)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushlist.h"
|
||||
|
@ -309,7 +310,8 @@ airbrush_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
mode = INCREMENTAL;
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, SOFT);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -481,127 +481,4 @@ gimp_brush_pixmap_pixmap (GimpBrushPixmap *brush)
|
|||
return brush->pixmap_mask;
|
||||
}
|
||||
|
||||
void
|
||||
color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
int mode)
|
||||
{
|
||||
|
||||
PixelRegion destPR;
|
||||
void *pr;
|
||||
guchar *d;
|
||||
int ulx, uly, offsetx, offsety, y;
|
||||
GimpBrushPixmap *pixmap;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush));
|
||||
|
||||
pixmap = GIMP_BRUSH_PIXMAP (paint_core->brush);
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
pr = pixel_regions_register (1, &destPR);
|
||||
|
||||
/* Calculate upper left corner of brush as in
|
||||
* paint_core_get_paint_area. Ugly to have to do this here, too.
|
||||
*/
|
||||
|
||||
ulx = (int) paint_core->curx - (paint_core->brush->mask->width >> 1);
|
||||
uly = (int) paint_core->cury - (paint_core->brush->mask->height >> 1);
|
||||
|
||||
offsetx = area->x - ulx;
|
||||
offsety = area->y - uly;
|
||||
|
||||
for (; pr != NULL; pr = pixel_regions_process (pr))
|
||||
{
|
||||
d = destPR.data;
|
||||
for (y = 0; y < destPR.h; y++)
|
||||
{
|
||||
paint_line_pixmap_mask (dest, drawable, pixmap,
|
||||
d, offsetx, y + offsety,
|
||||
destPR.bytes, destPR.w, mode);
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_line_pixmap_mask (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
GimpBrushPixmap *brush,
|
||||
guchar *d,
|
||||
int x,
|
||||
int y,
|
||||
int bytes,
|
||||
int width,
|
||||
int mode)
|
||||
{
|
||||
guchar *b, *p;
|
||||
int x_index;
|
||||
gdouble alpha;
|
||||
gdouble factor = 0.00392156986; /* 1.0/255.0 */
|
||||
gint i;
|
||||
gint j;
|
||||
guchar *mask;
|
||||
|
||||
/* Make sure x, y are positive */
|
||||
while (x < 0)
|
||||
x += brush->pixmap_mask->width;
|
||||
while (y < 0)
|
||||
y += brush->pixmap_mask->height;
|
||||
|
||||
/* Point to the approriate scanline */
|
||||
b = temp_buf_data (brush->pixmap_mask) +
|
||||
(y % brush->pixmap_mask->height) * brush->pixmap_mask->width * brush->pixmap_mask->bytes;
|
||||
|
||||
/* ditto, except for the brush mask, so we can pre-multiply the alpha value */
|
||||
mask = temp_buf_data((brush->gbrush).mask) +
|
||||
(y % brush->pixmap_mask->height) * brush->pixmap_mask->width;
|
||||
|
||||
if(mode == SOFT)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % brush->pixmap_mask->width);
|
||||
p = b + x_index * brush->pixmap_mask->bytes;
|
||||
d[bytes-1] = mask[x_index];
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
if(alpha = d[bytes-1] * factor)
|
||||
{
|
||||
d[0] *= alpha;
|
||||
d[1] *= alpha;
|
||||
d[2] *= alpha;
|
||||
}
|
||||
/* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % brush->pixmap_mask->width);
|
||||
p = b + x_index * brush->pixmap_mask->bytes;
|
||||
d[bytes-1] = 255;
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -481,127 +481,4 @@ gimp_brush_pixmap_pixmap (GimpBrushPixmap *brush)
|
|||
return brush->pixmap_mask;
|
||||
}
|
||||
|
||||
void
|
||||
color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
int mode)
|
||||
{
|
||||
|
||||
PixelRegion destPR;
|
||||
void *pr;
|
||||
guchar *d;
|
||||
int ulx, uly, offsetx, offsety, y;
|
||||
GimpBrushPixmap *pixmap;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush));
|
||||
|
||||
pixmap = GIMP_BRUSH_PIXMAP (paint_core->brush);
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
pr = pixel_regions_register (1, &destPR);
|
||||
|
||||
/* Calculate upper left corner of brush as in
|
||||
* paint_core_get_paint_area. Ugly to have to do this here, too.
|
||||
*/
|
||||
|
||||
ulx = (int) paint_core->curx - (paint_core->brush->mask->width >> 1);
|
||||
uly = (int) paint_core->cury - (paint_core->brush->mask->height >> 1);
|
||||
|
||||
offsetx = area->x - ulx;
|
||||
offsety = area->y - uly;
|
||||
|
||||
for (; pr != NULL; pr = pixel_regions_process (pr))
|
||||
{
|
||||
d = destPR.data;
|
||||
for (y = 0; y < destPR.h; y++)
|
||||
{
|
||||
paint_line_pixmap_mask (dest, drawable, pixmap,
|
||||
d, offsetx, y + offsety,
|
||||
destPR.bytes, destPR.w, mode);
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_line_pixmap_mask (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
GimpBrushPixmap *brush,
|
||||
guchar *d,
|
||||
int x,
|
||||
int y,
|
||||
int bytes,
|
||||
int width,
|
||||
int mode)
|
||||
{
|
||||
guchar *b, *p;
|
||||
int x_index;
|
||||
gdouble alpha;
|
||||
gdouble factor = 0.00392156986; /* 1.0/255.0 */
|
||||
gint i;
|
||||
gint j;
|
||||
guchar *mask;
|
||||
|
||||
/* Make sure x, y are positive */
|
||||
while (x < 0)
|
||||
x += brush->pixmap_mask->width;
|
||||
while (y < 0)
|
||||
y += brush->pixmap_mask->height;
|
||||
|
||||
/* Point to the approriate scanline */
|
||||
b = temp_buf_data (brush->pixmap_mask) +
|
||||
(y % brush->pixmap_mask->height) * brush->pixmap_mask->width * brush->pixmap_mask->bytes;
|
||||
|
||||
/* ditto, except for the brush mask, so we can pre-multiply the alpha value */
|
||||
mask = temp_buf_data((brush->gbrush).mask) +
|
||||
(y % brush->pixmap_mask->height) * brush->pixmap_mask->width;
|
||||
|
||||
if(mode == SOFT)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % brush->pixmap_mask->width);
|
||||
p = b + x_index * brush->pixmap_mask->bytes;
|
||||
d[bytes-1] = mask[x_index];
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
if(alpha = d[bytes-1] * factor)
|
||||
{
|
||||
d[0] *= alpha;
|
||||
d[1] *= alpha;
|
||||
d[2] *= alpha;
|
||||
}
|
||||
/* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % brush->pixmap_mask->width);
|
||||
p = b + x_index * brush->pixmap_mask->bytes;
|
||||
d[bytes-1] = 255;
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,4 @@ GimpBrushPipe *gimp_brush_pixmap_load (char *filename);
|
|||
|
||||
TempBuf *gimp_brush_pixmap_pixmap (GimpBrushPixmap *);
|
||||
|
||||
void color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
int mode);
|
||||
|
||||
#endif /* __GIMPBRUSHPIPE_H__ */
|
||||
|
|
|
@ -481,127 +481,4 @@ gimp_brush_pixmap_pixmap (GimpBrushPixmap *brush)
|
|||
return brush->pixmap_mask;
|
||||
}
|
||||
|
||||
void
|
||||
color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
int mode)
|
||||
{
|
||||
|
||||
PixelRegion destPR;
|
||||
void *pr;
|
||||
guchar *d;
|
||||
int ulx, uly, offsetx, offsety, y;
|
||||
GimpBrushPixmap *pixmap;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush));
|
||||
|
||||
pixmap = GIMP_BRUSH_PIXMAP (paint_core->brush);
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
pr = pixel_regions_register (1, &destPR);
|
||||
|
||||
/* Calculate upper left corner of brush as in
|
||||
* paint_core_get_paint_area. Ugly to have to do this here, too.
|
||||
*/
|
||||
|
||||
ulx = (int) paint_core->curx - (paint_core->brush->mask->width >> 1);
|
||||
uly = (int) paint_core->cury - (paint_core->brush->mask->height >> 1);
|
||||
|
||||
offsetx = area->x - ulx;
|
||||
offsety = area->y - uly;
|
||||
|
||||
for (; pr != NULL; pr = pixel_regions_process (pr))
|
||||
{
|
||||
d = destPR.data;
|
||||
for (y = 0; y < destPR.h; y++)
|
||||
{
|
||||
paint_line_pixmap_mask (dest, drawable, pixmap,
|
||||
d, offsetx, y + offsety,
|
||||
destPR.bytes, destPR.w, mode);
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_line_pixmap_mask (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
GimpBrushPixmap *brush,
|
||||
guchar *d,
|
||||
int x,
|
||||
int y,
|
||||
int bytes,
|
||||
int width,
|
||||
int mode)
|
||||
{
|
||||
guchar *b, *p;
|
||||
int x_index;
|
||||
gdouble alpha;
|
||||
gdouble factor = 0.00392156986; /* 1.0/255.0 */
|
||||
gint i;
|
||||
gint j;
|
||||
guchar *mask;
|
||||
|
||||
/* Make sure x, y are positive */
|
||||
while (x < 0)
|
||||
x += brush->pixmap_mask->width;
|
||||
while (y < 0)
|
||||
y += brush->pixmap_mask->height;
|
||||
|
||||
/* Point to the approriate scanline */
|
||||
b = temp_buf_data (brush->pixmap_mask) +
|
||||
(y % brush->pixmap_mask->height) * brush->pixmap_mask->width * brush->pixmap_mask->bytes;
|
||||
|
||||
/* ditto, except for the brush mask, so we can pre-multiply the alpha value */
|
||||
mask = temp_buf_data((brush->gbrush).mask) +
|
||||
(y % brush->pixmap_mask->height) * brush->pixmap_mask->width;
|
||||
|
||||
if(mode == SOFT)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % brush->pixmap_mask->width);
|
||||
p = b + x_index * brush->pixmap_mask->bytes;
|
||||
d[bytes-1] = mask[x_index];
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
if(alpha = d[bytes-1] * factor)
|
||||
{
|
||||
d[0] *= alpha;
|
||||
d[1] *= alpha;
|
||||
d[2] *= alpha;
|
||||
}
|
||||
/* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % brush->pixmap_mask->width);
|
||||
p = b + x_index * brush->pixmap_mask->bytes;
|
||||
d[bytes-1] = 255;
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,4 @@ GimpBrushPipe *gimp_brush_pixmap_load (char *filename);
|
|||
|
||||
TempBuf *gimp_brush_pixmap_pixmap (GimpBrushPixmap *);
|
||||
|
||||
void color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
int mode);
|
||||
|
||||
#endif /* __GIMPBRUSHPIPE_H__ */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushlist.h"
|
||||
|
@ -309,7 +310,8 @@ airbrush_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
mode = INCREMENTAL;
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, SOFT);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -156,7 +156,8 @@ pencil_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
/* if its a pixmap, do pixmap stuff */
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, HARD);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, HARD);
|
||||
paint_appl_mode = INCREMENTAL;
|
||||
}
|
||||
else
|
||||
|
|
181
app/paint_core.c
181
app/paint_core.c
|
@ -29,6 +29,7 @@
|
|||
#include "gdisplay.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpbrushlist.h"
|
||||
#include "gimpbrushpipe.h"
|
||||
#include "gimprc.h"
|
||||
#include "gradient.h" /* for grad_get_color_at() */
|
||||
#include "paint_funcs.h"
|
||||
|
@ -61,6 +62,7 @@ static MaskBuf * paint_core_subsample_mask (MaskBuf *, double, double);
|
|||
static MaskBuf * paint_core_pressurize_mask (MaskBuf *, double, double, double);
|
||||
static MaskBuf * paint_core_solidify_mask (MaskBuf *);
|
||||
static MaskBuf * paint_core_scale_mask (MaskBuf *, gdouble);
|
||||
static MaskBuf * paint_core_scale_pixmap (MaskBuf *, gdouble);
|
||||
static MaskBuf * paint_core_get_brush_mask (PaintCore *, BrushApplicationMode, gdouble);
|
||||
static void paint_core_paste (PaintCore *, MaskBuf *,
|
||||
GimpDrawable *, int, int,
|
||||
|
@ -96,12 +98,17 @@ static TempBuf * canvas_buf = NULL;
|
|||
static MaskBuf * pressure_brush;
|
||||
static MaskBuf * solid_brush;
|
||||
static MaskBuf * scale_brush = NULL;
|
||||
static MaskBuf * scale_pixmap = NULL;
|
||||
static MaskBuf * kernel_brushes[5][5];
|
||||
|
||||
|
||||
/* paint buffers utility functions */
|
||||
static void free_paint_buffers (void);
|
||||
|
||||
/* brush pipe utility functions */
|
||||
static void paint_line_pixmap_mask (GImage *, GimpDrawable *,
|
||||
TempBuf *, TempBuf *, guchar *,
|
||||
int, int, int, int, int);
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
|
@ -1373,7 +1380,7 @@ paint_core_scale_mask (MaskBuf *brush_mask,
|
|||
paint_core_calculate_brush_size (brush_mask, scale,
|
||||
&dest_width, &dest_height);
|
||||
|
||||
if (brush_mask == last_brush &&
|
||||
if (brush_mask == last_brush && !cache_invalid &&
|
||||
dest_width == last_width && dest_height == last_height)
|
||||
return scale_brush;
|
||||
|
||||
|
@ -1390,6 +1397,41 @@ paint_core_scale_mask (MaskBuf *brush_mask,
|
|||
return scale_brush;
|
||||
}
|
||||
|
||||
static MaskBuf *
|
||||
paint_core_scale_pixmap (MaskBuf *brush_mask,
|
||||
gdouble scale)
|
||||
{
|
||||
static MaskBuf *last_brush = NULL;
|
||||
static gint last_width = 0.0;
|
||||
static gint last_height = 0.0;
|
||||
gint dest_width, dest_height;
|
||||
|
||||
if (scale == 0.0)
|
||||
return NULL;
|
||||
|
||||
if (scale == 1.0)
|
||||
return brush_mask;
|
||||
|
||||
paint_core_calculate_brush_size (brush_mask, scale,
|
||||
&dest_width, &dest_height);
|
||||
|
||||
if (brush_mask == last_brush && !cache_invalid &&
|
||||
dest_width == last_width && dest_height == last_height)
|
||||
return scale_pixmap;
|
||||
|
||||
if (scale_pixmap)
|
||||
mask_buf_free (scale_pixmap);
|
||||
|
||||
last_brush = brush_mask;
|
||||
last_width = dest_width;
|
||||
last_height = dest_height;
|
||||
|
||||
scale_pixmap = brush_scale_pixmap (brush_mask, dest_width, dest_height);
|
||||
cache_invalid = TRUE;
|
||||
|
||||
return scale_pixmap;
|
||||
}
|
||||
|
||||
static MaskBuf *
|
||||
paint_core_get_brush_mask (PaintCore *paint_core,
|
||||
BrushApplicationMode brush_hardness,
|
||||
|
@ -1818,3 +1860,140 @@ free_paint_buffers ()
|
|||
temp_buf_free (canvas_buf);
|
||||
canvas_buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/* Brush pipe utility functions */
|
||||
/**************************************************/
|
||||
|
||||
void
|
||||
paint_core_color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
gdouble scale,
|
||||
int mode)
|
||||
{
|
||||
|
||||
PixelRegion destPR;
|
||||
void *pr;
|
||||
guchar *d;
|
||||
int ulx, uly, offsetx, offsety, y;
|
||||
TempBuf *pixmap_mask;
|
||||
TempBuf *brush_mask;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush));
|
||||
|
||||
/* scale the brushes */
|
||||
pixmap_mask =
|
||||
paint_core_scale_pixmap (gimp_brush_pixmap_pixmap (GIMP_BRUSH_PIXMAP (paint_core->brush)), scale);
|
||||
if (mode == SOFT)
|
||||
brush_mask = paint_core_scale_mask (paint_core->brush->mask, scale);
|
||||
else
|
||||
brush_mask = NULL;
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
pr = pixel_regions_register (1, &destPR);
|
||||
|
||||
/* Calculate upper left corner of brush as in
|
||||
* paint_core_get_paint_area. Ugly to have to do this here, too.
|
||||
*/
|
||||
|
||||
ulx = (int) paint_core->curx - (pixmap_mask->width >> 1);
|
||||
uly = (int) paint_core->cury - (pixmap_mask->height >> 1);
|
||||
|
||||
offsetx = area->x - ulx;
|
||||
offsety = area->y - uly;
|
||||
|
||||
for (; pr != NULL; pr = pixel_regions_process (pr))
|
||||
{
|
||||
d = destPR.data;
|
||||
for (y = 0; y < destPR.h; y++)
|
||||
{
|
||||
paint_line_pixmap_mask (dest, drawable, pixmap_mask, brush_mask,
|
||||
d, offsetx, y + offsety,
|
||||
destPR.bytes, destPR.w, mode);
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_line_pixmap_mask (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *pixmap_mask,
|
||||
TempBuf *brush_mask,
|
||||
guchar *d,
|
||||
int x,
|
||||
int y,
|
||||
int bytes,
|
||||
int width,
|
||||
int mode)
|
||||
{
|
||||
guchar *b, *p;
|
||||
int x_index;
|
||||
gdouble alpha;
|
||||
gdouble factor = 0.00392156986; /* 1.0/255.0 */
|
||||
gint i;
|
||||
guchar *mask;
|
||||
|
||||
/* Make sure x, y are positive */
|
||||
while (x < 0)
|
||||
x += pixmap_mask->width;
|
||||
while (y < 0)
|
||||
y += pixmap_mask->height;
|
||||
|
||||
/* Point to the approriate scanline */
|
||||
b = temp_buf_data (pixmap_mask) +
|
||||
(y % pixmap_mask->height) * pixmap_mask->width * pixmap_mask->bytes;
|
||||
|
||||
if (mode == SOFT && brush_mask)
|
||||
{
|
||||
/* ditto, except for the brush mask, so we can pre-multiply the alpha value */
|
||||
mask = temp_buf_data (brush_mask) +
|
||||
(y % brush_mask->height) * brush_mask->width;
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % pixmap_mask->width);
|
||||
p = b + x_index * pixmap_mask->bytes;
|
||||
d[bytes-1] = mask[x_index];
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
alpha = d[bytes-1] * factor;
|
||||
if (alpha)
|
||||
{
|
||||
d[0] *= alpha;
|
||||
d[1] *= alpha;
|
||||
d[2] *= alpha;
|
||||
}
|
||||
/* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % pixmap_mask->width);
|
||||
p = b + x_index * pixmap_mask->bytes;
|
||||
d[bytes-1] = 255;
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,5 +143,8 @@ void paint_core_replace_canvas (PaintCore *,
|
|||
BrushApplicationMode,
|
||||
gdouble,
|
||||
PaintApplicationMode);
|
||||
void paint_core_color_area_with_pixmap (PaintCore *,
|
||||
GImage *, GimpDrawable *,
|
||||
TempBuf *, gdouble, int);
|
||||
|
||||
#endif /* __PAINT_CORE_H__ */
|
||||
|
|
|
@ -445,7 +445,8 @@ paintbrush_motion (PaintCore *paint_core,
|
|||
pixmap image into the are instead of the color */
|
||||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush) && !gradient_length)
|
||||
{
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, SOFT);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
paint_appl_mode = INCREMENTAL;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -156,7 +156,8 @@ pencil_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
/* if its a pixmap, do pixmap stuff */
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, HARD);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, HARD);
|
||||
paint_appl_mode = INCREMENTAL;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushlist.h"
|
||||
|
@ -309,7 +310,8 @@ airbrush_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
mode = INCREMENTAL;
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, SOFT);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushlist.h"
|
||||
|
@ -309,7 +310,8 @@ airbrush_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
mode = INCREMENTAL;
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, SOFT);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -156,7 +156,8 @@ pencil_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
/* if its a pixmap, do pixmap stuff */
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, HARD);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, HARD);
|
||||
paint_appl_mode = INCREMENTAL;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "gdisplay.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpbrushlist.h"
|
||||
#include "gimpbrushpipe.h"
|
||||
#include "gimprc.h"
|
||||
#include "gradient.h" /* for grad_get_color_at() */
|
||||
#include "paint_funcs.h"
|
||||
|
@ -61,6 +62,7 @@ static MaskBuf * paint_core_subsample_mask (MaskBuf *, double, double);
|
|||
static MaskBuf * paint_core_pressurize_mask (MaskBuf *, double, double, double);
|
||||
static MaskBuf * paint_core_solidify_mask (MaskBuf *);
|
||||
static MaskBuf * paint_core_scale_mask (MaskBuf *, gdouble);
|
||||
static MaskBuf * paint_core_scale_pixmap (MaskBuf *, gdouble);
|
||||
static MaskBuf * paint_core_get_brush_mask (PaintCore *, BrushApplicationMode, gdouble);
|
||||
static void paint_core_paste (PaintCore *, MaskBuf *,
|
||||
GimpDrawable *, int, int,
|
||||
|
@ -96,12 +98,17 @@ static TempBuf * canvas_buf = NULL;
|
|||
static MaskBuf * pressure_brush;
|
||||
static MaskBuf * solid_brush;
|
||||
static MaskBuf * scale_brush = NULL;
|
||||
static MaskBuf * scale_pixmap = NULL;
|
||||
static MaskBuf * kernel_brushes[5][5];
|
||||
|
||||
|
||||
/* paint buffers utility functions */
|
||||
static void free_paint_buffers (void);
|
||||
|
||||
/* brush pipe utility functions */
|
||||
static void paint_line_pixmap_mask (GImage *, GimpDrawable *,
|
||||
TempBuf *, TempBuf *, guchar *,
|
||||
int, int, int, int, int);
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
|
@ -1373,7 +1380,7 @@ paint_core_scale_mask (MaskBuf *brush_mask,
|
|||
paint_core_calculate_brush_size (brush_mask, scale,
|
||||
&dest_width, &dest_height);
|
||||
|
||||
if (brush_mask == last_brush &&
|
||||
if (brush_mask == last_brush && !cache_invalid &&
|
||||
dest_width == last_width && dest_height == last_height)
|
||||
return scale_brush;
|
||||
|
||||
|
@ -1390,6 +1397,41 @@ paint_core_scale_mask (MaskBuf *brush_mask,
|
|||
return scale_brush;
|
||||
}
|
||||
|
||||
static MaskBuf *
|
||||
paint_core_scale_pixmap (MaskBuf *brush_mask,
|
||||
gdouble scale)
|
||||
{
|
||||
static MaskBuf *last_brush = NULL;
|
||||
static gint last_width = 0.0;
|
||||
static gint last_height = 0.0;
|
||||
gint dest_width, dest_height;
|
||||
|
||||
if (scale == 0.0)
|
||||
return NULL;
|
||||
|
||||
if (scale == 1.0)
|
||||
return brush_mask;
|
||||
|
||||
paint_core_calculate_brush_size (brush_mask, scale,
|
||||
&dest_width, &dest_height);
|
||||
|
||||
if (brush_mask == last_brush && !cache_invalid &&
|
||||
dest_width == last_width && dest_height == last_height)
|
||||
return scale_pixmap;
|
||||
|
||||
if (scale_pixmap)
|
||||
mask_buf_free (scale_pixmap);
|
||||
|
||||
last_brush = brush_mask;
|
||||
last_width = dest_width;
|
||||
last_height = dest_height;
|
||||
|
||||
scale_pixmap = brush_scale_pixmap (brush_mask, dest_width, dest_height);
|
||||
cache_invalid = TRUE;
|
||||
|
||||
return scale_pixmap;
|
||||
}
|
||||
|
||||
static MaskBuf *
|
||||
paint_core_get_brush_mask (PaintCore *paint_core,
|
||||
BrushApplicationMode brush_hardness,
|
||||
|
@ -1818,3 +1860,140 @@ free_paint_buffers ()
|
|||
temp_buf_free (canvas_buf);
|
||||
canvas_buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/* Brush pipe utility functions */
|
||||
/**************************************************/
|
||||
|
||||
void
|
||||
paint_core_color_area_with_pixmap (PaintCore *paint_core,
|
||||
GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *area,
|
||||
gdouble scale,
|
||||
int mode)
|
||||
{
|
||||
|
||||
PixelRegion destPR;
|
||||
void *pr;
|
||||
guchar *d;
|
||||
int ulx, uly, offsetx, offsety, y;
|
||||
TempBuf *pixmap_mask;
|
||||
TempBuf *brush_mask;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush));
|
||||
|
||||
/* scale the brushes */
|
||||
pixmap_mask =
|
||||
paint_core_scale_pixmap (gimp_brush_pixmap_pixmap (GIMP_BRUSH_PIXMAP (paint_core->brush)), scale);
|
||||
if (mode == SOFT)
|
||||
brush_mask = paint_core_scale_mask (paint_core->brush->mask, scale);
|
||||
else
|
||||
brush_mask = NULL;
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
pr = pixel_regions_register (1, &destPR);
|
||||
|
||||
/* Calculate upper left corner of brush as in
|
||||
* paint_core_get_paint_area. Ugly to have to do this here, too.
|
||||
*/
|
||||
|
||||
ulx = (int) paint_core->curx - (pixmap_mask->width >> 1);
|
||||
uly = (int) paint_core->cury - (pixmap_mask->height >> 1);
|
||||
|
||||
offsetx = area->x - ulx;
|
||||
offsety = area->y - uly;
|
||||
|
||||
for (; pr != NULL; pr = pixel_regions_process (pr))
|
||||
{
|
||||
d = destPR.data;
|
||||
for (y = 0; y < destPR.h; y++)
|
||||
{
|
||||
paint_line_pixmap_mask (dest, drawable, pixmap_mask, brush_mask,
|
||||
d, offsetx, y + offsety,
|
||||
destPR.bytes, destPR.w, mode);
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_line_pixmap_mask (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
TempBuf *pixmap_mask,
|
||||
TempBuf *brush_mask,
|
||||
guchar *d,
|
||||
int x,
|
||||
int y,
|
||||
int bytes,
|
||||
int width,
|
||||
int mode)
|
||||
{
|
||||
guchar *b, *p;
|
||||
int x_index;
|
||||
gdouble alpha;
|
||||
gdouble factor = 0.00392156986; /* 1.0/255.0 */
|
||||
gint i;
|
||||
guchar *mask;
|
||||
|
||||
/* Make sure x, y are positive */
|
||||
while (x < 0)
|
||||
x += pixmap_mask->width;
|
||||
while (y < 0)
|
||||
y += pixmap_mask->height;
|
||||
|
||||
/* Point to the approriate scanline */
|
||||
b = temp_buf_data (pixmap_mask) +
|
||||
(y % pixmap_mask->height) * pixmap_mask->width * pixmap_mask->bytes;
|
||||
|
||||
if (mode == SOFT && brush_mask)
|
||||
{
|
||||
/* ditto, except for the brush mask, so we can pre-multiply the alpha value */
|
||||
mask = temp_buf_data (brush_mask) +
|
||||
(y % brush_mask->height) * brush_mask->width;
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % pixmap_mask->width);
|
||||
p = b + x_index * pixmap_mask->bytes;
|
||||
d[bytes-1] = mask[x_index];
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
alpha = d[bytes-1] * factor;
|
||||
if (alpha)
|
||||
{
|
||||
d[0] *= alpha;
|
||||
d[1] *= alpha;
|
||||
d[2] *= alpha;
|
||||
}
|
||||
/* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
/* attempt to avoid doing this calc twice in the loop */
|
||||
x_index = ((i + x) % pixmap_mask->width);
|
||||
p = b + x_index * pixmap_mask->bytes;
|
||||
d[bytes-1] = 255;
|
||||
|
||||
/* multiply alpha into the pixmap data */
|
||||
/* maybe we could do this at tool creation or brush switch time? */
|
||||
/* and compute it for the whole brush at once and cache it? */
|
||||
gimage_transform_color (dest, drawable, p, d, RGB);
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,5 +143,8 @@ void paint_core_replace_canvas (PaintCore *,
|
|||
BrushApplicationMode,
|
||||
gdouble,
|
||||
PaintApplicationMode);
|
||||
void paint_core_color_area_with_pixmap (PaintCore *,
|
||||
GImage *, GimpDrawable *,
|
||||
TempBuf *, gdouble, int);
|
||||
|
||||
#endif /* __PAINT_CORE_H__ */
|
||||
|
|
|
@ -445,7 +445,8 @@ paintbrush_motion (PaintCore *paint_core,
|
|||
pixmap image into the are instead of the color */
|
||||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush) && !gradient_length)
|
||||
{
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, SOFT);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
paint_appl_mode = INCREMENTAL;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -156,7 +156,8 @@ pencil_motion (PaintCore *paint_core,
|
|||
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
|
||||
{
|
||||
/* if its a pixmap, do pixmap stuff */
|
||||
color_area_with_pixmap (paint_core, gimage, drawable, area, HARD);
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, HARD);
|
||||
paint_appl_mode = INCREMENTAL;
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue